diff --git a/pmoparadise/RADIO_PARADISE_STREAM_SOURCE.md b/pmoparadise/RADIO_PARADISE_STREAM_SOURCE.md index 37ac10eb..ccf8235f 100644 --- a/pmoparadise/RADIO_PARADISE_STREAM_SOURCE.md +++ b/pmoparadise/RADIO_PARADISE_STREAM_SOURCE.md @@ -20,7 +20,7 @@ RadioParadiseStreamSource (wrapper) Responsabilités : - **File d'attente** : `VecDeque` pour les blocks à télécharger -- **Cache anti-redondance** : `HashSet` pour 10 blocs récents +- **Cache anti-redondance** : `VecDeque` pour 10 blocs récents (FIFO) - **Téléchargement** : Fetch bloc FLAC (bitrate=4 uniquement) - **Décodage** : Stream FLAC via `pmoflac::decode_audio_stream` - **Timing** : Calcul précis pour insertion TrackBoundary @@ -36,7 +36,7 @@ Responsabilités : ▼ ┌─────────────────────────────────────────────────────────┐ │ 2. Vérification cache │ -│ └─> HashSet::contains(&event_id) │ +│ └─> VecDeque::contains(&event_id) │ └─────────────────────────────────────────────────────────┘ │ ▼ @@ -118,17 +118,20 @@ AudioSegment::new_audio(42, AudioChunk::I16(...)) const RECENT_BLOCKS_CACHE_SIZE: usize = 10; fn mark_block_downloaded(&mut self, event_id: EventId) { - self.recent_blocks.insert(event_id); + self.recent_blocks.push_back(event_id); + // Limiter la taille du cache : retirer le plus ancien if self.recent_blocks.len() > RECENT_BLOCKS_CACHE_SIZE { - // Retirer un élément (ordre non garanti avec HashSet) - if let Some(&first) = self.recent_blocks.iter().next() { - self.recent_blocks.remove(&first); - } + self.recent_blocks.pop_front(); } } ``` +**Avantages VecDeque** : +- ✅ Ordre FIFO garanti (le plus ancien est toujours retiré) +- ✅ Simple et prévisible +- ✅ Pour 10 éléments, `contains()` en O(n) reste très performant + ## Support FLAC ### Formats supportés diff --git a/pmoparadise/src/radio_paradise_stream_source.rs b/pmoparadise/src/radio_paradise_stream_source.rs index 71e2c4c0..45168b37 100644 --- a/pmoparadise/src/radio_paradise_stream_source.rs +++ b/pmoparadise/src/radio_paradise_stream_source.rs @@ -17,7 +17,7 @@ use pmoaudio::{ use pmoflac::decode_audio_stream; use pmometadata::{MemoryTrackMetadata, TrackMetadata}; use std::{ - collections::{HashSet, VecDeque}, + collections::VecDeque, sync::Arc, time::Duration, }; @@ -38,7 +38,7 @@ const RECENT_BLOCKS_CACHE_SIZE: usize = 10; pub struct RadioParadiseStreamSourceLogic { client: RadioParadiseClient, chunk_frames: usize, - recent_blocks: HashSet, + recent_blocks: VecDeque, block_queue: VecDeque, } @@ -50,7 +50,7 @@ impl RadioParadiseStreamSourceLogic { Self { client, chunk_frames, - recent_blocks: HashSet::with_capacity(RECENT_BLOCKS_CACHE_SIZE), + recent_blocks: VecDeque::with_capacity(RECENT_BLOCKS_CACHE_SIZE), block_queue: VecDeque::new(), } } @@ -65,16 +65,13 @@ impl RadioParadiseStreamSourceLogic { self.recent_blocks.contains(&event_id) } - /// Marque un bloc comme récemment téléchargé + /// Marque un bloc comme récemment téléchargé (FIFO) fn mark_block_downloaded(&mut self, event_id: EventId) { - self.recent_blocks.insert(event_id); + self.recent_blocks.push_back(event_id); - // Limiter la taille du cache + // Limiter la taille du cache : retirer le plus ancien if self.recent_blocks.len() > RECENT_BLOCKS_CACHE_SIZE { - // Retirer un élément (HashSet n'a pas d'ordre, donc on retire le premier) - if let Some(&first) = self.recent_blocks.iter().next() { - self.recent_blocks.remove(&first); - } + self.recent_blocks.pop_front(); } }