summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/cubeb-coreaudio/src/backend/mod.rs')
-rw-r--r--third_party/rust/cubeb-coreaudio/src/backend/mod.rs172
1 files changed, 169 insertions, 3 deletions
diff --git a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
index e6be028a2e..855c119b63 100644
--- a/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
+++ b/third_party/rust/cubeb-coreaudio/src/backend/mod.rs
@@ -33,6 +33,8 @@ use self::mixer::*;
use self::resampler::*;
use self::utils::*;
use backend::ringbuf::RingBuffer;
+#[cfg(feature = "audio_dump")]
+use cubeb_backend::ffi::cubeb_audio_dump_stream_t;
use cubeb_backend::{
ffi, ChannelLayout, Context, ContextOps, DeviceCollectionRef, DeviceId, DeviceRef, DeviceType,
Error, InputProcessingParams, Ops, Result, SampleFormat, State, Stream, StreamOps,
@@ -114,6 +116,16 @@ lazy_static! {
};
}
+#[cfg(feature = "audio_dump")]
+fn dump_audio(stream: cubeb_audio_dump_stream_t, audio_samples: *mut c_void, count: u32) {
+ unsafe {
+ let rv = ffi::cubeb_audio_dump_write(stream, audio_samples, count);
+ if rv != 0 {
+ cubeb_alog!("Error dumping audio data");
+ }
+ }
+}
+
fn make_sized_audio_channel_layout(sz: usize) -> AutoRelease<AudioChannelLayout> {
assert!(sz >= mem::size_of::<AudioChannelLayout>());
assert_eq!(
@@ -194,7 +206,12 @@ impl From<CAChannelLabel> for mixer::Channel {
sys::kAudioChannelLabel_TopBackLeft => mixer::Channel::TopBackLeft,
sys::kAudioChannelLabel_TopBackCenter => mixer::Channel::TopBackCenter,
sys::kAudioChannelLabel_TopBackRight => mixer::Channel::TopBackRight,
- _ => mixer::Channel::Silence,
+ sys::kAudioChannelLabel_Unknown => mixer::Channel::Discrete,
+ sys::kAudioChannelLabel_Unused => mixer::Channel::Silence,
+ v => {
+ eprintln!("Warning: channel label value {} isn't handled", v);
+ mixer::Channel::Silence
+ }
}
}
}
@@ -551,6 +568,16 @@ extern "C" fn audiounit_input_callback(
ErrorHandle::Reinit
} else {
assert_eq!(status, NO_ERR);
+
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_input,
+ input_buffer_list.mBuffers[0].mData,
+ input_frames * stm.core_stream_data.input_dev_desc.mChannelsPerFrame,
+ );
+ }
+
input_buffer_manager
.push_data(input_buffer_list.mBuffers[0].mData, input_frames as usize);
ErrorHandle::Return(status)
@@ -708,6 +735,14 @@ extern "C" fn audiounit_output_callback(
if stm.stopped.load(Ordering::SeqCst) {
cubeb_alog!("({:p}) output stopped.", stm as *const AudioUnitStream);
audiounit_make_silent(&buffers[0]);
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
return NO_ERR;
}
@@ -718,12 +753,20 @@ extern "C" fn audiounit_output_callback(
cubeb_alog!("({:p}) output drained.", stm as *const AudioUnitStream);
stm.notify_state_changed(State::Drained);
let queue = stm.queue.clone();
+ audiounit_make_silent(&buffers[0]);
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
// Use a new thread, through the queue, to avoid deadlock when calling
// AudioOutputUnitStop method from inside render callback
queue.run_async(move || {
stm.core_stream_data.stop_audiounits();
});
- audiounit_make_silent(&buffers[0]);
return NO_ERR;
}
@@ -846,12 +889,21 @@ extern "C" fn audiounit_output_callback(
stm.stopped.store(true, Ordering::SeqCst);
stm.notify_state_changed(State::Error);
let queue = stm.queue.clone();
+ audiounit_make_silent(&buffers[0]);
+
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
// Use a new thread, through the queue, to avoid deadlock when calling
// AudioOutputUnitStop method from inside render callback
queue.run_async(move || {
stm.core_stream_data.stop_audiounits();
});
- audiounit_make_silent(&buffers[0]);
return NO_ERR;
}
@@ -898,6 +950,15 @@ extern "C" fn audiounit_output_callback(
buffers[0].mDataByteSize as usize,
);
}
+
+ #[cfg(feature = "audio_dump")]
+ {
+ dump_audio(
+ stm.core_stream_data.audio_dump_output,
+ buffers[0].mData,
+ output_frames * stm.core_stream_data.output_dev_desc.mChannelsPerFrame,
+ );
+ }
NO_ERR
}
@@ -3010,6 +3071,14 @@ struct CoreStreamData<'ctx> {
output_alive_listener: Option<device_property_listener>,
output_source_listener: Option<device_property_listener>,
input_logging: Option<InputCallbackLogger>,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session: ffi::cubeb_audio_dump_session_t,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session_running: bool,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_input: ffi::cubeb_audio_dump_stream_t,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_output: ffi::cubeb_audio_dump_stream_t,
}
impl<'ctx> Default for CoreStreamData<'ctx> {
@@ -3050,6 +3119,14 @@ impl<'ctx> Default for CoreStreamData<'ctx> {
output_alive_listener: None,
output_source_listener: None,
input_logging: None,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session_running: false,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_input: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_output: ptr::null_mut(),
}
}
}
@@ -3097,6 +3174,14 @@ impl<'ctx> CoreStreamData<'ctx> {
output_alive_listener: None,
output_source_listener: None,
input_logging: None,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_session_running: false,
+ #[cfg(feature = "audio_dump")]
+ audio_dump_input: ptr::null_mut(),
+ #[cfg(feature = "audio_dump")]
+ audio_dump_output: ptr::null_mut(),
}
}
@@ -3454,6 +3539,11 @@ impl<'ctx> CoreStreamData<'ctx> {
assert!(!self.stm_ptr.is_null());
let stream = unsafe { &(*self.stm_ptr) };
+ #[cfg(feature = "audio_dump")]
+ unsafe {
+ ffi::cubeb_audio_dump_init(&mut self.audio_dump_session);
+ }
+
// Configure I/O stream
if self.has_input() {
assert!(!self.input_unit.is_null());
@@ -3543,6 +3633,26 @@ impl<'ctx> CoreStreamData<'ctx> {
e
})?;
+ #[cfg(feature = "audio_dump")]
+ {
+ let name = format!("input-{:p}.wav", self.stm_ptr);
+ let cname = CString::new(name).expect("OK");
+ let rv = unsafe {
+ ffi::cubeb_audio_dump_stream_init(
+ self.audio_dump_session,
+ &mut self.audio_dump_input,
+ *params.as_ptr(),
+ cname.as_ptr(),
+ )
+ };
+ if rv == 0 {
+ assert_ne!(self.audio_dump_input, ptr::null_mut(),);
+ cubeb_log!("Successfully inited audio dump for input");
+ } else {
+ cubeb_log!("Failed to init audio dump for input");
+ }
+ }
+
assert_eq!(self.input_dev_desc.mSampleRate, input_hw_desc.mSampleRate);
// Use latency to set buffer size
@@ -3739,6 +3849,26 @@ impl<'ctx> CoreStreamData<'ctx> {
e
})?;
+ #[cfg(feature = "audio_dump")]
+ {
+ let name = format!("output-{:p}.wav", self.stm_ptr);
+ let cname = CString::new(name).expect("OK");
+ let rv = unsafe {
+ ffi::cubeb_audio_dump_stream_init(
+ self.audio_dump_session,
+ &mut self.audio_dump_output,
+ *params.as_ptr(),
+ cname.as_ptr(),
+ )
+ };
+ if rv == 0 {
+ assert_ne!(self.audio_dump_output, ptr::null_mut(),);
+ cubeb_log!("Successfully inited audio dump for output");
+ } else {
+ cubeb_log!("Failed to init audio dump for output");
+ }
+ }
+
let device_layout = self
.get_output_channel_layout()
.map_err(|e| {
@@ -3908,6 +4038,12 @@ impl<'ctx> CoreStreamData<'ctx> {
self.input_logging = Some(InputCallbackLogger::new());
}
+ #[cfg(feature = "audio_dump")]
+ {
+ unsafe { ffi::cubeb_audio_dump_start(self.audio_dump_session) };
+ self.audio_dump_session_running = true;
+ }
+
if !self.input_unit.is_null() {
let r = audio_unit_initialize(self.input_unit);
if r != NO_ERR {
@@ -4081,6 +4217,36 @@ impl<'ctx> CoreStreamData<'ctx> {
// Return the VPIO unit if present.
self.voiceprocessing_unit_handle = None;
+ #[cfg(feature = "audio_dump")]
+ {
+ if !self.audio_dump_session.is_null() {
+ unsafe {
+ ffi::cubeb_audio_dump_stop(self.audio_dump_session);
+ if !self.audio_dump_input.is_null() {
+ let rv = ffi::cubeb_audio_dump_stream_shutdown(
+ self.audio_dump_session,
+ self.audio_dump_input,
+ );
+ if rv != 0 {
+ cubeb_log!("Failed to shutdown audio dump for input");
+ }
+ }
+ if !self.audio_dump_output.is_null() {
+ let rv = ffi::cubeb_audio_dump_stream_shutdown(
+ self.audio_dump_session,
+ self.audio_dump_output,
+ );
+ if rv != 0 {
+ cubeb_log!("Failed to shutdown audio dump for output");
+ }
+ }
+ ffi::cubeb_audio_dump_shutdown(self.audio_dump_session);
+ self.audio_dump_session = ptr::null_mut();
+ self.audio_dump_session_running = false;
+ }
+ }
+ }
+
self.resampler.destroy();
self.mixer = None;
self.aggregate_device = None;