Ajout de la fonctionnalité de shuffle pour mélanger l'ordre des morceaux dans la queue de lecture.
- Implémentation de la méthode shuffle_queue() dans MusicRenderer
- Ajout de l'endpoint REST /api/control/renderers/{renderer_id}/queue/shuffle
- Intégration du bouton shuffle dans l'interface Vue.js
- Centralisation des émissions d'événements SSE dans le MusicRenderer
- Mise à jour de la documentation OpenAPI
Cette fonctionnalité permet de randomiser l'ordre des morceaux dans la queue et de redémarrer la lecture depuis le premier morceau, tout en améliorant l'architecture en centralisant les émissions d'événements.
6.9 KiB
Rapport Final : Implémentation du Shuffle de la Queue de Lecture
Résumé
Implémentation complète de la fonctionnalité de shuffle (mélange aléatoire) de la queue de lecture pour les Music Renderers dans PMOMusic. Cette fonctionnalité permet de randomiser l'ordre des morceaux dans la queue et de redémarrer la lecture depuis le premier morceau.
Au-delà de la fonctionnalité shuffle, ce travail a permis d'améliorer l'architecture en centralisant l'émission des événements SSE dans le MusicRenderer plutôt que dans le ControlPoint.
Travail effectué
Étape 1 : Implémentation de la méthode shuffle dans MusicRenderer
Fichier modifié : pmocontrol/src/music_renderer/musicrenderer.rs
Ajout de la méthode shuffle_queue() qui implémente la stratégie suivante :
- Détache la queue de lecture d'une playlist si celle-ci est attachée
- Arrête la lecture en cours
- Prend un snapshot de la queue actuelle
- Randomise l'ordre des morceaux avec
rand::seq::SliceRandom - Remplace la queue avec les items mélangés
- Redémarre la lecture au premier morceau
Dépendances ajoutées :
rand = "0.9"dansCargo.toml(workspace)rand = { workspace = true }danspmocontrol/Cargo.toml
Étape 2 : API REST et documentation OpenAPI
Fichiers modifiés :
pmocontrol/src/pmoserver_ext.rs: Ajout du handlershuffle_queuepmocontrol/src/openapi.rs: Ajout du path dans la documentation OpenAPI
Endpoint créé :
POST /api/control/renderers/{renderer_id}/queue/shuffle
Réponses :
200: Queue mélangée et lecture démarrée400: Queue vide404: Renderer non trouvé504: Timeout de la commande500: Erreur interne
Étape 3 : Interface Vue.js
Fichiers créés :
pmoapp/webapp/src/components/pmocontrol/ShuffleControl.vue: Nouveau composant bouton shuffle
Fichiers modifiés :
pmoapp/webapp/src/services/pmocontrol/api.ts: Ajout de la méthodeshuffleQueue()pmoapp/webapp/src/components/unified/BottomTabBar.vue: Intégration du bouton shuffle à côté du timer
Design :
- Bouton circulaire avec icône Shuffle (lucide-vue-next)
- Style cohérent avec le bouton Timer existant
- Animation de chargement pendant l'exécution
- Responsive (taille réduite sur mobile)
Étape 4 : Émission automatique des événements SSE (Round 3)
Problème identifié : L'interface utilisateur ne se mettait pas à jour après un shuffle car aucun événement QueueUpdated n'était émis.
Solution implémentée : Le MusicRenderer stocke maintenant une référence optionnelle au RendererEventBus et émet automatiquement un événement QueueUpdated après chaque modification de la queue.
Fichiers modifiés :
| Fichier | Modification |
|---|---|
pmocontrol/src/music_renderer/musicrenderer.rs |
Ajout du champ event_bus: Option<RendererEventBus>, constructeur from_renderer_info_with_bus(), méthode helper emit_queue_updated(), implémentation manuelle de Debug |
pmocontrol/src/registry.rs |
Passage du RendererEventBus lors de la création des renderers via from_renderer_info_with_bus() |
Méthodes qui émettent désormais QueueUpdated :
enqueue_items()- Ajout d'items à la queuesync_queue()- Synchronisation de la queueclear_queue()- Vidage de la queuereplace_queue()- Remplacement complet de la queue (utilisé parshuffle_queue())play_next_from_queue()- Passage au morceau suivantplay_from_index()- Lecture à un index spécifique
Étape 5 : Refactoring des émissions d'événements (Round 4)
Objectif : Centraliser les émissions d'événements dans le MusicRenderer et supprimer les émissions redondantes du ControlPoint.
Principe : Puisque le MusicRenderer a maintenant accès au RendererEventBus, il est plus cohérent et maintenable que les événements soient émis au niveau du renderer plutôt que dispersés dans le ControlPoint.
Événements QueueUpdated
Modifications dans ControlPoint - Suppression des émissions redondantes dans :
clear_queue()enqueue_items_with_mode()shuffle_queue()play_next_from_queue()
Événements BindingChanged
Modifications dans MusicRenderer :
set_playlist_binding(): ÉmetBindingChangeduniquement si le binding change réellementclear_playlist_binding(): ÉmetBindingChangeduniquement s'il y avait un binding à supprimer- Ajout de la méthode helper
emit_binding_changed()
Modifications dans ControlPoint :
attach_queue_to_playlist_internal(): Suppression de l'émission manuelle deBindingChangeddetach_playlist_binding(): Suppression de l'émission manuelle, utilisation declear_playlist_binding()au lieu deset_playlist_binding(None)
Liste complète des fichiers modifiés
| Fichier | Type de modification |
|---|---|
Cargo.toml (workspace) |
Ajout dépendance rand |
pmocontrol/Cargo.toml |
Ajout dépendance rand |
pmocontrol/src/music_renderer/musicrenderer.rs |
Ajout shuffle_queue(), event_bus, émission d'événements automatique |
pmocontrol/src/control_point.rs |
Suppression des émissions d'événements redondantes |
pmocontrol/src/registry.rs |
Passage du RendererEventBus lors de la création des renderers |
pmocontrol/src/pmoserver_ext.rs |
Ajout handler REST shuffle_queue |
pmocontrol/src/openapi.rs |
Ajout documentation OpenAPI |
pmoapp/webapp/src/services/pmocontrol/api.ts |
Ajout méthode API shuffleQueue() |
pmoapp/webapp/src/components/unified/BottomTabBar.vue |
Intégration du bouton shuffle |
Fichiers créés
| Fichier | Description |
|---|---|
pmoapp/webapp/src/components/pmocontrol/ShuffleControl.vue |
Composant Vue.js du bouton shuffle |
Notes techniques
- La méthode
shuffle_queuedétache automatiquement la playlist liée pour éviter que la queue soit écrasée par une mise à jour de la playlist - Le shuffle utilise
rand::thread_rng()pour une génération aléatoire de qualité - L'endpoint REST utilise le même pattern async que les autres commandes de transport (spawn_blocking + timeout)
- Le timeout utilisé est
QUEUE_COMMAND_TIMEOUT(10 secondes) - L'émission des événements SSE est automatique via le
RendererEventBusintégré auMusicRenderer - L'implémentation manuelle de
DebugpourMusicRendererest nécessaire carRendererEventBusn'implémente pasDebug - Les événements ne sont émis que lorsqu'il y a un changement effectif (pas d'événement
BindingChangedsi le binding était déjàNone)
Améliorations architecturales
Ce travail a posé les bases d'une meilleure architecture où le MusicRenderer est responsable de l'émission de ses propres événements. Une tâche de suivi a été créée (Blackboard/Todo/stateful_music_renderer.md) pour aller plus loin et rendre le MusicRenderer complètement stateful avec son propre thread de surveillance.