in src/backend/mod.rs [4305:4411]
fn install_device_changed_callback(&mut self) -> Result<()> {
self.debug_assert_is_on_stream_queue();
assert!(!self.stm_ptr.is_null());
let stm = unsafe { &(*self.stm_ptr) };
if !self.output_unit.is_null() {
assert_ne!(self.output_device.id, kAudioObjectUnknown);
assert_ne!(self.output_device.id, kAudioObjectSystemObject);
assert!(
self.output_source_listener.is_none(),
"register output_source_listener without unregistering the one in use"
);
assert!(
self.output_alive_listener.is_none(),
"register output_alive_listener without unregistering the one in use"
);
// Get the notification when the data source on the same device changes,
// e.g., when the user plugs in a TRRS headset into the headphone jack.
self.output_source_listener = Some(device_property_listener::new(
self.output_device.id,
get_property_address(Property::DeviceSource, DeviceType::OUTPUT),
audiounit_property_listener_callback,
));
let rv = stm.add_device_listener(self.output_source_listener.as_ref().unwrap());
if rv != NO_ERR {
self.output_source_listener = None;
cubeb_log!("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDataSource rv={}, device id={}", rv, self.output_device.id);
return Err(Error::error());
}
// Get the notification when the output device is going away
// if the output doesn't follow the system default.
if !self
.output_device
.flags
.contains(device_flags::DEV_SELECTED_DEFAULT)
{
self.output_alive_listener = Some(device_property_listener::new(
self.output_device.id,
get_property_address(
Property::DeviceIsAlive,
DeviceType::INPUT | DeviceType::OUTPUT,
),
audiounit_property_listener_callback,
));
let rv = stm.add_device_listener(self.output_alive_listener.as_ref().unwrap());
if rv != NO_ERR {
self.output_alive_listener = None;
cubeb_log!("AudioObjectAddPropertyListener/output/kAudioDevicePropertyDeviceIsAlive rv={}, device id ={}", rv, self.output_device.id);
return Err(Error::error());
}
}
}
if !self.input_unit.is_null() {
assert_ne!(self.input_device.id, kAudioObjectUnknown);
assert_ne!(self.input_device.id, kAudioObjectSystemObject);
assert!(
self.input_source_listener.is_none(),
"register input_source_listener without unregistering the one in use"
);
assert!(
self.input_alive_listener.is_none(),
"register input_alive_listener without unregistering the one in use"
);
// Get the notification when the data source on the same device changes,
// e.g., when the user plugs in a TRRS mic into the headphone jack.
self.input_source_listener = Some(device_property_listener::new(
self.input_device.id,
get_property_address(Property::DeviceSource, DeviceType::INPUT),
audiounit_property_listener_callback,
));
let rv = stm.add_device_listener(self.input_source_listener.as_ref().unwrap());
if rv != NO_ERR {
self.input_source_listener = None;
cubeb_log!("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDataSource rv={}, device id={}", rv, self.input_device.id);
return Err(Error::error());
}
// Get the notification when the input device is going away
// if the input doesn't follow the system default.
if !self
.input_device
.flags
.contains(device_flags::DEV_SELECTED_DEFAULT)
{
self.input_alive_listener = Some(device_property_listener::new(
self.input_device.id,
get_property_address(
Property::DeviceIsAlive,
DeviceType::INPUT | DeviceType::OUTPUT,
),
audiounit_property_listener_callback,
));
let rv = stm.add_device_listener(self.input_alive_listener.as_ref().unwrap());
if rv != NO_ERR {
self.input_alive_listener = None;
cubeb_log!("AudioObjectAddPropertyListener/input/kAudioDevicePropertyDeviceIsAlive rv={}, device id ={}", rv, self.input_device.id);
return Err(Error::error());
}
}
}
Ok(())
}