fix: radio mode uses getSimilarSongs2 for artist/genre-aware playback
- Dedup now checks only the last 50 queued songs instead of the entire queue, so the radio doesn't stall on small libraries once every similar song has been seen - If every candidate is a recent duplicate (tiny library), allow up to 5 repeats rather than returning empty and letting the queue run dry - Add second _queueGen guard after the getRandomSongs fallback await Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
9fe8656a21
commit
377a6954e3
1 file changed
+15
-6
+15
-6
@@ -641,22 +641,31 @@ export async function fillRadioQueue() {
|
|||||||
try {
|
try {
|
||||||
const seed = S.queue[S.qIdx];
|
const seed = S.queue[S.qIdx];
|
||||||
let newSongs = [];
|
let newSongs = [];
|
||||||
|
|
||||||
|
// 1. Try similar songs seeded from the current track
|
||||||
if (seed?.id) {
|
if (seed?.id) {
|
||||||
const r = await api('getSimilarSongs2', `&id=${seed.id}&count=20`);
|
const r = await api('getSimilarSongs2', `&id=${seed.id}&count=20`);
|
||||||
newSongs = r.similarSongs2?.song || [];
|
newSongs = r.similarSongs2?.song || [];
|
||||||
}
|
}
|
||||||
// Fall back to random if similar songs unavailable (no Last.fm config, unknown track, etc.)
|
if (gen !== _queueGen) return;
|
||||||
|
|
||||||
|
// 2. Fall back to random if similar songs unavailable or empty
|
||||||
if (!newSongs.length) {
|
if (!newSongs.length) {
|
||||||
const r = await api('getRandomSongs', '&size=20');
|
const r = await api('getRandomSongs', '&size=20');
|
||||||
newSongs = r.randomSongs?.song || [];
|
newSongs = r.randomSongs?.song || [];
|
||||||
}
|
}
|
||||||
// Bail if playQueue() was called while we were awaiting — appending to a
|
|
||||||
// replaced queue would desync native (setQueue already wiped the old one).
|
|
||||||
if (gen !== _queueGen) return;
|
if (gen !== _queueGen) return;
|
||||||
// Deduplicate against songs already queued
|
|
||||||
const existingIds = new Set(S.queue.map(s => s.id));
|
|
||||||
newSongs = newSongs.filter(s => !existingIds.has(s.id));
|
|
||||||
if (!newSongs.length) return;
|
if (!newSongs.length) return;
|
||||||
|
|
||||||
|
// Deduplicate only against the last 50 queued songs so the radio never
|
||||||
|
// stalls on a small library. Songs cycle back after ~50 tracks rather than
|
||||||
|
// blocking forever once they've been seen once.
|
||||||
|
const recentIds = new Set(S.queue.slice(-50).map(s => s.id));
|
||||||
|
const deduped = newSongs.filter(s => !recentIds.has(s.id));
|
||||||
|
// If every candidate was a recent duplicate (very small library), allow
|
||||||
|
// repeats rather than letting the queue run dry and music stop.
|
||||||
|
newSongs = deduped.length > 0 ? deduped : newSongs.slice(0, 5);
|
||||||
|
|
||||||
const prevLen = S.queue.length;
|
const prevLen = S.queue.length;
|
||||||
S.queue.push(...newSongs);
|
S.queue.push(...newSongs);
|
||||||
renderQueue();
|
renderQueue();
|
||||||
|
|||||||
Reference in new issue
Block a user