9.9 KiB
Player Générique PMO Music
Vue d'ensemble
Ce document décrit l'implémentation d'un nouveau player web générique qui utilise uniquement l'API du trait pmosource sans dépendre d'aucune implémentation spécifique (comme pmoparadise).
Objectifs
L'objectif principal est de tester l'API pmosource dans un cas d'application concret afin d'identifier ce qui manque ou pourrait être amélioré dans l'API générique.
Architecture
1. Service API TypeScript (pmoapp/webapp/src/services/pmosource.ts)
Service qui encapsule toutes les interactions avec l'API REST de pmosource :
// Endpoints utilisés
GET /api/sources // Liste les sources
GET /api/sources/{id} // Info sur une source
GET /api/sources/{id}/root // Container racine
GET /api/sources/{id}/browse // Parcourt un container
GET /api/sources/{id}/resolve // Résout l'URI d'un item
GET /api/sources/{id}/image // Image de la source
GET /api/sources/{id}/capabilities // Capacités de la source
Fonctions implémentées :
listSources()- Liste toutes les sources enregistréesgetSource(id)- Récupère une source spécifiquegetSourceRoot(id)- Récupère le container racinebrowseSource(id, objectId?, pagination?)- Navigation dans les containersresolveUri(sourceId, objectId)- Résout l'URI de streaminggetSourceImageUrl(id)- URL de l'image de la source
2. Composant Player (pmoapp/webapp/src/components/GenericMusicPlayer.vue)
Composant Vue.js qui implémente :
Fonctionnalités implémentées
-
Sélection de sources
- Affichage de toutes les sources disponibles
- Affichage du logo de chaque source
- Affichage des capacités (FIFO, Search, Favorites)
-
Navigation dans les containers
- Breadcrumb pour remonter dans la hiérarchie
- Affichage des sous-containers (dossiers)
- Navigation par clic dans les containers
-
Liste des morceaux
- Affichage de tous les items audio d'un container
- Métadonnées : titre, artiste, album, cover art
- Numérotation des morceaux
-
Lecteur audio
- Lecture d'un morceau via résolution d'URI
- Contrôles audio natifs HTML5
- Section "Now Playing" avec métadonnées
- Gestion des erreurs de lecture
-
Interface utilisateur
- Design moderne avec dégradés et animations
- Responsive design
- Indicateurs visuels (morceau actif, en cours de lecture)
- Messages d'erreur clairs
3. Intégration
Le player a été configuré comme page d'accueil par défaut de l'application web PMO :
// router/index.ts
const routes = [
{ path: "/", name: "home", component: GenericMusicPlayer },
// ... autres routes
]
Ce qui fonctionne
✅ Complètement fonctionnel avec l'API actuelle de pmosource :
- Découverte des sources disponibles
- Navigation complète dans la hiérarchie des containers
- Affichage des métadonnées des morceaux
- Résolution des URIs et lecture audio
- Affichage des images de sources
- Métadonnées temps réel via Server-Sent Events (SSE) 🆕
- Mise à jour automatique toutes les 3 secondes
- Pas de polling, push serveur
- Reconnexion automatique
Limitations identifiées et améliorations possibles
1. Métadonnées de couverture d'album
Problème : Le trait MusicSource n'expose pas directement de méthode pour résoudre les URIs de couvertures d'album.
État actuel :
- Le champ
album_artdansItemcontient parfois une URI - Le champ
album_art_pkcontient une clé primaire mais pas d'URL exploitable directement - Certaines implémentations (pmoparadise) utilisent
/cache/cover/{pk}mais ce n'est pas standardisé
Proposition :
/// Résout l'URI de la couverture d'album pour un item
async fn resolve_cover_uri(&self, object_id: &str) -> Result<Option<String>>;
2. Recherche globale
Problème : La méthode search() existe mais retourne SearchNotSupported par défaut.
État actuel :
- Pas d'interface standardisée pour la recherche dans l'UI
- Pas de retour clair sur les capacités de recherche
Proposition :
- Utiliser
capabilities().supports_searchpour afficher/masquer l'UI de recherche - Documenter clairement le format attendu des requêtes de recherche
3. Pagination
Problème : L'API supporte la pagination mais les métadonnées ne permettent pas de connaître le nombre total d'items.
État actuel :
BrowseResponse.totalretourne le nombre d'items retournés, pas le total disponible- Pas de méthode
get_total_count(object_id)dans le trait
Proposition :
/// Retourne le nombre total d'items dans un container
async fn get_total_count(&self, object_id: &str) -> Result<usize>;
Ou ajouter total_available dans BrowseResponse :
pub struct SourceBrowseResponse {
// ... champs existants
pub total_available: Option<usize>, // Total disponible (pas juste retourné)
}
4. Métadonnées de stream en temps réel ✅ IMPLÉMENTÉ
Solution implémentée :
- ✅ Méthode
get_item(object_id)dans le traitMusicSource - ✅ Endpoint REST
GET /api/sources/{id}/item?object_id={id}pour récupérer les métadonnées d'un item - ✅ Endpoint SSE
GET /api/sources/{id}/item/stream?object_id={id}pour recevoir les mises à jour en temps réel - ✅ Le player web utilise Server-Sent Events (SSE) pour les métadonnées temps réel
Comment ça fonctionne :
- Le serveur envoie automatiquement les métadonnées à jour toutes les 3 secondes via SSE
- Le client se connecte avec
EventSource(API browser native) - Les métadonnées sont automatiquement mises à jour dans l'interface sans polling
Pour RadioParadise :
- La méthode
get_item()pour les live streams récupère les métadonnées depuis/radioparadise/metadata/{slug} - Le SSE permet d'avoir les métadonnées à jour en moins de 3 secondes (au lieu de 10 secondes avec le polling)
5. Playlists utilisateur
Problème : Les méthodes existent (get_user_playlists(), add_to_playlist()) mais retournent NotSupported par défaut.
État actuel :
- Pas encore testé dans le player
- Nécessiterait une UI dédiée
Proposition :
- Créer une section "Playlists" dans le player
- Tester l'API avec une implémentation qui supporte les playlists (ex: Qobuz)
6. Favoris
Problème : Similaire aux playlists, l'API existe mais n'est pas testée.
Proposition :
- Ajouter un bouton "⭐ Favoris" sur chaque morceau
- Afficher visuellement les morceaux favoris
- Créer une section "Mes Favoris"
7. Auto-play / Queue
Problème : Il n'y a pas de méthode pour gérer une file d'attente de lecture.
Proposition :
/// Interface pour gérer une queue de lecture
pub trait Playable: MusicSource {
async fn get_next_track(&self) -> Result<Option<Item>>;
async fn get_previous_track(&self) -> Result<Option<Item>>;
async fn add_to_queue(&self, item: Item) -> Result<()>;
async fn clear_queue(&self) -> Result<()>;
async fn get_queue(&self) -> Result<Vec<Item>>;
}
8. Durée totale d'un container
Problème : Pour afficher "Album: 45:32 min, 12 morceaux", il faut parcourir tous les items.
Proposition :
/// Statistiques d'un container spécifique
async fn get_container_stats(&self, object_id: &str) -> Result<ContainerStats>;
pub struct ContainerStats {
pub item_count: usize,
pub total_duration_ms: Option<u64>,
pub total_size_bytes: Option<u64>,
}
9. Formats audio disponibles
Problème : La méthode get_available_formats() existe mais n'est pas exploitée dans l'UI.
Proposition :
- Ajouter un sélecteur de qualité dans le player
- Afficher les formats disponibles (FLAC 24/96, MP3 320, etc.)
10. État du cache
Problème : Les méthodes existent (get_cache_status(), cache_item()) mais ne sont pas intégrées.
Proposition :
- Afficher un indicateur de cache sur chaque morceau
- Bouton "📥 Télécharger" pour mettre en cache
- Barre de progression pour le téléchargement
Prochaines étapes
Court terme
- ✅ Tester le player avec
pmoparadise(déjà implémenté) - 🔄 Identifier les bugs et limitations pratiques
- 🔄 Tester avec une deuxième source (ex:
pmoqobuz) pour valider la généricité
Moyen terme
- Implémenter les fonctionnalités manquantes identifiées ci-dessus
- Ajouter la gestion de queue et auto-play
- Ajouter la recherche si supportée
- Intégrer la gestion du cache
Long terme
- Support des playlists utilisateur
- Support des favoris
- Égaliseur et effets audio
- Visualisations audio
- Mode hors-ligne avec cache
Conclusion
Le player générique démontre que l'API pmosource est déjà très utilisable pour créer une application musicale fonctionnelle. Les principales limitations concernent :
- Les métadonnées de couvertures (pas d'URL standardisée)
- La pagination avancée (pas de compte total)
- Les métadonnées temps réel (pour les streams live)
- La gestion de queue (pas d'API dédiée)
Ces limitations ne sont pas bloquantes mais leur résolution améliorerait significativement l'expérience utilisateur et la complétude de l'API.
Utilisation
Pour tester le player :
-
Lancer le serveur backend avec au moins une source enregistrée :
cargo run --example single_channel_server --features full -
Accéder à l'application web :
http://localhost:8080/app/ -
Le player devrait afficher automatiquement les sources disponibles et permettre la navigation et la lecture.
Remarques importantes
- ✅ Le player n'utilise QUE l'API pmosource générique
- ✅ Aucune dépendance sur
pmoparadiseou toute autre implémentation spécifique - ✅ Tout est basé sur les endpoints REST de
pmosource::api - ✅ Le code est totalement réutilisable pour toute nouvelle source (Qobuz, Spotify, etc.)