Fix bug where tracks were duplicated in queue position 0 during playlist refreshes by comparing items with URI or didl_id Fix race condition in internal queue playback where transient STOPPED states caused unwanted auto-advance - Updated sync_queue in interne.rs to use didl_id as fallback for URI comparison - Added items_match function in openhome.rs for robust item comparison - Modified lcs_flags in openhome.rs to use items_match for LCS algorithm - Added has_played_since_track_start flag in musicrenderer.rs to prevent auto-advance on transient STOPPED states - Updated play_* methods in musicrenderer.rs to reset the has_played flag before starting playback - Added diagnostic logs in sync_queue for tracking item matching issues
3.1 KiB
Rapport : Bug de duplication de piste en position 0
Résumé
Correction d'un bug où la piste en cours de lecture était dupliquée en position 0 de la queue après un certain temps.
Problème identifié
Symptôme
Lors de la lecture d'une playlist liée à une queue (OpenHome ou interne), après le passage à une nouvelle piste, celle-ci finissait par être dupliquée en première position de la queue.
Cause racine
La fonction sync_queue (utilisée lors des refreshes périodiques de playlist toutes les 60 secondes) comparait les items uniquement par leur URI. Si le MediaServer retournait une URI légèrement différente pour le même morceau (tokens de session, encodage différent, etc.), l'item courant n'était pas reconnu dans la nouvelle playlist et était préservé en position 0, créant ainsi une duplication.
Mécanisme détaillé
- Une playlist est attachée à un renderer
- La lecture commence sur la piste N
- Après 60 secondes, un refresh périodique déclenche
sync_queue sync_queuecompare l'URI de la piste courante avec les URIs de la playlist rafraîchie- Si les URIs ne correspondent pas exactement, la piste courante est considérée comme "absente" de la playlist
- La logique de préservation insère alors la piste courante en position 0
- Résultat : duplication de la piste
Solution appliquée
Modification de la logique de comparaison
La comparaison des items a été étendue pour utiliser l'URI OU le didl_id comme critère d'identification. Le didl_id est l'identifiant DIDL-Lite stable assigné par le MediaServer, indépendant de l'URI de streaming.
Fichiers modifiés
1. pmocontrol/src/queue/interne.rs
- Ajout de la comparaison par
didl_iden fallback danssync_queue - Ajout de logs de diagnostic pour tracer les cas de non-correspondance
// Avant
let new_idx = items.iter().position(|item| item.uri == current_uri);
// Après
let new_idx = items.iter().position(|item| item.uri == current_uri)
.or_else(|| items.iter().position(|item| item.didl_id == current_didl_id));
2. pmocontrol/src/queue/openhome.rs
- Ajout de la fonction
items_matchpour encapsuler la logique de comparaison - Modification de
sync_queuepour utiliser URI oudidl_id - Modification de
lcs_flags(algorithme LCS) pour utiliser la même logique de comparaison
fn items_match(a: &PlaybackItem, b: &PlaybackItem) -> bool {
a.uri == b.uri || a.didl_id == b.didl_id
}
Tests recommandés
- Attacher une playlist à un renderer OpenHome
- Lancer la lecture
- Attendre plusieurs cycles de refresh (> 60 secondes)
- Vérifier que la queue ne contient pas de duplications
- Cliquer sur différentes pistes et vérifier le même comportement
Diagnostic
Pour activer les logs de diagnostic :
RUST_LOG=pmocontrol::queue=debug
Les messages suivants permettent de tracer le comportement :
sync_queue: current item found in new playlist- Comportement normalsync_queue: current item NOT found in new playlist, preserving as first item- Cas problématique (ne devrait plus apparaître avec le fix)