in src/backend/mod.rs [2524:2586]
fn add_devices_changed_listener(
&mut self,
devtype: DeviceType,
collection_changed_callback: ffi::cubeb_device_collection_changed_callback,
user_ptr: *mut c_void,
) -> Result<()> {
assert!(devtype.intersects(DeviceType::INPUT | DeviceType::OUTPUT));
assert!(collection_changed_callback.is_some());
let context_ptr = self as *mut AudioUnitContext;
let mut devices = self.devices.lock().unwrap();
// Note: second register without unregister first causes 'nope' error.
// Current implementation requires unregister before register a new cb.
if devtype.contains(DeviceType::INPUT) && devices.input.changed_callback.is_some()
|| devtype.contains(DeviceType::OUTPUT) && devices.output.changed_callback.is_some()
{
return Err(Error::invalid_parameter());
}
if devices.input.changed_callback.is_none() && devices.output.changed_callback.is_none() {
let address = get_property_address(
Property::HardwareDevices,
DeviceType::INPUT | DeviceType::OUTPUT,
);
let ret = audio_object_add_property_listener(
kAudioObjectSystemObject,
&address,
audiounit_collection_changed_callback,
context_ptr,
);
if ret != NO_ERR {
cubeb_log!(
"Cannot add devices-changed listener for {:?}, Error: {}",
devtype,
ret
);
return Err(Error::error());
}
}
if devtype.contains(DeviceType::INPUT) {
// Expected empty after unregister.
assert!(devices.input.is_empty());
devices.input.set(
collection_changed_callback,
user_ptr,
audiounit_get_devices_of_type(DeviceType::INPUT),
);
}
if devtype.contains(DeviceType::OUTPUT) {
// Expected empty after unregister.
assert!(devices.output.is_empty());
devices.output.set(
collection_changed_callback,
user_ptr,
audiounit_get_devices_of_type(DeviceType::OUTPUT),
);
}
Ok(())
}