Make workaround_for_airpod become a member functions
This commit is contained in:
Родитель
fde2106645
Коммит
b5ab6f1dd5
|
@ -1507,82 +1507,6 @@ fn audiounit_activate_clock_drift_compensation(aggregate_device_id: AudioDeviceI
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// TODO: If this is only called when airpod is part of the aggregate device,
|
||||
// should we add a check for this ?
|
||||
fn audiounit_workaround_for_airpod(stm: &AudioUnitStream)
|
||||
{
|
||||
let mut input_device_info = ffi::cubeb_device_info::default();
|
||||
// TODO: Check input_device.id ? Check if the call is successful ?
|
||||
assert_ne!(stm.input_device.id, kAudioObjectUnknown);
|
||||
audiounit_create_device_from_hwdev(&mut input_device_info, stm.input_device.id, DeviceType::INPUT);
|
||||
|
||||
let mut output_device_info = ffi::cubeb_device_info::default();
|
||||
assert_ne!(stm.output_device.id, kAudioObjectUnknown);
|
||||
audiounit_create_device_from_hwdev(&mut output_device_info, stm.output_device.id, DeviceType::OUTPUT);
|
||||
|
||||
// TODO: Check input_device_info.friendly_name and
|
||||
// output_device_info.friendly_name ?
|
||||
// NOTE: Retake the leaked friendly_name strings.
|
||||
// It's better to extract the part of getting name of the data source
|
||||
// into a function, so we don't need to call
|
||||
// `audiounit_create_device_from_hwdev` to get this info.
|
||||
let input_name_str = unsafe {
|
||||
CString::from_raw(input_device_info.friendly_name as *mut c_char)
|
||||
.into_string()
|
||||
.expect("Fail to convert input name from CString into String")
|
||||
};
|
||||
input_device_info.friendly_name = ptr::null();
|
||||
let output_name_str = unsafe {
|
||||
CString::from_raw(output_device_info.friendly_name as *mut c_char)
|
||||
.into_string()
|
||||
.expect("Fail to convert output name from CString into String")
|
||||
};
|
||||
output_device_info.friendly_name = ptr::null();
|
||||
|
||||
if input_name_str.contains("AirPods") &&
|
||||
output_name_str.contains("AirPods") {
|
||||
let mut input_min_rate = 0;
|
||||
let mut input_max_rate = 0;
|
||||
let mut input_nominal_rate = 0;
|
||||
audiounit_get_available_samplerate(stm.input_device.id, kAudioObjectPropertyScopeGlobal,
|
||||
&mut input_min_rate, &mut input_max_rate, &mut input_nominal_rate);
|
||||
cubeb_log!("({:p}) Input device {}, name: {}, min: {}, max: {}, nominal rate: {}", stm as *const AudioUnitStream, stm.input_device.id
|
||||
, input_name_str, input_min_rate, input_max_rate, input_nominal_rate);
|
||||
|
||||
let mut output_min_rate = 0;
|
||||
let mut output_max_rate = 0;
|
||||
let mut output_nominal_rate = 0;
|
||||
audiounit_get_available_samplerate(stm.output_device.id, kAudioObjectPropertyScopeGlobal,
|
||||
&mut output_min_rate, &mut output_max_rate, &mut output_nominal_rate);
|
||||
cubeb_log!("({:p}) Output device {}, name: {}, min: {}, max: {}, nominal rate: {}", stm as *const AudioUnitStream, stm.output_device.id
|
||||
, output_name_str, output_min_rate, output_max_rate, output_nominal_rate);
|
||||
|
||||
let rate = f64::from(input_nominal_rate);
|
||||
let addr = AudioObjectPropertyAddress {
|
||||
mSelector: kAudioDevicePropertyNominalSampleRate,
|
||||
mScope: kAudioObjectPropertyScopeGlobal,
|
||||
mElement: kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
// TODO: Check the aggregate_device_id ?
|
||||
let rv = audio_object_set_property_data(stm.aggregate_device_id,
|
||||
&addr,
|
||||
mem::size_of::<f64>(),
|
||||
&rate);
|
||||
if rv != NO_ERR {
|
||||
cubeb_log!("Non fatal error, AudioObjectSetPropertyData/kAudioDevicePropertyNominalSampleRate, rv={}", rv);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the rest lost memory.
|
||||
// No need to retrieve the memory of {input,output}_device_info.friendly_name
|
||||
// since they are already retrieved/retaken above.
|
||||
assert!(input_device_info.friendly_name.is_null());
|
||||
audiounit_device_destroy(&mut input_device_info);
|
||||
assert!(output_device_info.friendly_name.is_null());
|
||||
audiounit_device_destroy(&mut output_device_info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Aggregate Device is a virtual audio interface which utilizes inputs and outputs
|
||||
* of one or more physical audio interfaces. It is possible to use the clock of
|
||||
|
@ -1633,7 +1557,7 @@ fn audiounit_create_aggregate_device(stm: &mut AudioUnitStream) -> Result<()>
|
|||
return Err(r);
|
||||
}
|
||||
|
||||
audiounit_workaround_for_airpod(stm);
|
||||
stm.workaround_for_airpod();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -3595,6 +3519,90 @@ impl<'ctx> AudioUnitStream<'ctx> {
|
|||
audiounit_set_channel_layout(self.output_unit, io_side::OUTPUT, self.context.layout.load(atomic::Ordering::SeqCst));
|
||||
}
|
||||
|
||||
fn workaround_for_airpod(&self) {
|
||||
assert_ne!(self.input_device.id, self.output_device.id);
|
||||
assert_ne!(self.aggregate_device_id, kAudioObjectUnknown);
|
||||
|
||||
let mut input_device_info = ffi::cubeb_device_info::default();
|
||||
assert_ne!(self.input_device.id, kAudioObjectUnknown);
|
||||
audiounit_create_device_from_hwdev(&mut input_device_info, self.input_device.id, DeviceType::INPUT);
|
||||
|
||||
let mut output_device_info = ffi::cubeb_device_info::default();
|
||||
assert_ne!(self.output_device.id, kAudioObjectUnknown);
|
||||
audiounit_create_device_from_hwdev(&mut output_device_info, self.output_device.id, DeviceType::OUTPUT);
|
||||
|
||||
// NOTE: Retake the leaked friendly_name strings.
|
||||
// It's better to extract the part of getting name of the data source
|
||||
// into a function, so we don't need to call
|
||||
// `audiounit_create_device_from_hwdev` to get this info.
|
||||
let input_name_str = unsafe {
|
||||
CString::from_raw(input_device_info.friendly_name as *mut c_char)
|
||||
.into_string()
|
||||
.expect("Fail to convert input name from CString into String")
|
||||
};
|
||||
input_device_info.friendly_name = ptr::null();
|
||||
|
||||
let output_name_str = unsafe {
|
||||
CString::from_raw(output_device_info.friendly_name as *mut c_char)
|
||||
.into_string()
|
||||
.expect("Fail to convert output name from CString into String")
|
||||
};
|
||||
output_device_info.friendly_name = ptr::null();
|
||||
|
||||
if input_name_str.contains("AirPods") && output_name_str.contains("AirPods") {
|
||||
let mut input_min_rate = 0;
|
||||
let mut input_max_rate = 0;
|
||||
let mut input_nominal_rate = 0;
|
||||
audiounit_get_available_samplerate(
|
||||
self.input_device.id,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
&mut input_min_rate,
|
||||
&mut input_max_rate,
|
||||
&mut input_nominal_rate
|
||||
);
|
||||
cubeb_log!("({:p}) Input device {}, name: {}, min: {}, max: {}, nominal rate: {}",
|
||||
self as *const AudioUnitStream, self.input_device.id, input_name_str,
|
||||
input_min_rate, input_max_rate, input_nominal_rate);
|
||||
|
||||
let mut output_min_rate = 0;
|
||||
let mut output_max_rate = 0;
|
||||
let mut output_nominal_rate = 0;
|
||||
audiounit_get_available_samplerate(
|
||||
self.output_device.id,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
&mut output_min_rate,
|
||||
&mut output_max_rate,
|
||||
&mut output_nominal_rate
|
||||
);
|
||||
cubeb_log!("({:p}) Output device {}, name: {}, min: {}, max: {}, nominal rate: {}",
|
||||
self as *const AudioUnitStream, self.output_device.id, output_name_str,
|
||||
output_min_rate, output_max_rate, output_nominal_rate);
|
||||
|
||||
let rate = f64::from(input_nominal_rate);
|
||||
let addr = AudioObjectPropertyAddress {
|
||||
mSelector: kAudioDevicePropertyNominalSampleRate,
|
||||
mScope: kAudioObjectPropertyScopeGlobal,
|
||||
mElement: kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
let rv = audio_object_set_property_data(self.aggregate_device_id,
|
||||
&addr,
|
||||
mem::size_of::<f64>(),
|
||||
&rate);
|
||||
if rv != NO_ERR {
|
||||
cubeb_log!("Non fatal error, AudioObjectSetPropertyData/kAudioDevicePropertyNominalSampleRate, rv={}", rv);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the rest lost memory.
|
||||
// No need to retrieve the memory of {input,output}_device_info.friendly_name
|
||||
// since they are already retrieved/retaken above.
|
||||
assert!(input_device_info.friendly_name.is_null());
|
||||
audiounit_device_destroy(&mut input_device_info);
|
||||
assert!(output_device_info.friendly_name.is_null());
|
||||
audiounit_device_destroy(&mut output_device_info);
|
||||
}
|
||||
|
||||
fn init_input_linear_buffer(&mut self, capacity: u32) -> Result<()> {
|
||||
// FIXIT: Make sure `input_desc` is initialized, or the type of the buffer is set to float!
|
||||
// assert_ne!(self.input_desc.mFormatFlags, 0);
|
||||
|
|
Загрузка…
Ссылка в новой задаче