From: Thomas Karpiniec Date: Tue, 11 Feb 2025 11:17:53 +0000 (+1100) Subject: Configurable output card for codec2 adapter X-Git-Url: https://code.octet-stream.net/m17rt/commitdiff_plain Configurable output card for codec2 adapter --- diff --git a/m17codec2/src/lib.rs b/m17codec2/src/lib.rs index 2f05701..879000d 100755 --- a/m17codec2/src/lib.rs +++ b/m17codec2/src/lib.rs @@ -47,8 +47,7 @@ pub fn decode_codec2>(data: &[u8], out_path: P) -> Vec { /// Subscribes to M17 streams and attempts to play the decoded Codec2 pub struct Codec2Adapter { state: Arc>, - // TODO: make this configurable - output_card: String, + output_card: Option, } impl Codec2Adapter { @@ -61,9 +60,13 @@ impl Codec2Adapter { end_tx: None, })), // TODO: this doesn't work on rpi. Use default_output_device() by default - output_card: "default".to_owned(), + output_card: None, } } + + pub fn set_output_card>(&mut self, card_name: S) { + self.output_card = Some(card_name.into()); + } } impl Default for Codec2Adapter { @@ -139,28 +142,38 @@ fn stream_thread( end: Receiver<()>, setup_tx: Sender>, state: Arc>, - output_card: String, + output_card: Option, ) { let host = cpal::default_host(); - let device = match host - .output_devices() - .unwrap() - .find(|d| d.name().unwrap() == output_card) - { - Some(d) => d, - None => { - let _ = setup_tx.send(Err(M17Codec2Error::CardUnavailable(output_card).into())); - return; + let device = if let Some(output_card) = output_card { + // TODO: more error handling for unwraps + match host + .output_devices() + .unwrap() + .find(|d| d.name().unwrap() == output_card) + { + Some(d) => d, + None => { + let _ = setup_tx.send(Err(M17Codec2Error::CardUnavailable(output_card).into())); + return; + } + } + } else { + match host.default_output_device() { + Some(d) => d, + None => { + let _ = setup_tx.send(Err(M17Codec2Error::DefaultCardUnavailable.into())); + return; + } } }; + let card_name = device.name().unwrap(); let mut configs = match device.supported_output_configs() { Ok(c) => c, Err(e) => { - let _ = setup_tx.send(Err(M17Codec2Error::OutputConfigsUnavailable( - output_card, - e, - ) - .into())); + let _ = setup_tx.send(Err( + M17Codec2Error::OutputConfigsUnavailable(card_name, e).into() + )); return; } }; @@ -171,7 +184,7 @@ fn stream_thread( Some(c) => c, None => { let _ = setup_tx.send(Err( - M17Codec2Error::SupportedOutputUnavailable(output_card).into() + M17Codec2Error::SupportedOutputUnavailable(card_name).into() )); return; } @@ -192,7 +205,7 @@ fn stream_thread( Ok(s) => s, Err(e) => { let _ = setup_tx.send(Err( - M17Codec2Error::OutputStreamBuildError(output_card, e).into() + M17Codec2Error::OutputStreamBuildError(card_name, e).into() )); return; } @@ -201,7 +214,7 @@ fn stream_thread( Ok(()) => (), Err(e) => { let _ = setup_tx.send(Err( - M17Codec2Error::OutputStreamPlayError(output_card, e).into() + M17Codec2Error::OutputStreamPlayError(card_name, e).into() )); return; } @@ -284,6 +297,9 @@ pub enum M17Codec2Error { #[error("selected card '{0}' does not exist or is in use")] CardUnavailable(String), + #[error("default output card is unavailable")] + DefaultCardUnavailable, + #[error("selected card '{0}' failed to list available output configs: '{1}'")] OutputConfigsUnavailable(String, #[source] cpal::SupportedStreamConfigsError),