nandi/jolt-nativepublic Fork 0
cfd3e3677bed92e80cfe447469a249cfdc0b1401
Commits
Clone
git clone https://git.rickub.com/nandi/jolt-native.git
git clone ssh://git@rickub.com/nandi/jolt-native.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

enumerate.rs · 140 lines · 4.2 KBRust Blame HistoryRaw
Lift freeq's AV media plane out of sleek 90f8b89 nandi 19d ago1use super::{Device, OSStatus};
2use crate::{BackendSpecificError, DevicesError};
3use objc2_core_audio::{
4 kAudioHardwareNoError, kAudioHardwarePropertyDefaultInputDevice,
5 kAudioHardwarePropertyDefaultOutputDevice, kAudioHardwarePropertyDevices,
6 kAudioObjectPropertyElementMaster, kAudioObjectPropertyScopeGlobal, kAudioObjectSystemObject,
7 AudioDeviceID, AudioObjectGetPropertyData, AudioObjectGetPropertyDataSize, AudioObjectID,
8 AudioObjectPropertyAddress,
9};
10use std::mem;
11use std::ptr::{null, NonNull};
12use std::vec::IntoIter as VecIntoIter;
13
14unsafe fn audio_devices() -> Result<Vec<AudioDeviceID>, OSStatus> {
15 let property_address = AudioObjectPropertyAddress {
16 mSelector: kAudioHardwarePropertyDevices,
17 mScope: kAudioObjectPropertyScopeGlobal,
18 mElement: kAudioObjectPropertyElementMaster,
19 };
20
21 macro_rules! try_status_or_return {
22 ($status:expr) => {
23 if $status != kAudioHardwareNoError as i32 {
24 return Err($status);
25 }
26 };
27 }
28
29 let mut data_size = 0u32;
30 let status = AudioObjectGetPropertyDataSize(
31 kAudioObjectSystemObject as AudioObjectID,
32 NonNull::from(&property_address),
33 0,
34 null(),
35 NonNull::from(&mut data_size),
36 );
37 try_status_or_return!(status);
38
39 let device_count = data_size / mem::size_of::<AudioDeviceID>() as u32;
40 let mut audio_devices = vec![];
41 audio_devices.reserve_exact(device_count as usize);
42
43 let status = AudioObjectGetPropertyData(
44 kAudioObjectSystemObject as AudioObjectID,
45 NonNull::from(&property_address),
46 0,
47 null(),
48 NonNull::from(&mut data_size),
49 NonNull::new(audio_devices.as_mut_ptr()).unwrap().cast(),
50 );
51 try_status_or_return!(status);
52
53 audio_devices.set_len(device_count as usize);
54
55 Ok(audio_devices)
56}
57
58pub struct Devices(VecIntoIter<AudioDeviceID>);
59
60impl Devices {
61 pub fn new() -> Result<Self, DevicesError> {
62 let devices = unsafe {
63 match audio_devices() {
64 Ok(devices) => devices,
65 Err(os_status) => {
66 let description = format!("{os_status}");
67 let err = BackendSpecificError { description };
68 return Err(err.into());
69 }
70 }
71 };
72 Ok(Devices(devices.into_iter()))
73 }
74}
75
76impl Iterator for Devices {
77 type Item = Device;
78
79 fn next(&mut self) -> Option<Device> {
80 self.0.next().map(|id| Device {
81 audio_device_id: id,
82 })
83 }
84}
85
86pub fn default_input_device() -> Option<Device> {
87 let property_address = AudioObjectPropertyAddress {
88 mSelector: kAudioHardwarePropertyDefaultInputDevice,
89 mScope: kAudioObjectPropertyScopeGlobal,
90 mElement: kAudioObjectPropertyElementMaster,
91 };
92
93 let mut audio_device_id: AudioDeviceID = 0;
94 let data_size = mem::size_of::<AudioDeviceID>() as u32;
95 let status = unsafe {
96 AudioObjectGetPropertyData(
97 kAudioObjectSystemObject as AudioObjectID,
98 NonNull::from(&property_address),
99 0,
100 null(),
101 NonNull::from(&data_size),
102 NonNull::from(&mut audio_device_id).cast(),
103 )
104 };
105 if status != kAudioHardwareNoError {
106 return None;
107 }
108
109 let device = Device { audio_device_id };
110 Some(device)
111}
112
113pub fn default_output_device() -> Option<Device> {
114 let property_address = AudioObjectPropertyAddress {
115 mSelector: kAudioHardwarePropertyDefaultOutputDevice,
116 mScope: kAudioObjectPropertyScopeGlobal,
117 mElement: kAudioObjectPropertyElementMaster,
118 };
119
120 let mut audio_device_id: AudioDeviceID = 0;
121 let data_size = mem::size_of::<AudioDeviceID>() as u32;
122 let status = unsafe {
123 AudioObjectGetPropertyData(
124 kAudioObjectSystemObject as AudioObjectID,
125 NonNull::from(&property_address),
126 0,
127 null(),
128 NonNull::from(&data_size),
129 NonNull::from(&mut audio_device_id).cast(),
130 )
131 };
132 if status != kAudioHardwareNoError {
133 return None;
134 }
135
136 let device = Device { audio_device_id };
137 Some(device)
138}
139
140pub use crate::iter::{SupportedInputConfigs, SupportedOutputConfigs};