- SoundcardEvent::StartOutput { event_tx, buffer } => {
- let mut output_configs = device.supported_output_configs().unwrap();
- // TODO: more error handling
- let output_config = output_configs
- .find(|c| c.channels() == 1 && c.sample_format() == SampleFormat::I16)
- .unwrap()
- .with_sample_rate(SampleRate(48000));
- let stream = device
- .build_output_stream(
- &output_config.into(),
- move |data: &mut [i16], info: &cpal::OutputCallbackInfo| {
- let mut taken = 0;
- let ts = info.timestamp();
- let latency = ts
- .playback
- .duration_since(&ts.callback)
- .unwrap_or(Duration::ZERO);
- let mut buffer = buffer.write().unwrap();
- buffer.latency = latency;
- for out in data.iter_mut() {
- if let Some(s) = buffer.samples.pop_front() {
- *out = if tx_inverted { s.saturating_neg() } else { s };
- taken += 1;
- } else if buffer.idling {
- *out = 0;
- } else {
- log::debug!("output soundcard had underrun");
- let _ = event_tx.send(SoundmodemEvent::OutputUnderrun);
- break;
- }
+ SoundcardEvent::StartOutput {
+ event_tx,
+ buffer,
+ errors,
+ } => {
+ let mut output_configs = match device.supported_output_configs() {
+ Ok(c) => c,
+ Err(e) => {
+ errors.send_error(SoundcardError::SupportedConfigs(e));
+ continue;
+ }
+ };
+ let output_config = match output_configs.find(|c| config_is_compatible(c)) {
+ Some(c) => c,
+ None => {
+ errors.send_error(SoundcardError::NoValidConfigAvailable);
+ continue;
+ }
+ };
+ let output_config = output_config.with_sample_rate(SampleRate(48000));
+ let channels = output_config.channels();
+ let errors_1 = errors.clone();
+ let stream = match device.build_output_stream(
+ &output_config.into(),
+ move |data: &mut [i16], info: &cpal::OutputCallbackInfo| {
+ let mut taken = 0;
+ let ts = info.timestamp();
+ let latency = ts
+ .playback
+ .duration_since(&ts.callback)
+ .unwrap_or(Duration::ZERO);
+ let mut buffer = buffer.write().unwrap();
+ buffer.latency = latency;
+ for out in data.chunks_mut(channels as usize) {
+ if let Some(s) = buffer.samples.pop_front() {
+ out.fill(if tx_inverted { s.saturating_neg() } else { s });
+ taken += 1;
+ } else if buffer.idling {
+ out.fill(0);
+ } else {
+ let _ = event_tx.send(SoundmodemEvent::OutputUnderrun);
+ break;