6.4 KiB
6.4 KiB
Changelog - Extensions Multiroom et Volume
Version 0.2.0 - Extensions Multiroom
Nouvelles fonctionnalités
1. Contrôle de volume dynamique
- VolumeNode : node de contrôle de volume software thread-safe
- HardwareVolumeNode : variant pour contrôle matériel (prévu)
- VolumeHandle : handle pour contrôler le volume depuis un autre contexte
- Système master/slave : synchronisation automatique du volume entre branches
2. Nouveaux types de sinks
- DiskSink : écriture sur disque (WAV, FLAC, PCM)
- Dérivation automatique du nom de fichier depuis la source
- Application automatique du gain avant écriture
- ChromecastSink : diffusion vers Chromecast (mock)
- MpdSink : streaming vers MPD (mock)
3. Système d'événements
- EventPublisher/EventReceiver : système d'abonnement générique type-safe
- VolumeChangeEvent : notification de changement de volume
- SourceNameUpdateEvent : mise à jour du nom de source
- AudioDataEvent : transport de données audio via événements
4. Extensions AudioChunk
- Nouveau champ
gain: f32pour contrôle de volume lazy with_gain(): constructeur avec gainapply_gain(): application du gain sur les sampleswith_modified_gain(): modification du gain sans copie
Modules ajoutés
src/
├── events.rs [NOUVEAU]
└── nodes/
├── volume_node.rs [NOUVEAU]
├── disk_sink.rs [NOUVEAU]
├── chromecast_sink.rs [NOUVEAU]
└── mpd_sink.rs [NOUVEAU]
examples/
├── volume_control_demo.rs [NOUVEAU]
└── multiroom_volume_demo.rs [NOUVEAU]
API publique
Exports ajoutés dans lib.rs
// Events
pub use events::{
AudioDataEvent,
EventPublisher,
EventReceiver,
NodeEvent,
NodeListener,
SourceNameUpdateEvent,
VolumeChangeEvent,
};
// Volume nodes
pub use nodes::volume_node::{
HardwareVolumeNode,
VolumeHandle,
VolumeNode,
};
// Sinks
pub use nodes::disk_sink::{
AudioFileFormat,
DiskSink,
DiskSinkConfig,
DiskSinkStats,
};
pub use nodes::chromecast_sink::{
ChromecastConfig,
ChromecastSink,
ChromecastStats,
StreamEncoding,
};
pub use nodes::mpd_sink::{
MpdAudioFormat,
MpdConfig,
MpdHandle,
MpdSink,
MpdStats,
};
Modifications de types existants
AudioChunk
pub struct AudioChunk {
pub order: u64,
pub left: Arc<Vec<f32>>,
pub right: Arc<Vec<f32>>,
pub sample_rate: u32,
pub gain: f32, // [NOUVEAU]
}
impl AudioChunk {
// Méthodes existantes (inchangées)
pub fn new(...) -> Self;
pub fn from_arc(...) -> Self;
pub fn len(&self) -> usize;
pub fn is_empty(&self) -> bool;
pub fn clone_data(&self) -> (Vec<f32>, Vec<f32>);
// Nouvelles méthodes
pub fn with_gain(..., gain: f32) -> Self; // [NOUVEAU]
pub fn from_arc_with_gain(..., gain: f32) -> Self;// [NOUVEAU]
pub fn apply_gain(&self) -> Self; // [NOUVEAU]
pub fn with_modified_gain(&self, new_gain: f32) -> Self; // [NOUVEAU]
}
Tests
- 12 nouveaux tests unitaires
- Tous les tests existants continuent de passer
- Total : 31 tests, 0 failures
Exemples
volume_control_demo: contrôle de volume simplemultiroom_volume_demo: pipeline multiroom complet
Breaking changes
Aucun - Toutes les modifications sont additives.
Performances
- Zero-copy maintenu : partage des
Arc<AudioChunk>entre branches - Lazy evaluation : gain non appliqué jusqu'au sink
- Thread-safe :
RwLockpour le volume, channels Tokio
Documentation
FEATURES_EXTENDED.md: documentation complète des fonctionnalitésIMPLEMENTATION_SUMMARY.md: résumé technique de l'implémentation- Commentaires inline dans le code
Migration depuis 0.1.0
Aucune migration nécessaire. Le code existant fonctionne sans modification.
Pour utiliser les nouvelles fonctionnalités
Ajouter un contrôle de volume
// Avant
source.add_subscriber(sink_tx);
// Après
let (mut volume, volume_tx) = VolumeNode::new("main", 1.0, 10);
let handle = volume.get_handle();
volume.add_subscriber(sink_tx);
source.add_subscriber(volume_tx);
tokio::spawn(async move { volume.run().await });
// Modifier le volume dynamiquement
handle.set_volume(0.5).await;
Écrire sur disque
let config = DiskSinkConfig {
output_dir: PathBuf::from("/tmp/audio"),
filename: Some("output.wav".to_string()),
..Default::default()
};
let (disk_sink, disk_tx) = DiskSink::new("disk1".to_string(), config, 10);
// Connecter au pipeline
volume.add_subscriber(disk_tx);
// Lancer
tokio::spawn(async move {
let stats = disk_sink.run().await.unwrap();
stats.display();
});
Configuration multiroom
// Volume master
let (mut master, master_tx) = VolumeNode::new("master", 1.0, 50);
let (event_tx, event_rx1) = mpsc::channel(10);
let (_, event_rx2) = mpsc::channel(10);
master.subscribe_volume_events(event_tx);
source.add_subscriber(master_tx);
// Branche 1
let (mut vol1, vol1_tx) = VolumeNode::new("room1", 0.8, 50);
vol1.set_master_volume_source(event_rx1);
vol1.add_subscriber(sink1_tx);
master.add_subscriber(vol1_tx);
// Branche 2
let (mut vol2, vol2_tx) = VolumeNode::new("room2", 0.9, 50);
vol2.set_master_volume_source(event_rx2);
vol2.add_subscriber(sink2_tx);
master.add_subscriber(vol2_tx);
// Contrôle master
let master_handle = master.get_handle();
master_handle.set_volume(0.7).await; // Affecte toutes les branches
Roadmap
v0.3.0 (prévu)
- Implémentation réelle ChromecastSink avec
rust-cast - Implémentation réelle MpdSink avec protocole MPD
- Support FLAC dans DiskSink avec
claxon - AirPlaySink (diffusion AirPlay/AirPlay 2)
- EqualizerNode (égaliseur paramétrique)
v0.4.0 (prévu)
- PulseAudioSink / AlsaSink / CoreAudioSink
- CompressorNode / LimiterNode (dynamiques)
- ReverbNode (réverbération)
- CrossfadeNode (transition entre sources)
- HttpStreamSink (serveur Icecast/Shoutcast)
v1.0.0 (futur)
- Synchronisation NTP/PTP pour multi-device
- Room correction avec FIR filters
- API REST pour contrôle
- Dashboard web
- Documentation complète utilisateur
Contributeurs
- Implémentation initiale : Assistant Claude
- Architecture PMOAudio : Projet PMOMusic
Licence
Partie du projet PMOMusic