use std::sync::Arc; use std::sync::atomic::AtomicU32; use std::time::Duration; use tokio::sync::mpsc; use tokio::sync::oneshot; use bytes::{Bytes}; use crate::core::opus::{AudioOpus, AudioOpusDecoder}; use crate::utils::ringbuf::{RingBufReader, RingBufWriter, RingBuffer}; use crate::utils::shared_store::SharedArcMap; pub struct AudioClient { uuid: uuid::Uuid, decode_sender: mpsc::Sender, buffer_reader: RingBufReader, buffer_writer: RingBufWriter } struct DecodeRequest { data: Bytes, sequence: u16, } #[derive(Clone)] pub struct AudioClientManager { audio_clients: SharedArcMap, } impl AudioClient { pub fn new() -> Self { let (writer, reader) = RingBuffer::::new(4096).split(); let (decode_sender, mut decode_reader) = mpsc::channel::(100); let writer_clone = writer.clone(); let decode_handle = tokio::spawn(async move { let mut decoder = AudioOpus::new(48000, 1, "voip") .create_decoder().unwrap(); let mut last_sequence: u16 = 0; while let Some(request) = decode_reader.recv().await { // si la séquence est "trop vieille" on la drop. (voir plus tard pour un système de rattrapage si c'est possible) if last_sequence < request.sequence { // todo : si le décodage est trop long, voir pour le mettre dans un thread // avec let result = tokio::task::spawn_blocking({ // let data = request.data.clone(); // move || decoder.decode(&data) // }).await.unwrap(); let start = std::time::Instant::now(); let result = decoder.decode(&request.data); if start.elapsed() > Duration::from_millis(1) { println!("⚠️ Frame drop possible: {:?}", start.elapsed()); } match result { Ok(audio_frame) => { // Pousser la frame complète dans le buffer writer_clone.push_slice_overwrite(&audio_frame); println!("writed frame"); }, Err(e) => { eprintln!("Erreur de décodage audio : {}", e); } } last_sequence = request.sequence; } } }); Self { uuid: uuid::Uuid::new_v4(), decode_sender, buffer_reader: reader, buffer_writer: writer, } } pub fn write_audio(&self, sequence: u16, data: Bytes) { let _ = self.decode_sender.try_send(DecodeRequest { data, sequence }); } } impl AudioClientManager { pub fn new() -> Self { Self { audio_clients: SharedArcMap::new() } } pub fn audio_client_exists(&self, uuid: uuid::Uuid) -> bool { self.audio_clients.contains_key(&uuid) } pub fn get_audio_client(&self, uuid: uuid::Uuid) -> Option> { self.audio_clients.get(&uuid) } pub fn add_audio_client(&self, uuid: uuid::Uuid, audio_client: AudioClient) { self.audio_clients.insert(uuid, audio_client); } pub fn remove_audio_client(&self, uuid: uuid::Uuid) { self.audio_clients.remove(&uuid); } pub fn write_audio_to_client(&self, uuid: uuid::Uuid, sequence: u16, data: Bytes) { let _ = self.audio_clients.get(&uuid).unwrap().write_audio(sequence, data); } }