mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-28 10:06:47 +00:00
9058abd340
Track is the app's normalized song model and QueueItemRef its thin queue identity -- consumed app-wide (queue, cover, context menus, sharing, lucky-mix, library browse), not a playback-internal detail. They lived in features/playback/store/playerStoreTypes, forcing ~115 core/feature files to reach into the playback feature for the central media type. Move the two interfaces to lib/media/trackTypes; playerStoreTypes keeps PlayerState and now imports them from lib. 115 importers repointed (mixed 'PlayerState, Track' lines split so PlayerState stays). Pure type move (erased at runtime). tsc 0, lint 0.
79 lines
2.7 KiB
TypeScript
79 lines
2.7 KiB
TypeScript
import type { QueueItemRef, Track } from '@/lib/media/trackTypes';
|
|
/**
|
|
* After a bulk enqueue (queue replace, append-many, lucky-mix) the runtime
|
|
* warms the loudness cache for the current track + the next N entries so
|
|
* the engine's `audio_chain_preload` sees a real cached gain instead of
|
|
* the startup trim. These helpers compute that window — both as a
|
|
* "does this id sit inside it?" predicate and as the explicit id list
|
|
* the prefetch loop iterates over.
|
|
*
|
|
* Pure functions of the state slice — no store imports, no side effects.
|
|
* The caller passes the queue + index + current track so the test surface
|
|
* stays trivial and there's no top-level coupling back to playerStore.
|
|
*/
|
|
export const LOUDNESS_BACKFILL_WINDOW_AHEAD = 5;
|
|
|
|
export function isTrackInsideLoudnessBackfillWindow(
|
|
trackId: string,
|
|
queue: QueueItemRef[],
|
|
queueIndex: number,
|
|
currentTrack: Track | null,
|
|
): boolean {
|
|
if (!trackId) return false;
|
|
if (currentTrack?.id === trackId) return true;
|
|
if (queue.length === 0) return false;
|
|
const start = Math.max(0, queueIndex + 1);
|
|
const end = Math.min(queue.length, start + LOUDNESS_BACKFILL_WINDOW_AHEAD);
|
|
for (let i = start; i < end; i++) {
|
|
if (queue[i]?.trackId === trackId) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function collectLoudnessBackfillWindowTrackIds(
|
|
queue: QueueItemRef[],
|
|
queueIndex: number,
|
|
currentTrack: Track | null,
|
|
): string[] {
|
|
const ids = new Set<string>();
|
|
if (currentTrack?.id) ids.add(currentTrack.id);
|
|
const start = Math.max(0, queueIndex + 1);
|
|
const end = Math.min(queue.length, start + LOUDNESS_BACKFILL_WINDOW_AHEAD);
|
|
for (let i = start; i < end; i++) {
|
|
const tid = queue[i]?.trackId;
|
|
if (tid) ids.add(tid);
|
|
}
|
|
return Array.from(ids);
|
|
}
|
|
|
|
/** Next ~5 queue neighbours for middle-tier analysis priority hints. */
|
|
export function collectPlaybackMiddlePriorityTrackIds(
|
|
queue: QueueItemRef[],
|
|
queueIndex: number,
|
|
currentTrack: Track | null,
|
|
): string[] {
|
|
const ids = new Set<string>();
|
|
const start = Math.max(0, queueIndex + 1);
|
|
const end = Math.min(queue.length, start + LOUDNESS_BACKFILL_WINDOW_AHEAD);
|
|
for (let i = start; i < end; i++) {
|
|
const tid = queue[i]?.trackId;
|
|
if (tid && tid !== currentTrack?.id) ids.add(tid);
|
|
}
|
|
return Array.from(ids);
|
|
}
|
|
|
|
export function loudnessBackfillPriorityForTrack(
|
|
trackId: string,
|
|
queue: QueueItemRef[],
|
|
queueIndex: number,
|
|
currentTrack: Track | null,
|
|
): 'high' | 'middle' | 'low' {
|
|
if (currentTrack?.id === trackId) return 'high';
|
|
const start = Math.max(0, queueIndex + 1);
|
|
const end = Math.min(queue.length, start + LOUDNESS_BACKFILL_WINDOW_AHEAD);
|
|
for (let i = start; i < end; i++) {
|
|
if (queue[i]?.trackId === trackId) return 'middle';
|
|
}
|
|
return 'low';
|
|
}
|