Replace single-page browse with paginated loop to handle playlists exceeding BROWSE_PAGE_SIZE (64 items). Each page is fetched with retry logic, and entries are accumulated until fewer than BROWSE_PAGE_SIZE items are returned, ensuring complete playlist refresh.
deps: update esbuild to 0.27.4, rollup to 4.60.0, vite to 7.3.1
- bump esbuild and all platform-specific binaries from 0.25.10 to 0.27.4
- bump rollup and all platform-specific binaries from 4.52.3 to 4.60.0
- bump vite from 7.1.7 to 7.3.1 (esbuild peer dep updated to ^0.27.0)
- bump dompurify from 3.2.7 to 3.3.3
web: improve cover image retry logic
- increase maxRetries default from 3 to 5
- reduce initial retryDelay from 1000ms to 500ms
- implement exponential backoff: delay = retryDelay * 2^(retryCount - 1)
- add detailed logging for retries and final failure
rust: minor cleanup
- remove unused imports (watch, Url, AudioSegment, SyncMarker)
- add tracing debug logs for cache file requests
- handle missing files gracefully with warning + client retry hint
- add #[allow(async_fn_in_trait)] where needed
Cette modification implémente un système de playback gapless pour les renderers web, permettant une transition fluide entre les pistes. Le changement inclut l'ajout d'un moteur audio qui utilise deux éléments <audio> en ping-pong connectés à un AudioContext pour le contrôle du volume/mute et le contrôle du flux gapless. Les commandes UPnP ont été mises à jour pour gérer le préchargement des pistes suivantes via SetNextAVTransportURI. Le backend a été modifié pour gérer les transitions gapless et précharger les pistes suivantes. Des ajustements ont également été apportés au serveur pour permettre les requêtes CORS nécessaires à ce fonctionnement.
Ajout d'une nouvelle propriété `is_continuous_stream` pour identifier les flux continus (radio, stream) plutôt que les fichiers avec durée fixe.
- Ajout de la propriété `is_continuous_stream` dans `TrackMetadata`
- Implémentation de la détection dans plusieurs fichiers : control_point.rs, media_server.rs, music_renderer/watcher.rs et openhome_client.rs
- Utilisation de la fonction `is_continuous_stream_url` pour déterminer si l'URI correspond à un flux continu
Implémentation complète de l'étape 2 : ajout d'un indicateur visuel "Web Radio" dans l'interface web pour signaler la lecture d'un flux continu. Cet indicateur s'affiche à côté de l'indicateur "Attachée à une playlist" dans le composant QueueViewer.
Changements principaux :
- Ajout du champ `is_stream` dans `FullRendererSnapshot` pour transmettre l'état du flux au frontend
- Intégration de l'indicateur visuel dans `QueueViewer.vue` avec l'icône Radio
- Gestion de l'événement `stream_state_changed` dans le composant `useRenderers.ts`
- Mise à jour des types TypeScript pour inclure le nouveau champ `is_stream`
- Refactorisation de `sse.rs` pour éliminer la duplication de code
Cette fonctionnalité permet aux utilisateurs de savoir rapidement si la lecture en cours est un flux continu (webradio) ou un fichier audio traditionnel.
Cette mise à jour ajoute la gestion de la durée dans les métadonnées UPnP et OpenHome. Les changements incluent :
- Ajout de la dépendance `pmoutils` dans `pmocontrol`
- Mise à jour du modèle `Item` pour inclure le champ `duration`
- Implémentation de la sérialisation DIDL-Lite avec `pmodidl` et `pmoutils`
- Ajout de la gestion de la durée dans les renderers UPnP et OpenHome
- Extraction de la durée depuis les métadonnées DIDL-Lite
- Support du fallback vers la durée du DIDL lorsque l'ampli ne la retourne pas
- Mise à jour des constructeurs d'items pour inclure la durée calculée pour les streams radio
Ces modifications permettent une meilleure gestion des durées de pistes audio, notamment pour les streams radio avec des durées calculées à partir des timestamps de début/fin.
Fix backend mutex poisoned panic when stopping playback on OpenHome renderer
This commit addresses a panic that occurred when stopping playback on OpenHome renderers, which was caused by:
1. Mutex poisoning from unhandled panics in backend operations
2. A regression revealed after initial fixes, where inconsistent renderer state caused index out of bounds errors
Changes include:
- Added defensive error handling for mutex operations to prevent poisoning
- Implemented bounds-checking for current_index in sync_queue to handle inconsistent renderer states
- Removed redundant clear_queue calls that were causing additional failures
- Improved error tolerance in queue operations
The fix ensures that the backend mutex remains healthy and that inconsistent renderer states are handled gracefully rather than causing panics.
Le transfert de la queue de lecture entre renderers était corrompu car le binding de playlist était réinitialisé, effaçant les items transférés. Correction en transférant directement le binding sans déclencher de rafraîchissement, préservant ainsi le current_index et la position de lecture.
- Fichiers modifiés : pmocontrol/src/control_point.rs
- Version mise à jour : 0.3.7
Cette modification refactorise l'architecture pour que chaque `MusicRenderer` gère son propre thread de surveillance (watcher), au lieu de déléguer le polling au `ControlPoint` centralisé.
- Ajout d'un module `watcher.rs` avec `WatchStrategy`, `WatchedState` et fonctions helper
- Implémentation de `start_watching()` et `stop_watching()` dans `MusicRenderer`
- Centralisation de la gestion du watcher dans le constructeur et les méthodes `has_been_seen_now()`/`mark_as_offline()`
- Suppression du polling central (~140 lignes) dans `control_point.rs`
- Simplification du `registry.rs` avec suppression des appels manuels `start/stop_watching()`
- Correction du bug dans `refresh_device_presence()` pour le traitement offline→online
- Préparation pour le support futur des notifications push (OpenHome, Chromecast)
L'architecture est maintenant plus robuste avec une meilleure encapsulation, cohérence des événements et une gestion automatique du watcher.
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.
Version bump for PMOMusic from 0.3.1 to 0.3.3
- Updated snapshot update logic in useRenderers.ts to directly update local snapshot state based on event types
- Improved handling of various events like state_changed, position_changed, volume_changed, etc.
- Adjusted polling interval in control_point.rs from 500ms to 250ms for smoother UI updates
Réduction du délai de rafraîchissement des conteneurs à 2 secondes et ajustement du polling pour une meilleure réactivité de l'interface utilisateur.
- Modification du délai de cooldown de 5 secondes à 2 secondes dans MediaBrowser.vue
- Réduction du délai de polling de 60 secondes à 10 secondes pour la découverte des appareils dans control_point.rs
- Modification du polling de volume et de mute de 3 secondes à 1 seconde (tous les 2 ticks à 500ms) dans control_point.rs
- Réduction du délai de polling de position de 1 seconde à 500ms dans control_point.rs
This commit adds validation to ensure that the playback position does not exceed the track duration. When the position is greater than the duration (which can happen during track initialization on some UPNP renderers), the position is set to None to avoid displaying bogus timestamps. This improves the robustness of playback position handling.
Mark user-requested stops to prevent auto-advance when sleep timer expires. This ensures that playback stops cleanly without triggering automatic advancement to the next item.
This commit refactors queue management and transport control to use a unified approach across all renderer backends (UPnP, OpenHome, Arylic TCP, Chromecast, LinkPlay). Key changes include:
1. Introduces `RendererBackend` and `QueueTransportControl` traits to provide consistent queue access and transport control operations
2. Moves queue management from the `MusicRenderer` struct to individual backend implementations
3. Implements `play_from_queue`, `play_next`, `play_previous`, and `play_from_index` methods in all backends
4. Simplifies `MusicRenderer` methods to delegate to backend-specific implementations
5. Removes direct queue access methods from `MusicRenderer` and centralizes queue operations in backend traits
6. Updates all backend implementations (UPnP, OpenHome, Arylic TCP, Chromecast, LinkPlay) to implement the new queue transport control traits
This change provides a more consistent and maintainable way to handle queue operations across different renderer types, ensuring that queue management and playback navigation work uniformly regardless of the underlying backend.
Ajout de la fonctionnalité de sleep timer pour les renderers audio.
- Création du composant TimerControl.vue avec interface utilisateur interactive
- Implémentation des API endpoints pour gérer le sleep timer (start, update, cancel, get)
- Intégration du système de timer dans le control point avec surveillance par thread dédié
- Ajout de la logique de timer dans les renderers (sleep_timer.rs)
- Mise à jour des types et événements SSE pour le sleep timer
- Intégration du timer dans la barre de bas de l'application
Cette fonctionnalité permet aux utilisateurs de configurer un timer qui arrêtera automatiquement la lecture après une durée définie, avec une interface intuitive et des notifications en temps réel.
This commit ensures unified playback behavior across all backends by automatically playing the current track from the queue when available. It also detaches playlist bindings from source renderers during control point operations, improving consistency and reliability of music playback transitions.
Implémentation complète de la fonctionnalité de transfert de queue entre renderers :
- Ajout d'une nouvelle API POST /renderers/{id}/queue/transfer
- Intégration dans le backend avec la méthode transfer_queue dans ControlPoint
- Mise à jour des structures de données pour inclure l'ID de playlist dans les snapshots
- Ajout d'une interface utilisateur dans RendererDrawer avec menu déroulant pour le transfert
- Gestion des écouteurs d'événements pour fermer le menu en dehors
- Support du transfert de la queue avec préservation de la playlist binding
- Ajout de tests et documentation OpenAPI
Ajout d'un menu déroulant avec les actions 'Ajouter à la queue' et 'Ajouter après' pour les éléments dans le ServerDrawer.
- Remplacement des fonctions handlePlayItem et handleQueueItem par des fonctions plus spécifiques (handlePlayItem, handleAddToQueue, handleAddAfterCurrent)
- Ajout d'une gestion du menu déroulant avec ouverture/fermeture
- Intégration du composant useRenderers pour les actions de lecture
- Mise à jour des styles pour le menu déroulant avec animations
- Correction de l'alignement du backdrop sur mobile
- Amélioration des transitions et animations du drawer
- Ajout de la fonction addAfterCurrent dans l'API et le control point
- Support de l'ajout d'éléments après le morceau actuel dans les queues