2024-12-15 23:52:17 -05:00
use anyhow ::{ Context , Result } ;
use cpal ::traits ::{ DeviceTrait , HostTrait , StreamTrait } ;
use cpal ::{ FromSample , Sample , SampleFormat } ;
use tracing ::{ error , info , trace , warn } ;
use tokio ::sync ::mpsc ::Receiver ;
use crate ::task_msg ::{ PcmFrameMessage , PcmSampleMessage } ;
pub fn audio_transmitter_main (
mut rx_for_wire : Receiver < PcmSampleMessage > ,
2024-12-16 21:06:39 -05:00
cpal_output : & cpal ::Device ,
) -> Result < cpal ::Stream > {
2024-12-15 23:52:17 -05:00
trace! ( " audio_transmitter started " ) ;
let cpal_output_config = cpal_output . supported_output_configs ( )
. context ( " could not find a suitable audio output configuration. are you root, trying to use a normal user's audio stack? try setting the capability CAP_NET_ADMIN=ep on this binary, and running as the user who is running the audio stack. " ) ?
. max_by_key ( | cfg | {
2024-12-16 21:06:39 -05:00
if cfg . channels ( ) > 1 { return - 999 ; }
match cfg . sample_format ( ) {
SampleFormat ::U8 = > 10 ,
SampleFormat ::I8 = > 11 ,
SampleFormat ::U16 = > 20 ,
SampleFormat ::I16 = > 21 ,
SampleFormat ::U32 = > 30 ,
SampleFormat ::I32 = > 31 ,
SampleFormat ::F32 = > 40 ,
SampleFormat ::F64 = > 50 ,
SampleFormat ::U64 = > 60 ,
SampleFormat ::I64 = > 61 ,
x = > { warn! ( " Backend offered unknown sample format {x} " , ) ; - 999 }
}
2024-12-15 23:52:17 -05:00
} ) . expect ( " output device has no supported configurations available " )
2024-12-16 21:06:39 -05:00
. with_max_sample_rate ( ) ;
2024-12-15 23:52:17 -05:00
info! (
2024-12-16 21:06:39 -05:00
" output samples are {} @ {}hz on {} channels " ,
2024-12-15 23:52:17 -05:00
& cpal_output_config . sample_format ( ) ,
& cpal_output_config . sample_rate ( ) . 0 ,
2024-12-16 21:06:39 -05:00
& cpal_output_config . channels ( ) ,
2024-12-15 23:52:17 -05:00
) ;
let failed_pcm_give = move | e | {
warn! ( " dropped some PCM data on output stream?! {} " , e ) ;
} ;
let output_stream = match cpal_output_config . sample_format ( ) {
cpal ::SampleFormat ::U8 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< u8 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I8 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< i8 > ( pcm , & mut rx_for_wire ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::U16 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< u16 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I16 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< i16 > ( pcm , & mut rx_for_wire ) ,
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::U32 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
move | pcm , _ : & _ | give_output_pcm ::< u32 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I32 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< i32 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::F32 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< f32 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::F64 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< f64 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::U64 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< u64 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
cpal ::SampleFormat ::I64 = > cpal_output
. build_output_stream (
& cpal_output_config . into ( ) ,
2024-12-16 21:06:39 -05:00
move | pcm , _ : & _ | give_output_pcm ::< i64 > ( pcm , & mut rx_for_wire ) ,
2024-12-15 23:52:17 -05:00
failed_pcm_give ,
None ,
)
. context ( " failed to build output stream " ) ? ,
sample_format = > Err ( anyhow ::Error ::msg ( format! (
" unsupported sample format '{}'! please ask developers to add it " ,
sample_format
) ) ) ? ,
} ;
output_stream
. play ( )
2024-12-16 21:06:39 -05:00
. context ( " failed to start output audio stream " ) ? ;
2024-12-15 23:52:17 -05:00
2024-12-16 21:06:39 -05:00
Ok ( output_stream )
2024-12-15 23:52:17 -05:00
}
2024-12-16 21:06:39 -05:00
fn give_output_pcm < T > ( pcm : & mut [ T ] , channel : & mut Receiver < PcmSampleMessage > )
2024-12-15 23:52:17 -05:00
where
T : Sample + std ::fmt ::Debug + FromSample < i64 > + FromSample < f64 > ,
{
2024-12-16 11:44:14 -05:00
print! ( " ALSA wanted {} samples... " , pcm . len ( ) ) ;
2024-12-15 23:52:17 -05:00
for outgoing in pcm . iter_mut ( ) {
* outgoing = match channel . try_recv ( ) {
Ok ( sample ) = > sample . to_sample ::< T > ( ) ,
2024-12-16 21:06:39 -05:00
Err ( _ ) = > {
//warn!("rx_for_wire has no samples for us! carrier dead!");
//warn!("are we able to produce samples quickly enough? CPU OK?");
T ::EQUILIBRIUM
}
2024-12-15 23:52:17 -05:00
} ;
}
2024-12-16 11:44:14 -05:00
println! ( " gave them " ) ;
2024-12-15 23:52:17 -05:00
}