]> code.octet-stream.net Git - m17rt/blobdiff - m17codec2/src/rx.rs
Remove unneeded cpal dep
[m17rt] / m17codec2 / src / rx.rs
index c6d3cdc2504d82b5e023b5c75a8fdcb2d1653180..5649519c2b50b2acbf5316acee0f90f5e33731df 100644 (file)
@@ -50,7 +50,6 @@ impl Codec2RxAdapter {
     pub fn new() -> Self {
         Self {
             state: Arc::new(Mutex::new(AdapterState {
-                tx: None,
                 out_buf: VecDeque::new(),
                 codec2: Codec2::new(Codec2Mode::MODE_3200),
                 end_tx: None,
@@ -63,6 +62,33 @@ impl Codec2RxAdapter {
     pub fn set_output_card<S: Into<String>>(&mut self, card_name: S) {
         self.output_card = Some(card_name.into());
     }
+
+    /// List sound cards supported for audio output.
+    ///
+    /// M17RT will handle any card with 1 or 2 channels and 16-bit output.
+    pub fn supported_output_cards() -> Vec<String> {
+        let mut out = vec![];
+        let host = cpal::default_host();
+        let Ok(output_devices) = host.output_devices() else {
+            return out;
+        };
+        for d in output_devices {
+            let Ok(mut configs) = d.supported_output_configs() else {
+                continue;
+            };
+            if configs.any(|config| {
+                (config.channels() == 1 || config.channels() == 2)
+                    && config.sample_format() == SampleFormat::I16
+            }) {
+                let Ok(name) = d.name() else {
+                    continue;
+                };
+                out.push(name);
+            }
+        }
+        out.sort();
+        out
+    }
 }
 
 impl Default for Codec2RxAdapter {
@@ -72,7 +98,6 @@ impl Default for Codec2RxAdapter {
 }
 
 struct AdapterState {
-    tx: Option<TxHandle>,
     /// Circular buffer of output samples for playback
     out_buf: VecDeque<i16>,
     codec2: Codec2,
@@ -81,9 +106,7 @@ struct AdapterState {
 }
 
 impl StreamAdapter for Codec2RxAdapter {
-    fn start(&self, handle: TxHandle) -> Result<(), AdapterError> {
-        self.state.lock().unwrap().tx = Some(handle);
-
+    fn start(&self, _handle: TxHandle) -> Result<(), AdapterError> {
         let (end_tx, end_rx) = channel();
         let (setup_tx, setup_rx) = channel();
         let state = self.state.clone();
@@ -92,7 +115,7 @@ impl StreamAdapter for Codec2RxAdapter {
         self.state.lock().unwrap().end_tx = Some(end_tx);
         // Propagate any errors arising in the thread
         let sample_rate = setup_rx.recv()??;
-        debug!("selected codec2 output sample rate {sample_rate}");
+        debug!("selected codec2 speaker sample rate {sample_rate}");
         if sample_rate != 8000 {
             let params = SincInterpolationParameters {
                 sinc_len: 256,
@@ -110,7 +133,6 @@ impl StreamAdapter for Codec2RxAdapter {
 
     fn close(&self) -> Result<(), AdapterError> {
         let mut state = self.state.lock().unwrap();
-        state.tx = None;
         state.end_tx = None;
         Ok(())
     }