1 use crate::{
2     BackendSpecificError, BufferSize, Data, DefaultStreamConfigError, DeviceNameError,
3     DevicesError, InputCallbackInfo, OutputCallbackInfo, SampleFormat, SampleRate, StreamConfig,
4     SupportedBufferSize, SupportedStreamConfig, SupportedStreamConfigRange,
5     SupportedStreamConfigsError, COMMON_SAMPLE_RATES,
6 };
7 use std;
8 use std::ffi::OsString;
9 use std::fmt;
10 use std::io::Error as IoError;
11 use std::mem;
12 use std::ops::{Deref, DerefMut};
13 use std::os::windows::ffi::OsStringExt;
14 use std::ptr;
15 use std::slice;
16 use std::sync::{Arc, Mutex, MutexGuard};
17 
18 use super::check_result;
19 use super::check_result_backend_specific;
20 use super::com;
21 use super::winapi::ctypes::c_void;
22 use super::winapi::shared::devpkey;
23 use super::winapi::shared::guiddef::GUID;
24 use super::winapi::shared::ksmedia;
25 use super::winapi::shared::minwindef::{DWORD, WORD};
26 use super::winapi::shared::mmreg;
27 use super::winapi::shared::winerror;
28 use super::winapi::shared::wtypes;
29 use super::winapi::Interface;
30 
31 // https://msdn.microsoft.com/en-us/library/cc230355.aspx
32 use super::winapi::um::audioclient::{
33     self, IAudioClient, IID_IAudioClient, AUDCLNT_E_DEVICE_INVALIDATED,
34 };
35 use super::winapi::um::audiosessiontypes::{
36     AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, AUDCLNT_STREAMFLAGS_LOOPBACK,
37 };
38 use super::winapi::um::combaseapi::{
39     CoCreateInstance, CoTaskMemFree, PropVariantClear, CLSCTX_ALL,
40 };
41 use super::winapi::um::coml2api;
42 use super::winapi::um::mmdeviceapi::{
43     eAll, eCapture, eConsole, eRender, CLSID_MMDeviceEnumerator, EDataFlow, IMMDevice,
44     IMMDeviceCollection, IMMDeviceEnumerator, IMMEndpoint, DEVICE_STATE_ACTIVE,
45 };
46 use super::winapi::um::winnt::{LPWSTR, WCHAR};
47 
48 use super::{
49     stream::{AudioClientFlow, Stream, StreamInner},
50     winapi::um::synchapi,
51 };
52 use crate::{traits::DeviceTrait, BuildStreamError, StreamError};
53 
54 pub type SupportedInputConfigs = std::vec::IntoIter<SupportedStreamConfigRange>;
55 pub type SupportedOutputConfigs = std::vec::IntoIter<SupportedStreamConfigRange>;
56 
57 /// Wrapper because of that stupid decision to remove `Send` and `Sync` from raw pointers.
58 #[derive(Copy, Clone)]
59 struct IAudioClientWrapper(*mut IAudioClient);
60 unsafe impl Send for IAudioClientWrapper {}
61 unsafe impl Sync for IAudioClientWrapper {}
62 
63 /// An opaque type that identifies an end point.
64 pub struct Device {
65     device: *mut IMMDevice,
66     /// We cache an uninitialized `IAudioClient` so that we can call functions from it without
67     /// having to create/destroy audio clients all the time.
68     future_audio_client: Arc<Mutex<Option<IAudioClientWrapper>>>, // TODO: add NonZero around the ptr
69 }
70 
71 impl DeviceTrait for Device {
72     type SupportedInputConfigs = SupportedInputConfigs;
73     type SupportedOutputConfigs = SupportedOutputConfigs;
74     type Stream = Stream;
75 
name(&self) -> Result<String, DeviceNameError>76     fn name(&self) -> Result<String, DeviceNameError> {
77         Device::name(self)
78     }
79 
supported_input_configs( &self, ) -> Result<Self::SupportedInputConfigs, SupportedStreamConfigsError>80     fn supported_input_configs(
81         &self,
82     ) -> Result<Self::SupportedInputConfigs, SupportedStreamConfigsError> {
83         Device::supported_input_configs(self)
84     }
85 
supported_output_configs( &self, ) -> Result<Self::SupportedOutputConfigs, SupportedStreamConfigsError>86     fn supported_output_configs(
87         &self,
88     ) -> Result<Self::SupportedOutputConfigs, SupportedStreamConfigsError> {
89         Device::supported_output_configs(self)
90     }
91 
default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>92     fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
93         Device::default_input_config(self)
94     }
95 
default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>96     fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
97         Device::default_output_config(self)
98     }
99 
build_input_stream_raw<D, E>( &self, config: &StreamConfig, sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result<Self::Stream, BuildStreamError> where D: FnMut(&Data, &InputCallbackInfo) + Send + 'static, E: FnMut(StreamError) + Send + 'static,100     fn build_input_stream_raw<D, E>(
101         &self,
102         config: &StreamConfig,
103         sample_format: SampleFormat,
104         data_callback: D,
105         error_callback: E,
106     ) -> Result<Self::Stream, BuildStreamError>
107     where
108         D: FnMut(&Data, &InputCallbackInfo) + Send + 'static,
109         E: FnMut(StreamError) + Send + 'static,
110     {
111         let stream_inner = self.build_input_stream_raw_inner(config, sample_format)?;
112         Ok(Stream::new_input(
113             stream_inner,
114             data_callback,
115             error_callback,
116         ))
117     }
118 
build_output_stream_raw<D, E>( &self, config: &StreamConfig, sample_format: SampleFormat, data_callback: D, error_callback: E, ) -> Result<Self::Stream, BuildStreamError> where D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static, E: FnMut(StreamError) + Send + 'static,119     fn build_output_stream_raw<D, E>(
120         &self,
121         config: &StreamConfig,
122         sample_format: SampleFormat,
123         data_callback: D,
124         error_callback: E,
125     ) -> Result<Self::Stream, BuildStreamError>
126     where
127         D: FnMut(&mut Data, &OutputCallbackInfo) + Send + 'static,
128         E: FnMut(StreamError) + Send + 'static,
129     {
130         let stream_inner = self.build_output_stream_raw_inner(config, sample_format)?;
131         Ok(Stream::new_output(
132             stream_inner,
133             data_callback,
134             error_callback,
135         ))
136     }
137 }
138 
139 struct Endpoint {
140     endpoint: *mut IMMEndpoint,
141 }
142 
143 enum WaveFormat {
144     Ex(mmreg::WAVEFORMATEX),
145     Extensible(mmreg::WAVEFORMATEXTENSIBLE),
146 }
147 
148 // Use RAII to make sure CoTaskMemFree is called when we are responsible for freeing.
149 struct WaveFormatExPtr(*mut mmreg::WAVEFORMATEX);
150 
151 impl Drop for WaveFormatExPtr {
drop(&mut self)152     fn drop(&mut self) {
153         unsafe {
154             CoTaskMemFree(self.0 as *mut _);
155         }
156     }
157 }
158 
159 impl WaveFormat {
160     // Given a pointer to some format, returns a valid copy of the format.
copy_from_waveformatex_ptr(ptr: *const mmreg::WAVEFORMATEX) -> Option<Self>161     pub fn copy_from_waveformatex_ptr(ptr: *const mmreg::WAVEFORMATEX) -> Option<Self> {
162         unsafe {
163             match (*ptr).wFormatTag {
164                 mmreg::WAVE_FORMAT_PCM | mmreg::WAVE_FORMAT_IEEE_FLOAT => {
165                     Some(WaveFormat::Ex(*ptr))
166                 }
167                 mmreg::WAVE_FORMAT_EXTENSIBLE => {
168                     let extensible_ptr = ptr as *const mmreg::WAVEFORMATEXTENSIBLE;
169                     Some(WaveFormat::Extensible(*extensible_ptr))
170                 }
171                 _ => None,
172             }
173         }
174     }
175 
176     // Get the pointer to the WAVEFORMATEX struct.
as_ptr(&self) -> *const mmreg::WAVEFORMATEX177     pub fn as_ptr(&self) -> *const mmreg::WAVEFORMATEX {
178         self.deref() as *const _
179     }
180 }
181 
182 impl Deref for WaveFormat {
183     type Target = mmreg::WAVEFORMATEX;
deref(&self) -> &Self::Target184     fn deref(&self) -> &Self::Target {
185         match *self {
186             WaveFormat::Ex(ref f) => f,
187             WaveFormat::Extensible(ref f) => &f.Format,
188         }
189     }
190 }
191 
192 impl DerefMut for WaveFormat {
deref_mut(&mut self) -> &mut Self::Target193     fn deref_mut(&mut self) -> &mut Self::Target {
194         match *self {
195             WaveFormat::Ex(ref mut f) => f,
196             WaveFormat::Extensible(ref mut f) => &mut f.Format,
197         }
198     }
199 }
200 
immendpoint_from_immdevice(device: *const IMMDevice) -> *mut IMMEndpoint201 unsafe fn immendpoint_from_immdevice(device: *const IMMDevice) -> *mut IMMEndpoint {
202     let mut endpoint: *mut IMMEndpoint = ptr::null_mut();
203     check_result(
204         (*device).QueryInterface(&IMMEndpoint::uuidof(), &mut endpoint as *mut _ as *mut _),
205     )
206     .expect("could not query IMMDevice interface for IMMEndpoint");
207     endpoint
208 }
209 
data_flow_from_immendpoint(endpoint: *const IMMEndpoint) -> EDataFlow210 unsafe fn data_flow_from_immendpoint(endpoint: *const IMMEndpoint) -> EDataFlow {
211     let mut data_flow = std::mem::MaybeUninit::<EDataFlow>::uninit();
212     check_result((*endpoint).GetDataFlow(data_flow.as_mut_ptr()))
213         .expect("could not get endpoint data_flow");
214     data_flow.assume_init()
215 }
216 
217 // Given the audio client and format, returns whether or not the format is supported.
is_format_supported( client: *const IAudioClient, waveformatex_ptr: *const mmreg::WAVEFORMATEX, ) -> Result<bool, SupportedStreamConfigsError>218 pub unsafe fn is_format_supported(
219     client: *const IAudioClient,
220     waveformatex_ptr: *const mmreg::WAVEFORMATEX,
221 ) -> Result<bool, SupportedStreamConfigsError> {
222     /*
223     // `IsFormatSupported` checks whether the format is supported and fills
224     // a `WAVEFORMATEX`
225     let mut dummy_fmt_ptr: *mut mmreg::WAVEFORMATEX = mem::uninitialized();
226     let hresult =
227         (*audio_client)
228             .IsFormatSupported(share_mode, &format_attempt.Format, &mut dummy_fmt_ptr);
229     // we free that `WAVEFORMATEX` immediately after because we don't need it
230     if !dummy_fmt_ptr.is_null() {
231         CoTaskMemFree(dummy_fmt_ptr as *mut _);
232     }
233 
234     // `IsFormatSupported` can return `S_FALSE` (which means that a compatible format
235     // has been found), but we also treat this as an error
236     match (hresult, check_result(hresult)) {
237         (_, Err(ref e))
238             if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
239             (*audio_client).Release();
240             return Err(BuildStreamError::DeviceNotAvailable);
241         },
242         (_, Err(e)) => {
243             (*audio_client).Release();
244             panic!("{:?}", e);
245         },
246         (winerror::S_FALSE, _) => {
247             (*audio_client).Release();
248             return Err(BuildStreamError::StreamConfigNotSupported);
249         },
250         (_, Ok(())) => (),
251     };
252     */
253 
254     // Check if the given format is supported.
255     let is_supported = |waveformatex_ptr, mut closest_waveformatex_ptr| {
256         let result = (*client).IsFormatSupported(
257             AUDCLNT_SHAREMODE_SHARED,
258             waveformatex_ptr,
259             &mut closest_waveformatex_ptr,
260         );
261         // `IsFormatSupported` can return `S_FALSE` (which means that a compatible format
262         // has been found, but not an exact match) so we also treat this as unsupported.
263         match (result, check_result(result)) {
264             (_, Err(ref e)) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
265                 Err(SupportedStreamConfigsError::DeviceNotAvailable)
266             }
267             (_, Err(_)) => Ok(false),
268             (winerror::S_FALSE, _) => Ok(false),
269             (_, Ok(())) => Ok(true),
270         }
271     };
272 
273     // First we want to retrieve a pointer to the `WAVEFORMATEX`.
274     // Although `GetMixFormat` writes the format to a given `WAVEFORMATEX` pointer,
275     // the pointer itself may actually point to a `WAVEFORMATEXTENSIBLE` structure.
276     // We check the wFormatTag to determine this and get a pointer to the correct type.
277     match (*waveformatex_ptr).wFormatTag {
278         mmreg::WAVE_FORMAT_PCM | mmreg::WAVE_FORMAT_IEEE_FLOAT => {
279             let mut closest_waveformatex = *waveformatex_ptr;
280             let closest_waveformatex_ptr = &mut closest_waveformatex as *mut _;
281             is_supported(waveformatex_ptr, closest_waveformatex_ptr)
282         }
283         mmreg::WAVE_FORMAT_EXTENSIBLE => {
284             let waveformatextensible_ptr = waveformatex_ptr as *const mmreg::WAVEFORMATEXTENSIBLE;
285             let mut closest_waveformatextensible = *waveformatextensible_ptr;
286             let closest_waveformatextensible_ptr = &mut closest_waveformatextensible as *mut _;
287             let closest_waveformatex_ptr =
288                 closest_waveformatextensible_ptr as *mut mmreg::WAVEFORMATEX;
289             is_supported(waveformatex_ptr, closest_waveformatex_ptr)
290         }
291         _ => Ok(false),
292     }
293 }
294 
295 // Get a cpal Format from a WAVEFORMATEX.
format_from_waveformatex_ptr( waveformatex_ptr: *const mmreg::WAVEFORMATEX, ) -> Option<SupportedStreamConfig>296 unsafe fn format_from_waveformatex_ptr(
297     waveformatex_ptr: *const mmreg::WAVEFORMATEX,
298 ) -> Option<SupportedStreamConfig> {
299     fn cmp_guid(a: &GUID, b: &GUID) -> bool {
300         a.Data1 == b.Data1 && a.Data2 == b.Data2 && a.Data3 == b.Data3 && a.Data4 == b.Data4
301     }
302     let sample_format = match (
303         (*waveformatex_ptr).wBitsPerSample,
304         (*waveformatex_ptr).wFormatTag,
305     ) {
306         (16, mmreg::WAVE_FORMAT_PCM) => SampleFormat::I16,
307         (32, mmreg::WAVE_FORMAT_IEEE_FLOAT) => SampleFormat::F32,
308         (n_bits, mmreg::WAVE_FORMAT_EXTENSIBLE) => {
309             let waveformatextensible_ptr = waveformatex_ptr as *const mmreg::WAVEFORMATEXTENSIBLE;
310             let sub = (*waveformatextensible_ptr).SubFormat;
311             if n_bits == 16 && cmp_guid(&sub, &ksmedia::KSDATAFORMAT_SUBTYPE_PCM) {
312                 SampleFormat::I16
313             } else if n_bits == 32 && cmp_guid(&sub, &ksmedia::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT) {
314                 SampleFormat::F32
315             } else {
316                 return None;
317             }
318         }
319         // Unknown data format returned by GetMixFormat.
320         _ => return None,
321     };
322 
323     let format = SupportedStreamConfig {
324         channels: (*waveformatex_ptr).nChannels as _,
325         sample_rate: SampleRate((*waveformatex_ptr).nSamplesPerSec),
326         buffer_size: SupportedBufferSize::Unknown,
327         sample_format,
328     };
329     Some(format)
330 }
331 
332 unsafe impl Send for Device {}
333 unsafe impl Sync for Device {}
334 
335 impl Device {
name(&self) -> Result<String, DeviceNameError>336     pub fn name(&self) -> Result<String, DeviceNameError> {
337         unsafe {
338             // Open the device's property store.
339             let mut property_store = ptr::null_mut();
340             (*self.device).OpenPropertyStore(coml2api::STGM_READ, &mut property_store);
341 
342             // Get the endpoint's friendly-name property.
343             let mut property_value = mem::zeroed();
344             if let Err(err) = check_result((*property_store).GetValue(
345                 &devpkey::DEVPKEY_Device_FriendlyName as *const _ as *const _,
346                 &mut property_value,
347             )) {
348                 let description = format!("failed to retrieve name from property store: {}", err);
349                 let err = BackendSpecificError { description };
350                 return Err(err.into());
351             }
352 
353             // Read the friendly-name from the union data field, expecting a *const u16.
354             if property_value.vt != wtypes::VT_LPWSTR as _ {
355                 let description = format!(
356                     "property store produced invalid data: {:?}",
357                     property_value.vt
358                 );
359                 let err = BackendSpecificError { description };
360                 return Err(err.into());
361             }
362             let ptr_utf16 = *(&property_value.data as *const _ as *const *const u16);
363 
364             // Find the length of the friendly name.
365             let mut len = 0;
366             while *ptr_utf16.offset(len) != 0 {
367                 len += 1;
368             }
369 
370             // Create the utf16 slice and covert it into a string.
371             let name_slice = slice::from_raw_parts(ptr_utf16, len as usize);
372             let name_os_string: OsString = OsStringExt::from_wide(name_slice);
373             let name_string = match name_os_string.into_string() {
374                 Ok(string) => string,
375                 Err(os_string) => os_string.to_string_lossy().into(),
376             };
377 
378             // Clean up the property.
379             PropVariantClear(&mut property_value);
380 
381             Ok(name_string)
382         }
383     }
384 
385     #[inline]
from_immdevice(device: *mut IMMDevice) -> Self386     fn from_immdevice(device: *mut IMMDevice) -> Self {
387         Device {
388             device,
389             future_audio_client: Arc::new(Mutex::new(None)),
390         }
391     }
392 
393     /// Ensures that `future_audio_client` contains a `Some` and returns a locked mutex to it.
ensure_future_audio_client( &self, ) -> Result<MutexGuard<Option<IAudioClientWrapper>>, IoError>394     fn ensure_future_audio_client(
395         &self,
396     ) -> Result<MutexGuard<Option<IAudioClientWrapper>>, IoError> {
397         let mut lock = self.future_audio_client.lock().unwrap();
398         if lock.is_some() {
399             return Ok(lock);
400         }
401 
402         let audio_client: *mut IAudioClient = unsafe {
403             let mut audio_client = ptr::null_mut();
404             let hresult = (*self.device).Activate(
405                 &IID_IAudioClient,
406                 CLSCTX_ALL,
407                 ptr::null_mut(),
408                 &mut audio_client,
409             );
410 
411             // can fail if the device has been disconnected since we enumerated it, or if
412             // the device doesn't support playback for some reason
413             check_result(hresult)?;
414             assert!(!audio_client.is_null());
415             audio_client as *mut _
416         };
417 
418         *lock = Some(IAudioClientWrapper(audio_client));
419         Ok(lock)
420     }
421 
422     /// Returns an uninitialized `IAudioClient`.
423     #[inline]
build_audioclient(&self) -> Result<*mut IAudioClient, IoError>424     pub(crate) fn build_audioclient(&self) -> Result<*mut IAudioClient, IoError> {
425         let mut lock = self.ensure_future_audio_client()?;
426         let client = lock.unwrap().0;
427         *lock = None;
428         Ok(client)
429     }
430 
431     // There is no way to query the list of all formats that are supported by the
432     // audio processor, so instead we just trial some commonly supported formats.
433     //
434     // Common formats are trialed by first getting the default format (returned via
435     // `GetMixFormat`) and then mutating that format with common sample rates and
436     // querying them via `IsFormatSupported`.
437     //
438     // When calling `IsFormatSupported` with the shared-mode audio engine, only the default
439     // number of channels seems to be supported. Any, more or less returns an invalid
440     // parameter error. Thus, we just assume that the default number of channels is the only
441     // number supported.
supported_formats(&self) -> Result<SupportedInputConfigs, SupportedStreamConfigsError>442     fn supported_formats(&self) -> Result<SupportedInputConfigs, SupportedStreamConfigsError> {
443         // initializing COM because we call `CoTaskMemFree` to release the format.
444         com::com_initialized();
445 
446         // Retrieve the `IAudioClient`.
447         let lock = match self.ensure_future_audio_client() {
448             Ok(lock) => lock,
449             Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
450                 return Err(SupportedStreamConfigsError::DeviceNotAvailable)
451             }
452             Err(e) => {
453                 let description = format!("{}", e);
454                 let err = BackendSpecificError { description };
455                 return Err(err.into());
456             }
457         };
458         let client = lock.unwrap().0;
459 
460         unsafe {
461             // Retrieve the pointer to the default WAVEFORMATEX.
462             let mut default_waveformatex_ptr = WaveFormatExPtr(ptr::null_mut());
463             match check_result((*client).GetMixFormat(&mut default_waveformatex_ptr.0)) {
464                 Ok(()) => (),
465                 Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
466                     return Err(SupportedStreamConfigsError::DeviceNotAvailable);
467                 }
468                 Err(e) => {
469                     let description = format!("{}", e);
470                     let err = BackendSpecificError { description };
471                     return Err(err.into());
472                 }
473             };
474 
475             // If the default format can't succeed we have no hope of finding other formats.
476             assert_eq!(
477                 is_format_supported(client, default_waveformatex_ptr.0)?,
478                 true
479             );
480 
481             // Copy the format to use as a test format (as to avoid mutating the original format).
482             let mut test_format = {
483                 match WaveFormat::copy_from_waveformatex_ptr(default_waveformatex_ptr.0) {
484                     Some(f) => f,
485                     // If the format is neither EX nor EXTENSIBLE we don't know how to work with it.
486                     None => return Ok(vec![].into_iter()),
487                 }
488             };
489 
490             // Begin testing common sample rates.
491             //
492             // NOTE: We should really be testing for whole ranges here, but it is infeasible to
493             // test every sample rate up to the overflow limit as the `IsFormatSupported` method is
494             // quite slow.
495             let mut supported_sample_rates: Vec<u32> = Vec::new();
496             for &rate in COMMON_SAMPLE_RATES {
497                 let rate = rate.0 as DWORD;
498                 test_format.nSamplesPerSec = rate;
499                 test_format.nAvgBytesPerSec =
500                     rate * u32::from((*default_waveformatex_ptr.0).nBlockAlign);
501                 if is_format_supported(client, test_format.as_ptr())? {
502                     supported_sample_rates.push(rate);
503                 }
504             }
505 
506             // If the common rates don't include the default one, add the default.
507             let default_sr = (*default_waveformatex_ptr.0).nSamplesPerSec as _;
508             if !supported_sample_rates.iter().any(|&r| r == default_sr) {
509                 supported_sample_rates.push(default_sr);
510             }
511 
512             // Reset the sample rate on the test format now that we're done.
513             test_format.nSamplesPerSec = (*default_waveformatex_ptr.0).nSamplesPerSec;
514             test_format.nAvgBytesPerSec = (*default_waveformatex_ptr.0).nAvgBytesPerSec;
515 
516             // TODO: Test the different sample formats?
517 
518             // Create the supported formats.
519             let format = match format_from_waveformatex_ptr(default_waveformatex_ptr.0) {
520                 Some(fmt) => fmt,
521                 None => {
522                     let description =
523                         "could not create a `cpal::SupportedStreamConfig` from a `WAVEFORMATEX`"
524                             .to_string();
525                     let err = BackendSpecificError { description };
526                     return Err(err.into());
527                 }
528             };
529             let mut supported_formats = Vec::with_capacity(supported_sample_rates.len());
530             for rate in supported_sample_rates {
531                 supported_formats.push(SupportedStreamConfigRange {
532                     channels: format.channels.clone(),
533                     min_sample_rate: SampleRate(rate as _),
534                     max_sample_rate: SampleRate(rate as _),
535                     buffer_size: format.buffer_size.clone(),
536                     sample_format: format.sample_format.clone(),
537                 })
538             }
539             Ok(supported_formats.into_iter())
540         }
541     }
542 
supported_input_configs( &self, ) -> Result<SupportedInputConfigs, SupportedStreamConfigsError>543     pub fn supported_input_configs(
544         &self,
545     ) -> Result<SupportedInputConfigs, SupportedStreamConfigsError> {
546         if self.data_flow() == eCapture {
547             self.supported_formats()
548         // If it's an output device, assume no input formats.
549         } else {
550             Ok(vec![].into_iter())
551         }
552     }
553 
supported_output_configs( &self, ) -> Result<SupportedOutputConfigs, SupportedStreamConfigsError>554     pub fn supported_output_configs(
555         &self,
556     ) -> Result<SupportedOutputConfigs, SupportedStreamConfigsError> {
557         if self.data_flow() == eRender {
558             self.supported_formats()
559         // If it's an input device, assume no output formats.
560         } else {
561             Ok(vec![].into_iter())
562         }
563     }
564 
565     // We always create voices in shared mode, therefore all samples go through an audio
566     // processor to mix them together.
567     //
568     // One format is guaranteed to be supported, the one returned by `GetMixFormat`.
default_format(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>569     fn default_format(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
570         // initializing COM because we call `CoTaskMemFree`
571         com::com_initialized();
572 
573         let lock = match self.ensure_future_audio_client() {
574             Ok(lock) => lock,
575             Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
576                 return Err(DefaultStreamConfigError::DeviceNotAvailable)
577             }
578             Err(e) => {
579                 let description = format!("{}", e);
580                 let err = BackendSpecificError { description };
581                 return Err(err.into());
582             }
583         };
584         let client = lock.unwrap().0;
585 
586         unsafe {
587             let mut format_ptr = WaveFormatExPtr(ptr::null_mut());
588             match check_result((*client).GetMixFormat(&mut format_ptr.0)) {
589                 Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
590                     return Err(DefaultStreamConfigError::DeviceNotAvailable);
591                 }
592                 Err(e) => {
593                     let description = format!("{}", e);
594                     let err = BackendSpecificError { description };
595                     return Err(err.into());
596                 }
597                 Ok(()) => (),
598             };
599 
600             format_from_waveformatex_ptr(format_ptr.0)
601                 .ok_or(DefaultStreamConfigError::StreamTypeNotSupported)
602         }
603     }
604 
data_flow(&self) -> EDataFlow605     pub(crate) fn data_flow(&self) -> EDataFlow {
606         let endpoint = Endpoint::from(self.device as *const _);
607         endpoint.data_flow()
608     }
609 
default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>610     pub fn default_input_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
611         if self.data_flow() == eCapture {
612             self.default_format()
613         } else {
614             Err(DefaultStreamConfigError::StreamTypeNotSupported)
615         }
616     }
617 
default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError>618     pub fn default_output_config(&self) -> Result<SupportedStreamConfig, DefaultStreamConfigError> {
619         let data_flow = self.data_flow();
620         if data_flow == eRender {
621             self.default_format()
622         } else {
623             Err(DefaultStreamConfigError::StreamTypeNotSupported)
624         }
625     }
626 
build_input_stream_raw_inner( &self, config: &StreamConfig, sample_format: SampleFormat, ) -> Result<StreamInner, BuildStreamError>627     pub(crate) fn build_input_stream_raw_inner(
628         &self,
629         config: &StreamConfig,
630         sample_format: SampleFormat,
631     ) -> Result<StreamInner, BuildStreamError> {
632         unsafe {
633             // Making sure that COM is initialized.
634             // It's not actually sure that this is required, but when in doubt do it.
635             com::com_initialized();
636 
637             // Obtaining a `IAudioClient`.
638             let audio_client = match self.build_audioclient() {
639                 Ok(client) => client,
640                 Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
641                     return Err(BuildStreamError::DeviceNotAvailable)
642                 }
643                 Err(e) => {
644                     let description = format!("{}", e);
645                     let err = BackendSpecificError { description };
646                     return Err(err.into());
647                 }
648             };
649 
650             match config.buffer_size {
651                 BufferSize::Fixed(_) => {
652                     // TO DO: We need IAudioClient3 to get buffersize ranges first
653                     // Otherwise the supported ranges are unknown. In the meantime
654                     // the smallest buffersize is selected and used.
655                     return Err(BuildStreamError::StreamConfigNotSupported);
656                 }
657                 BufferSize::Default => (),
658             };
659 
660             let mut stream_flags: DWORD = AUDCLNT_STREAMFLAGS_EVENTCALLBACK;
661 
662             if self.data_flow() == eRender {
663                 stream_flags |= AUDCLNT_STREAMFLAGS_LOOPBACK;
664             }
665 
666             // Computing the format and initializing the device.
667             let waveformatex = {
668                 let format_attempt = config_to_waveformatextensible(config, sample_format)
669                     .ok_or(BuildStreamError::StreamConfigNotSupported)?;
670                 let share_mode = AUDCLNT_SHAREMODE_SHARED;
671 
672                 // Ensure the format is supported.
673                 match super::device::is_format_supported(audio_client, &format_attempt.Format) {
674                     Ok(false) => return Err(BuildStreamError::StreamConfigNotSupported),
675                     Err(_) => return Err(BuildStreamError::DeviceNotAvailable),
676                     _ => (),
677                 }
678 
679                 // Finally, initializing the audio client
680                 let hresult = (*audio_client).Initialize(
681                     share_mode,
682                     stream_flags,
683                     0,
684                     0,
685                     &format_attempt.Format,
686                     ptr::null(),
687                 );
688                 match check_result(hresult) {
689                     Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
690                         (*audio_client).Release();
691                         return Err(BuildStreamError::DeviceNotAvailable);
692                     }
693                     Err(e) => {
694                         (*audio_client).Release();
695                         let description = format!("{}", e);
696                         let err = BackendSpecificError { description };
697                         return Err(err.into());
698                     }
699                     Ok(()) => (),
700                 };
701 
702                 format_attempt.Format
703             };
704 
705             // obtaining the size of the samples buffer in number of frames
706             let max_frames_in_buffer = {
707                 let mut max_frames_in_buffer = 0u32;
708                 let hresult = (*audio_client).GetBufferSize(&mut max_frames_in_buffer);
709 
710                 match check_result(hresult) {
711                     Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
712                         (*audio_client).Release();
713                         return Err(BuildStreamError::DeviceNotAvailable);
714                     }
715                     Err(e) => {
716                         (*audio_client).Release();
717                         let description = format!("{}", e);
718                         let err = BackendSpecificError { description };
719                         return Err(err.into());
720                     }
721                     Ok(()) => (),
722                 };
723 
724                 max_frames_in_buffer
725             };
726 
727             // Creating the event that will be signalled whenever we need to submit some samples.
728             let event = {
729                 let event = synchapi::CreateEventA(ptr::null_mut(), 0, 0, ptr::null());
730                 if event.is_null() {
731                     (*audio_client).Release();
732                     let description = "failed to create event".to_string();
733                     let err = BackendSpecificError { description };
734                     return Err(err.into());
735                 }
736 
737                 if let Err(e) = check_result((*audio_client).SetEventHandle(event)) {
738                     (*audio_client).Release();
739                     let description = format!("failed to call SetEventHandle: {}", e);
740                     let err = BackendSpecificError { description };
741                     return Err(err.into());
742                 }
743 
744                 event
745             };
746 
747             // Building a `IAudioCaptureClient` that will be used to read captured samples.
748             let capture_client = {
749                 let mut capture_client: *mut audioclient::IAudioCaptureClient = ptr::null_mut();
750                 let hresult = (*audio_client).GetService(
751                     &audioclient::IID_IAudioCaptureClient,
752                     &mut capture_client as *mut *mut audioclient::IAudioCaptureClient as *mut _,
753                 );
754 
755                 match check_result(hresult) {
756                     Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
757                         (*audio_client).Release();
758                         return Err(BuildStreamError::DeviceNotAvailable);
759                     }
760                     Err(e) => {
761                         (*audio_client).Release();
762                         let description = format!("failed to build capture client: {}", e);
763                         let err = BackendSpecificError { description };
764                         return Err(err.into());
765                     }
766                     Ok(()) => (),
767                 };
768 
769                 &mut *capture_client
770             };
771 
772             // Once we built the `StreamInner`, we add a command that will be picked up by the
773             // `run()` method and added to the `RunContext`.
774             let client_flow = AudioClientFlow::Capture { capture_client };
775 
776             let audio_clock = get_audio_clock(audio_client).map_err(|err| {
777                 (*audio_client).Release();
778                 err
779             })?;
780 
781             Ok(StreamInner {
782                 audio_client,
783                 audio_clock,
784                 client_flow,
785                 event,
786                 playing: false,
787                 max_frames_in_buffer,
788                 bytes_per_frame: waveformatex.nBlockAlign,
789                 config: config.clone(),
790                 sample_format,
791             })
792         }
793     }
794 
build_output_stream_raw_inner( &self, config: &StreamConfig, sample_format: SampleFormat, ) -> Result<StreamInner, BuildStreamError>795     pub(crate) fn build_output_stream_raw_inner(
796         &self,
797         config: &StreamConfig,
798         sample_format: SampleFormat,
799     ) -> Result<StreamInner, BuildStreamError> {
800         unsafe {
801             // Making sure that COM is initialized.
802             // It's not actually sure that this is required, but when in doubt do it.
803             com::com_initialized();
804 
805             // Obtaining a `IAudioClient`.
806             let audio_client = match self.build_audioclient() {
807                 Ok(client) => client,
808                 Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
809                     return Err(BuildStreamError::DeviceNotAvailable)
810                 }
811                 Err(e) => {
812                     let description = format!("{}", e);
813                     let err = BackendSpecificError { description };
814                     return Err(err.into());
815                 }
816             };
817 
818             match config.buffer_size {
819                 BufferSize::Fixed(_) => {
820                     // TO DO: We need IAudioClient3 to get buffersize ranges first
821                     // Otherwise the supported ranges are unknown. In the meantime
822                     // the smallest buffersize is selected and used.
823                     return Err(BuildStreamError::StreamConfigNotSupported);
824                 }
825                 BufferSize::Default => (),
826             };
827 
828             // Computing the format and initializing the device.
829             let waveformatex = {
830                 let format_attempt = config_to_waveformatextensible(config, sample_format)
831                     .ok_or(BuildStreamError::StreamConfigNotSupported)?;
832                 let share_mode = AUDCLNT_SHAREMODE_SHARED;
833 
834                 // Ensure the format is supported.
835                 match super::device::is_format_supported(audio_client, &format_attempt.Format) {
836                     Ok(false) => return Err(BuildStreamError::StreamConfigNotSupported),
837                     Err(_) => return Err(BuildStreamError::DeviceNotAvailable),
838                     _ => (),
839                 }
840 
841                 // Finally, initializing the audio client
842                 let hresult = (*audio_client).Initialize(
843                     share_mode,
844                     AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
845                     0,
846                     0,
847                     &format_attempt.Format,
848                     ptr::null(),
849                 );
850 
851                 match check_result(hresult) {
852                     Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
853                         (*audio_client).Release();
854                         return Err(BuildStreamError::DeviceNotAvailable);
855                     }
856                     Err(e) => {
857                         (*audio_client).Release();
858                         let description = format!("{}", e);
859                         let err = BackendSpecificError { description };
860                         return Err(err.into());
861                     }
862                     Ok(()) => (),
863                 };
864 
865                 format_attempt.Format
866             };
867 
868             // Creating the event that will be signalled whenever we need to submit some samples.
869             let event = {
870                 let event = synchapi::CreateEventA(ptr::null_mut(), 0, 0, ptr::null());
871                 if event.is_null() {
872                     (*audio_client).Release();
873                     let description = "failed to create event".to_string();
874                     let err = BackendSpecificError { description };
875                     return Err(err.into());
876                 }
877 
878                 if let Err(e) = check_result((*audio_client).SetEventHandle(event)) {
879                     (*audio_client).Release();
880                     let description = format!("failed to call SetEventHandle: {}", e);
881                     let err = BackendSpecificError { description };
882                     return Err(err.into());
883                 };
884 
885                 event
886             };
887 
888             // obtaining the size of the samples buffer in number of frames
889             let max_frames_in_buffer = {
890                 let mut max_frames_in_buffer = 0u32;
891                 let hresult = (*audio_client).GetBufferSize(&mut max_frames_in_buffer);
892 
893                 match check_result(hresult) {
894                     Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
895                         (*audio_client).Release();
896                         return Err(BuildStreamError::DeviceNotAvailable);
897                     }
898                     Err(e) => {
899                         (*audio_client).Release();
900                         let description = format!("failed to obtain buffer size: {}", e);
901                         let err = BackendSpecificError { description };
902                         return Err(err.into());
903                     }
904                     Ok(()) => (),
905                 };
906 
907                 max_frames_in_buffer
908             };
909 
910             // Building a `IAudioRenderClient` that will be used to fill the samples buffer.
911             let render_client = {
912                 let mut render_client: *mut audioclient::IAudioRenderClient = ptr::null_mut();
913                 let hresult = (*audio_client).GetService(
914                     &audioclient::IID_IAudioRenderClient,
915                     &mut render_client as *mut *mut audioclient::IAudioRenderClient as *mut _,
916                 );
917 
918                 match check_result(hresult) {
919                     Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
920                         (*audio_client).Release();
921                         return Err(BuildStreamError::DeviceNotAvailable);
922                     }
923                     Err(e) => {
924                         (*audio_client).Release();
925                         let description = format!("failed to build render client: {}", e);
926                         let err = BackendSpecificError { description };
927                         return Err(err.into());
928                     }
929                     Ok(()) => (),
930                 };
931 
932                 &mut *render_client
933             };
934 
935             // Once we built the `StreamInner`, we add a command that will be picked up by the
936             // `run()` method and added to the `RunContext`.
937             let client_flow = AudioClientFlow::Render { render_client };
938 
939             let audio_clock = get_audio_clock(audio_client).map_err(|err| {
940                 (*audio_client).Release();
941                 err
942             })?;
943 
944             Ok(StreamInner {
945                 audio_client,
946                 audio_clock,
947                 client_flow,
948                 event,
949                 playing: false,
950                 max_frames_in_buffer,
951                 bytes_per_frame: waveformatex.nBlockAlign,
952                 config: config.clone(),
953                 sample_format,
954             })
955         }
956     }
957 }
958 
959 impl PartialEq for Device {
960     #[inline]
eq(&self, other: &Device) -> bool961     fn eq(&self, other: &Device) -> bool {
962         // Use case: In oder to check whether the default device has changed
963         // the client code might need to compare the previous default device with the current one.
964         // The pointer comparison (`self.device == other.device`) don't work there,
965         // because the pointers are different even when the default device stays the same.
966         //
967         // In this code section we're trying to use the GetId method for the device comparison, cf.
968         // https://docs.microsoft.com/en-us/windows/desktop/api/mmdeviceapi/nf-mmdeviceapi-immdevice-getid
969         unsafe {
970             struct IdRAII(LPWSTR);
971             /// RAII for device IDs.
972             impl Drop for IdRAII {
973                 fn drop(&mut self) {
974                     unsafe { CoTaskMemFree(self.0 as *mut c_void) }
975                 }
976             }
977             let mut id1: LPWSTR = ptr::null_mut();
978             let rc1 = (*self.device).GetId(&mut id1);
979             // GetId only fails with E_OUTOFMEMORY and if it does, we're probably dead already.
980             // Plus it won't do to change the device comparison logic unexpectedly.
981             if rc1 != winerror::S_OK {
982                 panic!("cpal: GetId failure: {}", rc1)
983             }
984             let id1 = IdRAII(id1);
985             let mut id2: LPWSTR = ptr::null_mut();
986             let rc2 = (*other.device).GetId(&mut id2);
987             if rc2 != winerror::S_OK {
988                 panic!("cpal: GetId failure: {}", rc1)
989             }
990             let id2 = IdRAII(id2);
991             // 16-bit null-terminated comparison.
992             let mut offset = 0;
993             loop {
994                 let w1: WCHAR = *id1.0.offset(offset);
995                 let w2: WCHAR = *id2.0.offset(offset);
996                 if w1 == 0 && w2 == 0 {
997                     return true;
998                 }
999                 if w1 != w2 {
1000                     return false;
1001                 }
1002                 offset += 1;
1003             }
1004         }
1005     }
1006 }
1007 
1008 impl Eq for Device {}
1009 
1010 impl Clone for Device {
1011     #[inline]
clone(&self) -> Device1012     fn clone(&self) -> Device {
1013         unsafe {
1014             (*self.device).AddRef();
1015         }
1016 
1017         Device {
1018             device: self.device,
1019             future_audio_client: self.future_audio_client.clone(),
1020         }
1021     }
1022 }
1023 
1024 impl fmt::Debug for Device {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result1025     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1026         f.debug_struct("Device")
1027             .field("device", &self.device)
1028             .field("name", &self.name())
1029             .finish()
1030     }
1031 }
1032 
1033 impl Drop for Device {
1034     #[inline]
drop(&mut self)1035     fn drop(&mut self) {
1036         unsafe {
1037             (*self.device).Release();
1038         }
1039 
1040         if let Some(client) = self.future_audio_client.lock().unwrap().take() {
1041             unsafe {
1042                 (*client.0).Release();
1043             }
1044         }
1045     }
1046 }
1047 
1048 impl Drop for Endpoint {
drop(&mut self)1049     fn drop(&mut self) {
1050         unsafe {
1051             (*self.endpoint).Release();
1052         }
1053     }
1054 }
1055 
1056 impl From<*const IMMDevice> for Endpoint {
from(device: *const IMMDevice) -> Self1057     fn from(device: *const IMMDevice) -> Self {
1058         unsafe {
1059             let endpoint = immendpoint_from_immdevice(device);
1060             Endpoint { endpoint }
1061         }
1062     }
1063 }
1064 
1065 impl Endpoint {
data_flow(&self) -> EDataFlow1066     fn data_flow(&self) -> EDataFlow {
1067         unsafe { data_flow_from_immendpoint(self.endpoint) }
1068     }
1069 }
1070 
1071 lazy_static! {
1072     static ref ENUMERATOR: Enumerator = {
1073         // COM initialization is thread local, but we only need to have COM initialized in the
1074         // thread we create the objects in
1075         com::com_initialized();
1076 
1077         // building the devices enumerator object
1078         unsafe {
1079             let mut enumerator: *mut IMMDeviceEnumerator = ptr::null_mut();
1080 
1081             let hresult = CoCreateInstance(
1082                 &CLSID_MMDeviceEnumerator,
1083                 ptr::null_mut(),
1084                 CLSCTX_ALL,
1085                 &IMMDeviceEnumerator::uuidof(),
1086                 &mut enumerator as *mut *mut IMMDeviceEnumerator as *mut _,
1087             );
1088 
1089             check_result(hresult).unwrap();
1090             Enumerator(enumerator)
1091         }
1092     };
1093 }
1094 
1095 /// RAII objects around `IMMDeviceEnumerator`.
1096 struct Enumerator(*mut IMMDeviceEnumerator);
1097 
1098 unsafe impl Send for Enumerator {}
1099 unsafe impl Sync for Enumerator {}
1100 
1101 impl Drop for Enumerator {
1102     #[inline]
drop(&mut self)1103     fn drop(&mut self) {
1104         unsafe {
1105             (*self.0).Release();
1106         }
1107     }
1108 }
1109 
1110 /// WASAPI implementation for `Devices`.
1111 pub struct Devices {
1112     collection: *mut IMMDeviceCollection,
1113     total_count: u32,
1114     next_item: u32,
1115 }
1116 
1117 impl Devices {
new() -> Result<Self, DevicesError>1118     pub fn new() -> Result<Self, DevicesError> {
1119         unsafe {
1120             let mut collection: *mut IMMDeviceCollection = ptr::null_mut();
1121             // can fail because of wrong parameters (should never happen) or out of memory
1122             check_result_backend_specific((*ENUMERATOR.0).EnumAudioEndpoints(
1123                 eAll,
1124                 DEVICE_STATE_ACTIVE,
1125                 &mut collection,
1126             ))?;
1127 
1128             let count = 0u32;
1129             // can fail if the parameter is null, which should never happen
1130             check_result_backend_specific((*collection).GetCount(&count))?;
1131 
1132             Ok(Devices {
1133                 collection,
1134                 total_count: count,
1135                 next_item: 0,
1136             })
1137         }
1138     }
1139 }
1140 
1141 unsafe impl Send for Devices {}
1142 unsafe impl Sync for Devices {}
1143 
1144 impl Drop for Devices {
1145     #[inline]
drop(&mut self)1146     fn drop(&mut self) {
1147         unsafe {
1148             (*self.collection).Release();
1149         }
1150     }
1151 }
1152 
1153 impl Iterator for Devices {
1154     type Item = Device;
1155 
next(&mut self) -> Option<Device>1156     fn next(&mut self) -> Option<Device> {
1157         if self.next_item >= self.total_count {
1158             return None;
1159         }
1160 
1161         unsafe {
1162             let mut device = ptr::null_mut();
1163             // can fail if out of range, which we just checked above
1164             check_result((*self.collection).Item(self.next_item, &mut device)).unwrap();
1165 
1166             self.next_item += 1;
1167             Some(Device::from_immdevice(device))
1168         }
1169     }
1170 
1171     #[inline]
size_hint(&self) -> (usize, Option<usize>)1172     fn size_hint(&self) -> (usize, Option<usize>) {
1173         let num = self.total_count - self.next_item;
1174         let num = num as usize;
1175         (num, Some(num))
1176     }
1177 }
1178 
default_device(data_flow: EDataFlow) -> Option<Device>1179 fn default_device(data_flow: EDataFlow) -> Option<Device> {
1180     unsafe {
1181         let mut device = ptr::null_mut();
1182         let hres = (*ENUMERATOR.0).GetDefaultAudioEndpoint(data_flow, eConsole, &mut device);
1183         if let Err(_err) = check_result(hres) {
1184             return None; // TODO: check specifically for `E_NOTFOUND`, and panic otherwise
1185         }
1186         Some(Device::from_immdevice(device))
1187     }
1188 }
1189 
default_input_device() -> Option<Device>1190 pub fn default_input_device() -> Option<Device> {
1191     default_device(eCapture)
1192 }
1193 
default_output_device() -> Option<Device>1194 pub fn default_output_device() -> Option<Device> {
1195     default_device(eRender)
1196 }
1197 
1198 /// Get the audio clock used to produce `StreamInstant`s.
get_audio_clock( audio_client: *mut audioclient::IAudioClient, ) -> Result<*mut audioclient::IAudioClock, BuildStreamError>1199 unsafe fn get_audio_clock(
1200     audio_client: *mut audioclient::IAudioClient,
1201 ) -> Result<*mut audioclient::IAudioClock, BuildStreamError> {
1202     let mut audio_clock: *mut audioclient::IAudioClock = ptr::null_mut();
1203     let hresult = (*audio_client).GetService(
1204         &audioclient::IID_IAudioClock,
1205         &mut audio_clock as *mut *mut audioclient::IAudioClock as *mut _,
1206     );
1207     match check_result(hresult) {
1208         Err(ref e) if e.raw_os_error() == Some(AUDCLNT_E_DEVICE_INVALIDATED) => {
1209             return Err(BuildStreamError::DeviceNotAvailable);
1210         }
1211         Err(e) => {
1212             let description = format!("failed to build audio clock: {}", e);
1213             let err = BackendSpecificError { description };
1214             return Err(err.into());
1215         }
1216         Ok(()) => (),
1217     };
1218     Ok(audio_clock)
1219 }
1220 
1221 // Turns a `Format` into a `WAVEFORMATEXTENSIBLE`.
1222 //
1223 // Returns `None` if the WAVEFORMATEXTENSIBLE does not support the given format.
config_to_waveformatextensible( config: &StreamConfig, sample_format: SampleFormat, ) -> Option<mmreg::WAVEFORMATEXTENSIBLE>1224 fn config_to_waveformatextensible(
1225     config: &StreamConfig,
1226     sample_format: SampleFormat,
1227 ) -> Option<mmreg::WAVEFORMATEXTENSIBLE> {
1228     let format_tag = match sample_format {
1229         SampleFormat::I16 => mmreg::WAVE_FORMAT_PCM,
1230         SampleFormat::F32 => mmreg::WAVE_FORMAT_EXTENSIBLE,
1231         SampleFormat::U16 => return None,
1232     };
1233     let channels = config.channels as WORD;
1234     let sample_rate = config.sample_rate.0 as DWORD;
1235     let sample_bytes = sample_format.sample_size() as WORD;
1236     let avg_bytes_per_sec = u32::from(channels) * sample_rate * u32::from(sample_bytes);
1237     let block_align = channels * sample_bytes;
1238     let bits_per_sample = 8 * sample_bytes;
1239     let cb_size = match sample_format {
1240         SampleFormat::I16 => 0,
1241         SampleFormat::F32 => {
1242             let extensible_size = mem::size_of::<mmreg::WAVEFORMATEXTENSIBLE>();
1243             let ex_size = mem::size_of::<mmreg::WAVEFORMATEX>();
1244             (extensible_size - ex_size) as WORD
1245         }
1246         SampleFormat::U16 => return None,
1247     };
1248     let waveformatex = mmreg::WAVEFORMATEX {
1249         wFormatTag: format_tag,
1250         nChannels: channels,
1251         nSamplesPerSec: sample_rate,
1252         nAvgBytesPerSec: avg_bytes_per_sec,
1253         nBlockAlign: block_align,
1254         wBitsPerSample: bits_per_sample,
1255         cbSize: cb_size,
1256     };
1257 
1258     // CPAL does not care about speaker positions, so pass audio straight through.
1259     // TODO: This constant should be defined in winapi but is missing.
1260     const KSAUDIO_SPEAKER_DIRECTOUT: DWORD = 0;
1261     let channel_mask = KSAUDIO_SPEAKER_DIRECTOUT;
1262 
1263     let sub_format = match sample_format {
1264         SampleFormat::I16 => ksmedia::KSDATAFORMAT_SUBTYPE_PCM,
1265         SampleFormat::F32 => ksmedia::KSDATAFORMAT_SUBTYPE_IEEE_FLOAT,
1266         SampleFormat::U16 => return None,
1267     };
1268     let waveformatextensible = mmreg::WAVEFORMATEXTENSIBLE {
1269         Format: waveformatex,
1270         Samples: bits_per_sample as WORD,
1271         dwChannelMask: channel_mask,
1272         SubFormat: sub_format,
1273     };
1274 
1275     Some(waveformatextensible)
1276 }
1277