(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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- 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)
- 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
- 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
- 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
- Added automatic retries with exponential backoff to fetchRenderers
- Improved WebRenderer registration: handle stale players, avoid duplicate registrations,
and force renderers refresh after successful connection
- Bumped version to v0.3.37 (Cargo: 0.3.36 → Cargo.lock mismatch fixed by updating to final version)
- Fix renderer filtering logic to normalize `udn` and id by stripping 'uuid:' prefix
- Replace fragile model_name-based detection with reliable friendly-name check for WebRenderers ('Web Audio – ' prefix)
- Add `manufacturer` field to renderer types and registry
- Update badge count in UnifiedControlView.vue to use filtered renderers
- Bump crate and app versions from `v0.3.5` to v"\n- Add retry logic with exponential backoff in `fetchRenderers`[39m
- Improve re-registration robustness in `useWebRenderer` (stale player handling, instanceId error recovery)
- Trigger forced renderer refresh after successful registration
- Bump version to v0.3.35 in Cargo.toml, lockfile and `version.txt`
- Refactor MediaRenderer to accept dynamic stream URL base instead of hardcoded `/api/webrenderer` path
- Remove `PlayerStateReport`, moving it to pmoweb/renderer as local type for better encapsulation
- Update `register_or_reconnect` and device creation to accept renderer name, stream URL base via closure
- Replace `update_player_state` and `get_pending_command`, delegating state/command access directly via instance lookup
- Simplify device creation by using `Device::new_from_config` and removing manual model_name setting
- Phase 1.5/2.6 : adapter BrowserAdapter instancié dans WebRendererInstance et câblé aux handlers (Flush/Stop/Pause via deliver())
- Phase 2.4 : Flush envoyé au device sur TrackEnded (Weak<dyn DeviceAdapter> évite les cycles de référence)
- Phase 1.6 : méthodes browser-spécifiques supprimées de RendererRegistry (set_player_command, has_current_uri…), remplacée par get_instance() + accès direct adapter/pipeline
- handlers.rs : flush/stop et pause livrés via l'adapter dans stop_handler/pause_handle
- register.rs : endpoints /play, pause et set_uri mis à jour pour utiliser l'adapter
- pipeline.rs : adapter exposé dans PipelineHandle et passé au event listener via Weak
- Phase 1: Introduce DeviceCommand enum and BrowserAdapter in adapter.rs
- Fix P0 bug (play_handler now checks URI before state change)
- Phase 2: Wire flac_handle.pause/resume into pause_handler/stop/play
- Add VecDeque<DeviceCommand> to RendererState, replace Option<Value>
- Phase 3: Add AudioContext + exponential backoff reconnect in PMOPlayer.ts
- Fix position format (seconds_to_upnp_time) and add /nowplaying, /state endpoints
- Phase 4: Register new HTTP routes in config.rs and implement handlers
- Introduit DeviceAdapter trait pour isoler la livraison aux devices (browser, Android Auto…)
- Remplace player_command Option<serde_json::Value> par VecDeque typée DeviceCommand
- Corrige P0 (play_handler bloqué sans URI) et résout les bugs de pause/flush non transmis au browser
- Ajoute AudioContext dans PMOPlayer.ts pour réduire le buffer décodé (~5s → ~50ms)
- Implémenter auto-reconnect sur coupure réseau HTTP
- Unifie le format de position en HH:MM:SS (UPnP)
- Ajoute endpoints JSON /nowplaying et /state pour les futurs adaptateurs
— Restructuration modulaire préparée (core/ vs browser/) pour facilité l'ajout de devices
- Extract beforeunload handler in useWebrenderer.ts to ensure consistent unregister() calls
- Remove unused AudioContext from PMOPlayer and clean up destroy()
- Add guaranteed final report via sendBeacon during destruction
- Simplify playStream() in PMOPlayer by removing URL rewriting logic (now handled server-side)
- Update play_handler to pass instance_id and store stream command atomically
- Avoid race conditions when setting current_uri before sending Play control event
- Remove obsolete WebSocket message types from messages.rs (now using HTTP polling)
- Keep only core PlaybackState enum
- Fix registry::get_player_command to avoid nested locks on HashMap + Sharedstate Arcs
- Add missing PlaybackState::Transitioning in pipeline.rs TrackEnded event
- Refactor renderer service variable registration using helper add_var() function
- Remplacer les Arc+Box::pin manuels par la macro action_handler!(captures(...))
- Supprimer helpers locaux dupliqués dans renderer.rs (add_var, add_action)
- Extraire handlers génériques pour GET requests
- Factoriser extraction metadata dans set_uri_handler /set_next_uriHandler
- Simplifier build_renderingcontrol en retirant pipeline inutile
- Mettre à jour edition Rust de 2021 vers 2024 dans tous les Cargo.toml
- Corriger pattern matching inutile `ref` sur déréférencement dans pmoaudio et pmoflac
- Remplacer les macro_rules! `add_arg_in` et `add_out`, ainsi que la duplication manuelle d’ajout de variables/actions, par des fonctions explicites (`add_arg_in`, `all arg_out`, etc.)
- Introduire des fonctions utilitaires génériques pour `add_var`, `add_action` afin d’unifier la gestion des erreurs
- Mettre à jour tous les services UPnP (`build_avtransport`, `renderingcontrol_service_builder` et autres) pour utiliser les nouvelles fonctions
- Supprimer le code redondant dans la construction des actions (ex: ~12 lignes dupliquées)
- Ajouter le fichier de plan `.kilo/plans/17xx-kind-falcon.md` décrivant la refonte
- Vérifier que les imports et signatures sont cohérents (ex: `&Arc<StateVariable>`)
Introduce add_arg_in! andadd_outmacros to reduce boilerplate in UPnP action argument setup. Refactor all actions (Play, Stop,...GetPositionInfo) to use macros instead of repetitive add_argument calls. Also remove unused blank line in pipeline.rs.
- Drop unnecessary `axum::extract::{Path(State)}` imports in config.rs and registry.rs
- Mark unused field `_position_sec` with `#[allow(dead_code)]`
- Add missing attribute to dead code struct
- Remove unused macros `add_action_arg!`, etc. and related types (`PlayerReport`)
- Add documentation comments to all AVTransport, RenderingControl & ConnectionManager handlers
- Simplify play_handler: remove redundant state writes and clarify flow with comments
- Deduplicate pipeline command logic in registry.rs by introducing send_pipeline_command helper
- Replace direct PlayerCommand usage with unified PipelineControl enum in registry and handlers
- Fix handler signatures: clone pipeline once before Arc closure (next/previous)—avoid redundant clones
- Add helper macros for UPnP service factory to reduce boilerplate (add_action, add_var)
- Minor formatting fixes: sort imports and align handler assignments
- Drop `Path`/``State``` from unused Axum imports in config.rs and registry
- Mark `_position_sec` field as `#[allow(dead_code)]`` in PositionUpdateRequest and PlayerStateReport
- Remove unused macro rules (`add_action_arg!`, `add_action!``, `` add_var!)``
- Delete unused PlayerReport struct and related handler code
- Updateurequest dependency from v2 to latest major (v3.14)
- Add ureq as optional dependency in pmoaudio-ext
- Introduce is_continuous flag to UriSource and PlayerState for proper StreamType handling (Finite vs Continuous)
- Implement detect_continuous_stream() with URL pattern matching and HTTP HEAD header inspection (ICY, chunked encoding)
- Update send_track_boundary() to accept StreamType parameter
- Introduce `Streamtype` enum (Continuous vs Finite) to distinguish radio streams from finite tracks
- Enrich `TrackBoundary` sync marker with stream type for proper pause behavior per mode (silence vs backpressure)
- Update all sources and sinks to pass `StreamType` when creating track boundaries
- Radio Paradise, HTTP source → Continuous (infinite)
- Improve UPnP control architecture: pause sends silence for radio, blocks pipeline via backpressure for tracks
- Prepare groundwork for multi-client DSP architecture with shared source and per-DSP pipelines
- Bump crate and file versions from `v0.3.29` to v\[correction: actually 0\.3\.33] (see Cargo.toml & version.txt)
- Extend cover URL transformation logic to queue items in `pmoserver_ext.rs`—now transforms album art for both current track *and* queue items
- Add debug logging to cover URL transformation steps (local route, instance match & proxy)
- Minor cleanup: remove redundant `clone()` in base_url usage
- Convert `renderer_event_to_payload` and `media_server_sse::event_handler`s to async
- Replace sync cover URL transformation with `.await` on `transform_cover_url`
- Remove blocking thread-based workarounds for async execution
- Improve SSE scalability and responsiveness by eliminating nested runtimes