cidre/cm/
audio_device_clock.rs1#[cfg(target_os = "macos")]
2use crate::{arc, cf, cm, os};
3
4#[cfg(feature = "core_audio")]
5use crate::core_audio;
6
7#[cfg(target_os = "macos")]
8impl cm::Clock {
9 pub fn with_default_audio_output() -> os::Result<arc::R<Self>> {
11 Self::with_audio_device_uid(None)
12 }
13
14 #[doc(alias = "CMAudioDeviceClockCreate")]
15 pub fn with_audio_device_uid_in(
16 device_uid: Option<&cf::String>,
17 allocator: Option<&cf::Allocator>,
18 ) -> os::Result<Option<arc::R<Self>>> {
19 let mut res = None;
20 unsafe {
21 CMAudioDeviceClockCreate(allocator, device_uid, &mut res).result()?;
22 }
23
24 Ok(res)
25 }
26
27 #[doc(alias = "CMAudioDeviceClockCreate")]
28 pub fn with_audio_device_uid(device_uid: Option<&cf::String>) -> os::Result<arc::R<Self>> {
29 let mut res = None;
30 unsafe {
31 CMAudioDeviceClockCreate(None, device_uid, &mut res).result()?;
32 }
33
34 Ok(unsafe { std::mem::transmute(res) })
35 }
36
37 #[cfg(feature = "core_audio")]
38 #[doc(alias = "CMAudioDeviceClockCreateFromAudioDeviceID")]
39 pub fn with_audio_device_in(
40 audio_device: core_audio::Device,
41 allocator: Option<&cf::Allocator>,
42 ) -> os::Result<Option<arc::R<Self>>> {
43 let mut res = None;
44 unsafe {
45 CMAudioDeviceClockCreateFromAudioDeviceID(allocator, audio_device, &mut res)
46 .result()?;
47 }
48 Ok(res)
49 }
50
51 #[cfg(feature = "core_audio")]
52 #[doc(alias = "CMAudioDeviceClockCreateFromAudioDeviceID")]
53 pub fn with_audio_device(audio_device: core_audio::Device) -> os::Result<arc::R<Self>> {
54 let mut res = None;
55 unsafe {
56 CMAudioDeviceClockCreateFromAudioDeviceID(None, audio_device, &mut res).result()?;
57 }
58 Ok(unsafe { std::mem::transmute(res) })
59 }
60
61 #[doc(alias = "CMAudioDeviceClockSetAudioDeviceUID")]
62 pub fn set_audio_device_uid(&mut self, device_uid: Option<&cf::String>) -> os::Result {
63 unsafe { CMAudioDeviceClockSetAudioDeviceUID(self, device_uid).result() }
64 }
65
66 #[cfg(feature = "core_audio")]
67 #[doc(alias = "CMAudioDeviceClockSetAudioDeviceID")]
68 pub fn set_audio_device(&mut self, audio_device: core_audio::Device) -> os::Result {
69 unsafe { CMAudioDeviceClockSetAudioDeviceID(self, audio_device).result() }
70 }
71
72 #[cfg(feature = "core_audio")]
73 pub fn audio_device_uid(&self) -> os::Result<Option<&cf::String>> {
74 let mut device_uid_out = None;
75 unsafe {
76 CMAudioDeviceClockGetAudioDevice(
77 self,
78 &mut device_uid_out,
79 std::ptr::null_mut(),
80 std::ptr::null_mut(),
81 )
82 .result()?
83 }
84 Ok(device_uid_out)
85 }
86
87 #[cfg(feature = "core_audio")]
88 pub fn audio_device(&self) -> os::Result<core_audio::Device> {
89 let mut device_out = core_audio::Device(core_audio::Obj::UNKNOWN);
90 unsafe {
91 CMAudioDeviceClockGetAudioDevice(
92 self,
93 std::ptr::null_mut(),
94 &mut device_out,
95 std::ptr::null_mut(),
96 )
97 .result()?
98 }
99 Ok(device_out)
100 }
101
102 #[cfg(feature = "core_audio")]
103 pub fn is_tracking_default_device(&self) -> os::Result<bool> {
104 let mut tracking_default_device_out = false;
105 unsafe {
106 CMAudioDeviceClockGetAudioDevice(
107 self,
108 std::ptr::null_mut(),
109 std::ptr::null_mut(),
110 &mut tracking_default_device_out,
111 )
112 .result()?
113 }
114 Ok(tracking_default_device_out)
115 }
116}
117
118#[cfg(target_os = "macos")]
119unsafe extern "C" {
120 fn CMAudioDeviceClockCreate(
121 allocator: Option<&cf::Allocator>,
122 device_uid: Option<&cf::String>,
123 clock_out: *mut Option<arc::R<cm::Clock>>,
124 ) -> os::Status;
125
126 #[cfg(feature = "core_audio")]
127 fn CMAudioDeviceClockCreateFromAudioDeviceID(
128 allocator: Option<&cf::Allocator>,
129 audio_device: core_audio::Device,
130 clock_out: *mut Option<arc::R<cm::Clock>>,
131 ) -> os::Status;
132
133 fn CMAudioDeviceClockSetAudioDeviceUID(
134 clock: &mut cm::Clock,
135 device_uid: Option<&cf::String>,
136 ) -> os::Status;
137
138 #[cfg(feature = "core_audio")]
139 fn CMAudioDeviceClockSetAudioDeviceID(
140 clock: &mut cm::Clock,
141 audio_device: core_audio::Device,
142 ) -> os::Status;
143
144 #[cfg(feature = "core_audio")]
145 fn CMAudioDeviceClockGetAudioDevice(
146 clock: &cm::Clock,
147 device_uid_out: *mut Option<&cf::String>,
148 device_out: *mut core_audio::Device,
149 tracking_default_device_out: *mut bool,
150 ) -> os::Status;
151}
152
153#[cfg(target_os = "macos")]
154#[cfg(test)]
155mod tests {
156 use crate::{cm, core_audio};
157
158 #[test]
159 fn basics() {
160 let clock = cm::Clock::with_audio_device_uid(None).unwrap();
161 assert!(clock.audio_device_uid().unwrap().is_none());
162 let device = clock.audio_device().unwrap();
163 assert!(!device.is_unknown());
164
165 assert_eq!(device, core_audio::System::default_output_device().unwrap());
166
167 assert!(clock.is_tracking_default_device().unwrap());
168
169 let _time = clock.time();
170
171 let clock =
172 cm::Clock::with_audio_device(core_audio::System::default_output_device().unwrap())
173 .unwrap();
174 assert!(clock.audio_device_uid().unwrap().is_none());
175 let device = clock.audio_device().unwrap();
176 assert!(!device.is_unknown());
177
178 assert_eq!(device, core_audio::System::default_output_device().unwrap());
179
180 assert!(!clock.is_tracking_default_device().unwrap());
181 let _time = clock.time();
182 }
183}