Commit Graph

954 Commits

Author SHA1 Message Date
0d4cf3cdae Merge pull request 'push-ltynmtvvsnkt' (#100) from push-ltynmtvvsnkt into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m33s
Reviewed-on: #100
2026-06-11 11:15:31 +02:00
bcfffa6df8 feat: implement batch track loading via track/getList endpoint
Replaces sequential track requests with a chunked batch enrichment workflow using MD5-signed POST requests (50-ID windows). Introduces cache-first fetching, order preservation via HashMap lookups, and graceful fallbacks for playlist and favorite loading.
2026-06-11 11:07:09 +02:00
e670e8e0d8 feat: enhance Qobuz bundle extraction with caching and retry logic
Refactor Qobuz bundle fetching to improve resilience and performance. Add HTTP timeout and retry configuration, and implement a retry loop that returns version metadata. Introduce bundle version caching and persistence to skip redundant extractions when the bundle remains unchanged. Replace console logging with structured tracing macros and update the architectural tracking document to mark these improvements as complete.
2026-06-11 09:51:15 +02:00
c7f67e7c7c feat(pmoqobuz): add progressive CMAF FLAC streaming support
Introduce a `/tracks/:id/flac` endpoint and `open_cmaf_stream` client method to enable incremental decryption and caching of FLAC audio. Refactor segment decryption into a reusable helper and stream decrypted frames via a bounded tokio channel. Add `tokio-util` as an optional dependency, update the `pmoserver` feature, and implement conditional routing for local proxy versus direct API access. Update the architecture roadmap to document these improvements.
2026-06-11 09:43:44 +02:00
a97bfe6148 feat: implement Qobuz CMAF streaming and AES decryption
Introduces a new CMAF streaming module for Qobuz that handles progressive segment fetching and full-track decryption. The implementation adds HKDF session key derivation, AES-128-CBC key unwrapping, and AES-128-CTR frame decryption, alongside an ISO BMFF parser for extracting FLAC headers and segment metadata. It also integrates automatic session renewal with double-checked locking, a generic async retry mechanism for transient HTTP errors, and centralized error handling. Finally, it exposes `CmafStreamInfo` and async streaming methods in the public API, updating cryptographic dependencies accordingly.
2026-06-11 08:52:28 +02:00
7c10b22204 Merge pull request 'push-zusoquuoxstx' (#99) from push-zusoquuoxstx into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m35s
Reviewed-on: #99
2026-06-07 15:14:04 +02:00
46e269a290 fix: resume playback on non-empty queue regardless of transport state
Removes the strict `transport_state` condition and now triggers `api.resume(id)` solely based on a non-empty queue. This improves resilience against transient or unknown device states, such as post-sleep-timer or network errors, where transport state strings may mismatch expected values but playback should still proceed.
2026-06-07 15:13:03 +02:00
7bce0ffe19 Debounce transient snapshot fetch errors
Introduce a `consecutiveSnapshotErrors` counter with a threshold of 3 to debounce transient fetch failures. The last known snapshot is preserved and UI notifications are suppressed until the threshold is met, filtering out intermittent device glitches. The counter resets on success.
2026-06-07 14:57:51 +02:00
ba40d07f73 fix: prevent direct playback of single-item playlists
Update `isNavigable` to explicitly validate `item.is_container` and disable navigation for playlists with only one item. This forces users to enter the playlist container, preserving metadata update benefits.
2026-06-07 14:52:51 +02:00
8bc0670de4 fix: correct queue drawer positioning and safe-area layout
Replace malformed max-height values with precise calc() expressions and update open/closed transform states. Apply flexbox improvements to ensure reliable mobile drawer layout and proper safe-area padding above the BottomTabBar.
2026-06-07 14:41:37 +02:00
037435af20 style: optimize drawer layout for mobile portrait viewports
Update mobile portrait media queries in RendererDrawer and ServerDrawer to span full viewport width, reduce background opacity to 6%, and remove side box shadows. This flattens the visual style and improves layout for narrow screens.
2026-06-07 14:27:15 +02:00
2b3fae7778 feat: handle SSE cache invalidation and nightly rust toolchain config
Adds a Vue watch in `ServerDrawer.vue` to trigger a manual container directory refresh when SSE cache invalidation clears `browseData`. Includes guards to prevent redundant requests during active loads and properly manages the `isLoading` state. Additionally, introduces `rust-toolchain.toml` to enforce the nightly Rust compiler across all environments, ensuring consistent builds and access to recent language improvements.
2026-06-07 14:20:25 +02:00
06de4feb5e Merge pull request '🎨 Improve mobile safe-area support and refine UPnP/Chromecast rendering' (#98) from push-optznxlwwomy into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m25s
Reviewed-on: #98
2026-04-13 04:14:51 +02:00
9b5a028f3f 🎨 Improve mobile safe-area support and refine UPnP/Chromecast rendering
- Add viewport-fit=cover to HTML meta for iOS safe-area support
- Extend bottom drawers and tab bar into system navigation area using env(safe_area_inset_bottom)
- Adjust queue drawer transforms to account for safe-area padding
+ Add enrich_position_from_queue() helper and integrate across UPnP, Arylic TCP,
  LinkPlay & Chromecast backends to ensure queue-authoritative metadata
+ Add transient error retry logic for UPnP control actions (2 retries, 300ms delay)
+ Separate timeouts: short poll timeout for GetTransportInfo/GetPosition (3s),
  longer actiontimeout SetAVTURI/SetNext... for slow devices
+ Remove duplicate continuous-stream detection from play_uri() methods (now handled centrally)
- Bump version to 0.3.49
2026-04-13 04:14:18 +02:00
9ad7d7454d Merge pull request 'push-yvskvtsqsmxs' (#97) from push-yvskvtsqsmxs into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m4s
Reviewed-on: #97
2026-04-12 21:10:23 +02:00
39d7c56a99 Replace unwrap() with expect("mutex poisoned") across all mutex locks
- Replace `.lock().unwrap()` with explicit error messages for poisoned MutexGuard
- Improve robustness against mutex poisoning in renderer, queue and event subsystems
2026-04-12 21:09:38 +02:00
82197c8103 ♻️ refactor stream detection and queue sync logic
- Replace `is_continuous_stream_url` with new canonical check using metadata + fallback
- Extract stream duration comparison logic to `queue::stream_duration_*` helpers  
- Improve queue sync concurrency: add worker loop, pending/cancel flags
- Make `stream_duration_*` functions public(crate) for reuse
2026-04-12 21:09:38 +02:00
8ddee7d94f ♻️ refactor queue control methods into trait default impls
Remove duplicate `play_from_queue`, ` play_next `,  
`play_previous , and
``
pay _from_index implementations across all renderers (ArylicTcp, Chromecast,
LinkPlay , OpenHome UPnP) and instead provide default implementations in the
`QueueTransportControl `trait. Also introduce dispatch macros to simplify backend delegation for Transport/Volume control, and expose parse_didl_duration as public(crate).
2026-04-12 21:09:38 +02:00
4b793cec59 refactor: replace unwrap() with expect for mutex locks
Replace all `lock().unwrap()` calls on Mutex guards with explicit error messages using `.expect("... mutex poisoned")`. This improves robustness by providing clear diagnostics when a thread panics while holding the lock, preventing silent failures. Affected modules: events.rs (Renderer/MediaServer), all renderer backends, queue backend/implementation files. Also adds documentation to marker traits (HasQueue、 HasContinuousStream) and clarifies error handling in watcher loop with panic catching.
2026-04-12 21:09:38 +02:00
9e447023a8 🚀 refactor(pmocontrol): eliminate QueueBackend boilerplate with HasQueue blanket impl
- Add `Hasqueue` trait and implement it for all renderers (Upnp, OpenHome, LinkPlay, ArylicTcp, Chromecast)
- Replace manual `QueueBackend` implementations with blanket impl for types implementing Hasqueue
  (removes ~30+ duplicated methods across renderers)
- Fix BUG: `sync_queue` in UpnpRenderer now correctly propagates cancel_token instead of ignoring it
- Update version to 0.3.48 in Cargo.toml, lockfile and root file
- Add refactoring plan document (`refactoring_pmocontrol.md`) detailing remaining P1-P3 tasks
2026-04-12 19:03:39 +02:00
6285c8ccc8 Merge pull request 'push-zpoknxvwspkr' (#96) from push-zpoknxvwspkr into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m3s
Reviewed-on: #96
2026-04-10 00:06:54 +02:00
3401ee839c chore: bump version to 0.3.48
Update package and project versions from v0.3.57 to 0.48 in Cargo.toml and version.txt.
2026-04-10 00:06:20 +02:00
e8e33414f0 (refactor) Replace tokio::spawn_blocking with std thread for metadata preloading
(refactor) Replace tokio::spawn_blocking with std thread for metadata preloading
- Use `std::thread` instead of Tokio's blocking pool to avoid potential thread starvation in async context
- Ensures long-running metadata loading does not block Tokio workers
2026-04-10 00:05:16 +02:00
b0e24c3b3c 🔖 bump version to v0.3.47
- Update Cargo.lock packageversion
- Refactor DB initialization: move PRAGMA settings after table creation for correctness and clarity (WAL, cache size etc.)
- Add foreign key enforcement (`PRAGMAforeign_keys = ON`)
>- Reorder index creation to follow table definition
- Add new indexes: `idx_asset_last_used`, idx`_asset_hits`
>- Introduce indexed lazy_pk support with unique constraint on non-NULL values
> - Improve LRU index to use ASC ordering for efficient oldest-record lookup
2026-04-10 00:03:39 +02:00
b5b6becb25 Merge pull request '⬆️ Bump version to v0.3.47' (#95) from push-nlksvqrutmxv into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m12s
Reviewed-on: #95
2026-04-09 23:34:51 +02:00
353e54af76 ⬆️ Bump version to v0.3.47
- Update package versions in Cargo.toml, lockfile and version.txt to v0.3.47
- Optimize SQLite database initialization with WAL mode, larger cache and critical missing indexes (idx_metadata_key_value, idx_asset_last_used/hits)
- Fix production bug in OpenHome renderer: avoid blocking main thread when loading metadata for large queues; offload preloading of next 10 items to background task with small delays
- Minor formatting cleanup in db.rs
2026-04-09 23:34:32 +02:00
f2be1b9bc1 Merge pull request '⬆️ version bump to v0.3.46' (#94) from push-lprskpllksrm into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m8s
Reviewed-on: #94
2026-04-09 23:04:53 +02:00
6e65558ba9 ⬆️ version bump to v0.3.46
- Update Cargo.toml and version.txt to v0.3.46
- Fix production bug in music renderer autoadvance logic: add fallback timeout (20s) to compensate for missed PLAYING events due DB latency
- Update Cargo.lock accordingly
2026-04-09 23:04:35 +02:00
4c7c99f0a4 Merge pull request 'push-ppmsrvolzpzk' (#93) from push-ppmsrvolzpzk into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m10s
Reviewed-on: #93
2026-04-09 22:37:48 +02:00
5c6e2d43ac 🚀 Correctif bug shuffle et amélioration auto-advance
- Mise à jour de la version : `0.3.x` → `0.45`
- Correction critique du bug d'auto-skip après shuffle ou sélection manuelle : réinitialisation obligatoire de `has_played_flag` + positionnement explicite du playback source avant lancement
- Ajout de logs détaillés pour traçabilité des transitions (index, source)
- Gestion robustesse : retry automatique pour renderers JBL-like
- Meilleure synchronisation entre `play_from_index`, watcher et autoadvance
2026-04-09 22:37:27 +02:00
6fd11ab450 ♻️, feat: add retry logic for transient renderer errors
- Replace play_current_from_queue with new `playCurrentFromQueueWithRetry` method in control_point.rs
- Replace play_next_from_queue with `playNextFromQueueWithRetry` and add panic safety in musicrenderer.rs
- Implement retry logic (3 attempts, 200ms delay) for transient renderer errors like JBL Authentics 300
- Deprecate old methods without retry support
2026-04-09 22:37:16 +02:00
57c2552247 🚀 v0.3.42 → v0.3.43 — Correctif bug shuffle & amélioration auto-advance
- Mise à jour de la version (0.3.42 → 0.3.43) dans Cargo.toml, lock et version.txt
- Correctif critique du bug d’auto-saut après shuffle ou sélection manuelle : réinitialisation obligatoire de `has_played_flag` + positionnement explicite du playback source avant appel backend
- Ajout de logs détaillés pour tracer les appels à `play_from_index`, ainsi que l’état de la queue
- Intégration d’un retry (`play_current_from_queue_with_retry`) pour les renderers JBL-like qui échouent au premier Play
- Correction de race condition potentielle lors du changement d’index ou auto-saut
2026-04-09 22:37:16 +02:00
9935a5e5af 🚀 Version bump to v0.3.42 → v0.3.46 & fix shuffle/auto-advance race condition
- Bump version to v0.3.46 across Cargo.toml, lockfile & version.txt
- 🔧 Fix critical shuffle/auto_advance bug: ensure `has_played_flag` is reset and playback source set *before* backend calls in play_from_index, next/prev & queue init
- 📝 Add detailed logging for playback source transitions and index changes to debug timing issues (especially with JBL-like renderers)
- 🎯 Introduce `play_current_from_queue_with_retry()` for resilient playback start on flaky UPnP devices
2026-04-09 22:37:16 +02:00
3979d346a5 ✏️ amélioration des messages d'erreur avec nom du lecteur
- Ajout de `rendererName` computed property dans plusieurs composants pour afficher le nom convivial du lecteur (ou l'ID en fallback)
- Mise à jour des messages d’erreur dans CurrentTrack, TransportControls et VolumeControl pour inclure le nom du lecteur (ex: « Sonos One » — impossible de…)
- Amélioration du message d’erreur dans useRenderers.ts : « Impossible de rafraîchir la liste des lecteurs audio » + message plus spécifique pour les snapshots
- Ajout de l’import `computed` manquant dans VolumeControl.vue
2026-04-09 18:03:00 +02:00
6240179397 Merge pull request '⬆️ migration mdns →mddns-sd' (#92) from push-kmzstwrlymsr into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 8m33s
Reviewed-on: #92
2026-04-09 15:50:56 +02:00
934bbaf4b8 ⬆️ migration mdns →mddns-sd
- Remplacer la crate abandonnée `mdns` (3.0, non-UTF8) par activement maintenue et UTF‑compliant `mdns-sd` (0.19)
- Supprimer les dépendances inutiles `async‑std`, `futures-util` (uniquement utilisées dans le thread mDNS)
- Refactoriser `control_point.rs` : passer d’un bloc async bloquant à une boucle synchrone avec `ServiceDaemon.browse()` + récepteur blocant
- Simplifier drastiquement le parsing dans `chromecast_discovery.rs` via l’API haut‑niveau de mdns-sd (`ServiceInfo`, `get_property_val_str`) → ~80 lignes remplacées par 52
- Ajouter index SQLite `idx_metadata_key_value` pour accélérer les requêtes par origin_url
- Nettoyer exports inutiles dans `pmomediaserver::server_ext`
- Supprimer filtre de bruit obsolète `mdns=error` dans les logs
- Met à jour la version en 0.3.42
2026-04-09 15:50:18 +02:00
35e2e037f0 Merge pull request 'push-xvuyuzpqnxzs' (#91) from push-xvuyuzpqnxzs into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 10m40s
Reviewed-on: #91
2026-04-09 11:21:59 +02:00
9dee193947 ⬆️ version to v0.3.41 — async queue sync refactoring
- Add `SyncCancelled` error variant for non-fatal cancellations
- Refactor queue sync to async via `MusicQueue::schedule_sync()`
  - Extract browse+conversion into internal helper
- Update all `QueueBackend::sync_queue()` signatures to accept cancel token and on_ready callback  
- Implement early-start logic (on pivot preservation or first insert)
 - Add `QueueReadyToPlay` and  ‘ QueueSyncCancelled➔ SSE events
- Replace blocking `refresh_attached_queue_for()` with non-blocking async dispatch in control_point.rs  
- Bump version to v0.3.41
2026-04-09 11:21:11 +02:00
c128120697 🚀 Optimisations OpenHome : fast path LCS, connection pooling & metadata cache
- Ajout d’un chemin rapide (fast path) pour détecter les cas simples de sync_queue : append-only ou delete-from-end, évitant ReadList coûteux
- Mise en place d’un cache URI par track_id pour accélérer la comparaison de préfixe
- Intégration d’un agent HTTP statique via OnceLock pour réutiliser les connexions TCP (pooling), éliminant 95% des handshakes
- Mise à jour de Vite (7.3.1 → 7.3.2) dans le webapp
- Refonte de cache_metadata() pour accepter et stocke l’URI en parallèle des métadonnées
- Toutes les opérations d'insert/delete/replace_item exploitent désormais le cache URI pour la détection de pattern
- Respect strict des contraintes architecturales : OpenHome reste source unique, pas de miroir persistant
2026-04-09 08:40:10 +02:00
4b7c482bf3 [webapp] Add debug logging to search functionality
- Bump Cargo.lock version from v0.3.41 to v0.3.52
- Add console.log statements in ServerDrawer.vue and useMediaServers.ts to trace search flow: handleSearch call, server ID/query passed in API request
- Include logging for number of entries returned by search
2026-04-08 09:01:42 +02:00
4c70a939cd Merge pull request 'push-uplrprqrknlm' (#90) from push-uplrprqrknlm into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m33s
Reviewed-on: #90
2026-04-06 18:47:02 +02:00
77cfb7b3e3 ⬆️ version bump to v0.3.40
- Update crate and project versions from `v0.3.39` to "\""
- Reorder imports in media_server.rs for consistency
  – Move `error_codes` import before other soap modules in pmoupnp
  – Reorder crate imports to group external and local deps logically (soap_client, then core types)
- Improve Browse response formatting: wrap long expressions for readability
  – Add deterministic sort by `+dc:title` in Browse requests (alphabetical, ascending)
  – Preserve track ordering by NOT sorting items (track number preserved), only containers
- Add explicit sort of container list in content_handler.rs for deterministic output
2026-04-06 18:16:48 +02:00
abe8c1a4b2 Optimise frontend performance for large playlists (~1000 tracks)
- Virtualize queue list in QueueViewer.vue using RecycleScroller
- Add 300ms debounce on queue_updated refetches to prevent cascading JSON fetch
- Implement client-side pagination (100 items/page) + cache in PlayListManager.vue with sortedTracks memoization
- Limit browse infinite scroll memory usage via sliding window (200 items)
+ Minor CSS fixes for flexbox overflow/min-width to support virtualization
2026-04-06 17:48:41 +02:00
22b3a67417 🚀 Optimise OpenHome playlist sync performance (-75% SOAP calls)
- Augmente le batch ReadList de 64 à 256 (-75% appels SOAP)
- Élimine les doubles appel à queue_snapshot() dans sync_queue()–50% appels SOAP en moins
- Introduit lcs_flags_optimized() pour élaguer préfixe/suffixes communs (LCS O(n) vs quadratique)
- Met en place un polling adaptatif : 500ms actif / 5s veille
- Factorise parse_duration() et invalidation de caches via méthodes utilitaires
2026-04-06 17:12:46 +02:00
cba1c01b1b Merge pull request 'push-nuorysnrrttx' (#89) from push-nuorysnrrttx into main
All checks were successful
Build and Push Docker Image / build (push) Successful in 9m35s
Reviewed-on: #89
2026-04-06 09:53:45 +02:00
8be250b167 [FE] Révise la stabilité, réactivité et performance du frontend
- Corrige fuites mémoire SSE via nettoyage des listeners (P0)
- Remplace shallowRef<Map> par reactive(new Map()) pour réactivité native Vue (P1)
- Ajoute timeout/AbortController aux requêtes fetch dans l'API client (P4)
- Déboucle les watch() de useTabs avec debounce unique et try/finally sur isRestoringFromStorage (P7)
- Limite notifications à 5 + nettoyage des timers dans UI store (P15)
- Protège routes debug avec import dynamique uniquement en DEV + wildcard 403 (P8)
- Déplace SVG par défaut dans assets/default-cover.svg et import ?raw (P10)
- Ajoute @media prefers-reduced-motion aux animations CSS globales
- Factorise styles drawer-btns avec .drawer-icon-classe + ajoute --opacity-disabled (P13)
- Encode les clés de cache browse avec encodeURIComponent + ':' séparateur (P14)
- Implémente pagination infinite scroll dans browseContainer/loadMore
+ Supprime formatMsToShortTime alias (P9)
- Corrige truncate() pour éviter dépassement maxLength si suffix >=maxLength (P10)
- Valide structure des commandes PMOPlayer avant traitement
+ Met à jour version Cargo.toml et lock (0.3.39)
2026-04-06 09:53:10 +02:00
78c37e1732 🔖 move Frontent Review to Done
- Move `Frontend_Review.md` from Todo/Blackboard to Done/
- Reflects task completion status
2026-04-06 08:56:54 +02:00
164e3d9e5f fix(useRenderers): résoudre les problèmes de réactivité
- Supprimer l'import obsolète `toRaw` et simplifier les mises à jour via spread
- Corriger la mutation directe de `state_changed` en créant des objets immutables + appel à trigger
- Ajouter `triggerQueueReactivity()` pour déclencher la réactivité sur les événements queue
- Mettre à jour le doc de revue frontend pour marquer toutes les tâches comme corrigées
2026-04-06 08:56:36 +02:00
ac9cb3ef3f 🔧 Frontend review fixes & quality improvements
- Fixed race condition in apiCache TTL handling by passing ttl per-entry
- Removed double snapshot reassignment bug after switch cases in useRenderers.ts  
- Replaced `as any` cast on transport_state with runtime guard (isTransportState)
- Fixed invalidate() to preserve subscriptions instead of deleting them
- Migrated reactive(Map) → shallowRef + explicit reactivity triggers (triggerSnapshotReactive, triggerLoadingReactice)
- Added onUnmounted cleanup for debounce timer in useRenderer()
- Exposed resetSSE() to allow reinitialization after SSE reconnect
- Split deep watch in useTabs.ts into separate lightweight watches without {deep: true}
- Fixed swipe gesture to capture startX in onSwipeStart instead of using final clientX
- Added minimal JSON validation log for null responses (DEV mode only)
- Implemented ARIA labels on transport controls and volume slider
- Added UI notifications for network errors via uiStore.notifyError()
+ Removed obsolete toRaw() usage and import after shallowRef migration
- Added missing reactivity triggers for state_changed, queue_refreshing/updated cases
2026-04-06 08:51:12 +02:00
66ba31b12f ⬆️ version bump & fix race conditions in API cache and renderers
- Bump Cargo.lock version to `0.3.47`
- Fix race condition in API cache by using unique request keys and proper promise cleanup
  - Avoid duplicate pending requests with `request:${key}` prefix
- Improve renderer snapshot error handling: clear invalid snapshots on failure and always clean up loading flag in `finally`
- Add debounce to renderer refresh logic (500ms) preventing excessive concurrent fetches
  - Use local `currentRendererId` to avoid stale ID usage across async boundaries
2026-04-06 08:06:51 +02:00