♻️ refactor: extract DecoderThread and clean up identifiers
parent
f7c38d88de
commit
70e5182dfc
118
src/main.rs
118
src/main.rs
|
@ -102,7 +102,7 @@ pub struct SharedState {
|
||||||
pub quit: bool,
|
pub quit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cmd_gui (args: &[String]) -> Result <()> {
|
fn cmd_gui (_args: &[String]) -> Result <()> {
|
||||||
let (fltk_tx, fltk_rx) = app::channel::<Message> ();
|
let (fltk_tx, fltk_rx) = app::channel::<Message> ();
|
||||||
|
|
||||||
let app = app::App::default ();
|
let app = app::App::default ();
|
||||||
|
@ -151,59 +151,19 @@ fn cmd_play (args: &[String]) -> Result <()> {
|
||||||
.map (|s| s.to_string ())
|
.map (|s| s.to_string ())
|
||||||
.collect ();
|
.collect ();
|
||||||
|
|
||||||
let pair = Arc::new ((Mutex::new (SharedState::default ()), Condvar::new ()));
|
let shared_state = 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 pcm_quit = Arc::new ((Mutex::new (false), 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...");
|
tracing::debug! ("Joining decoder thread...");
|
||||||
|
|
||||||
if false {
|
thread_decoder.join ()?;
|
||||||
let mut decoder_state = pair3.0.lock ().unwrap ();
|
|
||||||
decoder_state.quit = true;
|
|
||||||
pair3.1.notify_one ();
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_decoder.join ().unwrap ()?;
|
|
||||||
|
|
||||||
tracing::debug! ("Joining PCM thread...");
|
tracing::debug! ("Joining PCM thread...");
|
||||||
|
|
||||||
let (lock, cvar) = &*pcm_quit2;
|
let (lock, cvar) = &*pcm_quit;
|
||||||
let _ = cvar.wait (lock.lock ().unwrap ()).unwrap ();
|
let _ = cvar.wait (lock.lock ().unwrap ()).unwrap ();
|
||||||
|
|
||||||
drop (audio_output);
|
drop (audio_output);
|
||||||
|
@ -214,6 +174,57 @@ fn cmd_play (args: &[String]) -> Result <()> {
|
||||||
Ok (())
|
Ok (())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct DecoderThread {
|
||||||
|
join_handle: thread::JoinHandle <Result <()>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecoderThread {
|
||||||
|
pub fn new (
|
||||||
|
shared_state: Arc <(Mutex <SharedState>, Condvar)>,
|
||||||
|
filenames: Vec <String>,
|
||||||
|
) -> 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 {
|
struct AudioOutput {
|
||||||
host: cpal::Host,
|
host: cpal::Host,
|
||||||
device: cpal::Device,
|
device: cpal::Device,
|
||||||
|
@ -223,8 +234,9 @@ struct AudioOutput {
|
||||||
impl AudioOutput {
|
impl AudioOutput {
|
||||||
pub fn new (
|
pub fn new (
|
||||||
pcm_quit: Arc <(Mutex <bool>, Condvar)>,
|
pcm_quit: Arc <(Mutex <bool>, Condvar)>,
|
||||||
pair: Arc <(Mutex <SharedState>, Condvar)>,
|
shared_state: Arc <(Mutex <SharedState>, Condvar)>,
|
||||||
) -> Result <Self> {
|
) -> Result <Self>
|
||||||
|
{
|
||||||
let host = cpal::default_host ();
|
let host = cpal::default_host ();
|
||||||
let device = host.default_output_device ().ok_or_else (|| anyhow! ("can't open cpal device"))?;
|
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 (
|
let stream = device.build_output_stream (
|
||||||
&config,
|
&config,
|
||||||
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
move |data: &mut [f32], _: &cpal::OutputCallbackInfo| {
|
||||||
let (lock, cvar) = &*pair;
|
let (lock, cvar) = &*shared_state;
|
||||||
|
|
||||||
let time_start = Instant::now ();
|
let time_start = Instant::now ();
|
||||||
let mut decoder_state = match lock.lock () {
|
let mut decoder_state = match lock.lock () {
|
||||||
|
@ -281,6 +293,14 @@ impl AudioOutput {
|
||||||
stream,
|
stream,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn play (&mut self) -> Result <()> {
|
||||||
|
Ok (self.stream.play ()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pause (&mut self) -> Result <()> {
|
||||||
|
Ok (self.stream.pause ()?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg (test)]
|
#[cfg (test)]
|
||||||
|
|
Loading…
Reference in New Issue