Skip to content

Commit c7395ce

Browse files
committed
fix(wasapi): get name of default device
1 parent f208797 commit c7395ce

1 file changed

Lines changed: 64 additions & 61 deletions

File tree

src/host/wasapi/device.rs

Lines changed: 64 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -327,57 +327,59 @@ unsafe impl Sync for Device {}
327327

328328
impl Device {
329329
pub fn name(&self) -> Result<String, DeviceNameError> {
330-
match &self.device {
331-
DeviceType::DefaultOutput => Ok("Default Output".to_string()),
332-
DeviceType::DefaultInput => Ok("Default Input".to_string()),
333-
DeviceType::Specific(device) => unsafe {
334-
// Open the device's property store.
335-
let property_store = device
336-
.OpenPropertyStore(STGM_READ)
337-
.expect("could not open property store");
338-
339-
// Get the endpoint's friendly-name property.
340-
let mut property_value = property_store
341-
.GetValue(&Properties::DEVPKEY_Device_FriendlyName as *const _ as *const _)
342-
.map_err(|err| {
343-
let description =
344-
format!("failed to retrieve name from property store: {}", err);
345-
let err = BackendSpecificError { description };
346-
DeviceNameError::from(err)
347-
})?;
330+
let device = self
331+
.immdevice()
332+
.ok_or(DeviceNameError::from(BackendSpecificError {
333+
description: "device not found while getting name".to_string(),
334+
}))?;
348335

349-
let prop_variant = &property_value.Anonymous.Anonymous;
350-
351-
// Read the friendly-name from the union data field, expecting a *const u16.
352-
if prop_variant.vt != VT_LPWSTR {
353-
let description = format!(
354-
"property store produced invalid data: {:?}",
355-
prop_variant.vt
356-
);
336+
unsafe {
337+
// Open the device's property store.
338+
let property_store = device
339+
.OpenPropertyStore(STGM_READ)
340+
.expect("could not open property store");
341+
342+
// Get the endpoint's friendly-name property.
343+
let mut property_value = property_store
344+
.GetValue(&Properties::DEVPKEY_Device_FriendlyName as *const _ as *const _)
345+
.map_err(|err| {
346+
let description =
347+
format!("failed to retrieve name from property store: {}", err);
357348
let err = BackendSpecificError { description };
358-
return Err(err.into());
359-
}
360-
let ptr_utf16 = *(&prop_variant.Anonymous as *const _ as *const *const u16);
349+
DeviceNameError::from(err)
350+
})?;
361351

362-
// Find the length of the friendly name.
363-
let mut len = 0;
364-
while *ptr_utf16.offset(len) != 0 {
365-
len += 1;
366-
}
352+
let prop_variant = &property_value.Anonymous.Anonymous;
367353

368-
// Create the utf16 slice and convert it into a string.
369-
let name_slice = slice::from_raw_parts(ptr_utf16, len as usize);
370-
let name_os_string: OsString = OsStringExt::from_wide(name_slice);
371-
let name_string = match name_os_string.into_string() {
372-
Ok(string) => string,
373-
Err(os_string) => os_string.to_string_lossy().into(),
374-
};
354+
// Read the friendly-name from the union data field, expecting a *const u16.
355+
if prop_variant.vt != VT_LPWSTR {
356+
let description = format!(
357+
"property store produced invalid data: {:?}",
358+
prop_variant.vt
359+
);
360+
let err = BackendSpecificError { description };
361+
return Err(err.into());
362+
}
363+
let ptr_utf16 = *(&prop_variant.Anonymous as *const _ as *const *const u16);
375364

376-
// Clean up the property.
377-
StructuredStorage::PropVariantClear(&mut property_value).ok();
365+
// Find the length of the friendly name.
366+
let mut len = 0;
367+
while *ptr_utf16.offset(len) != 0 {
368+
len += 1;
369+
}
378370

379-
Ok(name_string)
380-
},
371+
// Create the utf16 slice and convert it into a string.
372+
let name_slice = slice::from_raw_parts(ptr_utf16, len as usize);
373+
let name_os_string: OsString = OsStringExt::from_wide(name_slice);
374+
let name_string = match name_os_string.into_string() {
375+
Ok(string) => string,
376+
Err(os_string) => os_string.to_string_lossy().into(),
377+
};
378+
379+
// Clean up the property.
380+
StructuredStorage::PropVariantClear(&mut property_value).ok();
381+
382+
Ok(name_string)
381383
}
382384
}
383385

@@ -405,9 +407,23 @@ impl Device {
405407
}
406408
}
407409

408-
// pub fn immdevice(&self) -> &Audio::IMMDevice {
409-
// &self.device
410-
// }
410+
pub fn immdevice(&self) -> Option<Audio::IMMDevice> {
411+
match &self.device {
412+
DeviceType::DefaultOutput => unsafe {
413+
get_enumerator()
414+
.0
415+
.GetDefaultAudioEndpoint(Audio::eRender, Audio::eConsole)
416+
.ok()
417+
},
418+
DeviceType::DefaultInput => unsafe {
419+
get_enumerator()
420+
.0
421+
.GetDefaultAudioEndpoint(Audio::eCapture, Audio::eConsole)
422+
.ok()
423+
},
424+
DeviceType::Specific(device) => Some(device.clone()),
425+
}
426+
}
411427

412428
/// Ensures that `future_audio_client` contains a `Some` and returns a locked mutex to it.
413429
fn ensure_future_audio_client(
@@ -1015,24 +1031,11 @@ impl Iterator for Devices {
10151031
}
10161032
}
10171033

1018-
//fn default_device(data_flow: Audio::EDataFlow) -> Option<Device> {
1019-
// unsafe {
1020-
// let device = get_enumerator()
1021-
// .0
1022-
// .GetDefaultAudioEndpoint(data_flow, Audio::eConsole)
1023-
// .ok()?;
1024-
// // TODO: check specifically for `E_NOTFOUND`, and panic otherwise
1025-
// Some(Device::from_immdevice(device))
1026-
// }
1027-
//}
1028-
10291034
pub fn default_input_device() -> Option<Device> {
1030-
//default_device(Audio::eCapture)
10311035
Some(Device::default_input())
10321036
}
10331037

10341038
pub fn default_output_device() -> Option<Device> {
1035-
//default_device(Audio::eRender)
10361039
Some(Device::default_output())
10371040
}
10381041

0 commit comments

Comments
 (0)