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,
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 {
}
struct AdapterState {
- tx: Option<TxHandle>,
/// Circular buffer of output samples for playback
out_buf: VecDeque<i16>,
codec2: Codec2,
}
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();
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,
fn close(&self) -> Result<(), AdapterError> {
let mut state = self.state.lock().unwrap();
- state.tx = None;
state.end_tx = None;
Ok(())
}