From 70e5182dfcf78164e5e39e74aaee39b125fcfd83 Mon Sep 17 00:00:00 2001 From: _ <> Date: Sat, 13 Nov 2021 19:45:16 +0000 Subject: [PATCH] :recycle: refactor: extract DecoderThread and clean up identifiers --- src/main.rs | 118 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 49 deletions(-) diff --git a/src/main.rs b/src/main.rs index b682ed4..3190b13 100644 --- a/src/main.rs +++ b/src/main.rs @@ -102,7 +102,7 @@ pub struct SharedState { pub quit: bool, } -fn cmd_gui (args: &[String]) -> Result <()> { +fn cmd_gui (_args: &[String]) -> Result <()> { let (fltk_tx, fltk_rx) = app::channel:: (); let app = app::App::default (); @@ -151,59 +151,19 @@ fn cmd_play (args: &[String]) -> Result <()> { .map (|s| s.to_string ()) .collect (); - let pair = Arc::new ((Mutex::new (SharedState::default ()), Condvar::new ())); - let pair2 = Arc::clone (&pair); - let pair3 = Arc::clone (&pair); - - let thread_decoder = thread::spawn (move|| { - let (lock, cvar) = &*pair2; - - 'many_files: for filename in &filenames { - let mut decoder = decoder::Decoder::new (&filename)?; - - 'one_file: loop { - let frame = match decoder.next ()? { - Some (x) => x, - None => { - tracing::debug! ("Decoder thread finished a file"); - break 'one_file; - }, - }; - - let mut decoder_state = cvar.wait_while (lock.lock ().unwrap (), |decoder_state| { - decoder_state.pcm_buffers.samples_available () >= 12_000 && - ! decoder_state.quit - }).unwrap (); - - if decoder_state.quit { - break 'many_files; - } - - decoder_state.pcm_buffers.produce_bytes (frame.data ().into ()); - } - } - - Ok::<_, anyhow::Error> (()) - }); - + let shared_state = Arc::new ((Mutex::new (SharedState::default ()), Condvar::new ())); let pcm_quit = Arc::new ((Mutex::new (false), Condvar::new ())); - let pcm_quit2 = Arc::clone (&pcm_quit); - let audio_output = AudioOutput::new (pcm_quit, pair)?; + let thread_decoder = DecoderThread::new (Arc::clone (&shared_state), filenames); + let audio_output = AudioOutput::new (Arc::clone (&pcm_quit), Arc::clone (&shared_state))?; tracing::debug! ("Joining decoder thread..."); - if false { - let mut decoder_state = pair3.0.lock ().unwrap (); - decoder_state.quit = true; - pair3.1.notify_one (); - } - - thread_decoder.join ().unwrap ()?; + thread_decoder.join ()?; tracing::debug! ("Joining PCM thread..."); - let (lock, cvar) = &*pcm_quit2; + let (lock, cvar) = &*pcm_quit; let _ = cvar.wait (lock.lock ().unwrap ()).unwrap (); drop (audio_output); @@ -214,6 +174,57 @@ fn cmd_play (args: &[String]) -> Result <()> { Ok (()) } +struct DecoderThread { + join_handle: thread::JoinHandle >, +} + +impl DecoderThread { + pub fn new ( + shared_state: Arc <(Mutex , Condvar)>, + filenames: Vec , + ) -> Self + { + let join_handle = thread::spawn (move|| { + let (lock, cvar) = &*shared_state; + + 'many_files: for filename in &filenames { + let mut decoder = decoder::Decoder::new (&filename)?; + + 'one_file: loop { + let frame = match decoder.next ()? { + Some (x) => x, + None => { + tracing::debug! ("Decoder thread finished a file"); + break 'one_file; + }, + }; + + let mut decoder_state = cvar.wait_while (lock.lock ().unwrap (), |decoder_state| { + decoder_state.pcm_buffers.samples_available () >= 12_000 && + ! decoder_state.quit + }).unwrap (); + + if decoder_state.quit { + break 'many_files; + } + + decoder_state.pcm_buffers.produce_bytes (frame.data ().into ()); + } + } + + Ok::<_, anyhow::Error> (()) + }); + + Self { + join_handle, + } + } + + pub fn join (self) -> Result <()> { + self.join_handle.join ().unwrap () + } +} + struct AudioOutput { host: cpal::Host, device: cpal::Device, @@ -223,8 +234,9 @@ struct AudioOutput { impl AudioOutput { pub fn new ( pcm_quit: Arc <(Mutex , Condvar)>, - pair: Arc <(Mutex , Condvar)>, - ) -> Result { + shared_state: Arc <(Mutex , Condvar)>, + ) -> Result + { let host = cpal::default_host (); let device = host.default_output_device ().ok_or_else (|| anyhow! ("can't open cpal device"))?; @@ -239,7 +251,7 @@ impl AudioOutput { let stream = device.build_output_stream ( &config, move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { - let (lock, cvar) = &*pair; + let (lock, cvar) = &*shared_state; let time_start = Instant::now (); let mut decoder_state = match lock.lock () { @@ -281,6 +293,14 @@ impl AudioOutput { stream, }) } + + pub fn play (&mut self) -> Result <()> { + Ok (self.stream.play ()?) + } + + pub fn pause (&mut self) -> Result <()> { + Ok (self.stream.pause ()?) + } } #[cfg (test)]