♻️ 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, | ||||
| } | ||||
| 
 | ||||
| fn cmd_gui (args: &[String]) -> Result <()> { | ||||
| fn cmd_gui (_args: &[String]) -> Result <()> { | ||||
| 	let (fltk_tx, fltk_rx) = app::channel::<Message> (); | ||||
| 	
 | ||||
| 	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 <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 { | ||||
| 	host: cpal::Host, | ||||
| 	device: cpal::Device, | ||||
|  | @ -223,8 +234,9 @@ struct AudioOutput { | |||
| impl AudioOutput { | ||||
| 	pub fn new ( | ||||
| 		pcm_quit: Arc <(Mutex <bool>, Condvar)>, | ||||
| 		pair: Arc <(Mutex <SharedState>, Condvar)>, | ||||
| 	) -> Result <Self> { | ||||
| 		shared_state: Arc <(Mutex <SharedState>, Condvar)>, | ||||
| 	) -> Result <Self> 
 | ||||
| 	{ | ||||
| 		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)] | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 _
						_