1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
//! Audio input device enumeration using `AVFoundation`.
//!
//! This module provides access to available microphone devices on macOS.
use crate::utils::ffi_string::{ffi_string_from_buffer, SMALL_BUFFER_SIZE};
/// Represents an audio input device (microphone).
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AudioInputDevice {
/// The unique device ID used with `SCStreamConfiguration::with_microphone_capture_device_id`
pub id: String,
/// Human-readable device name
pub name: String,
/// Whether this is the system default audio input device
pub is_default: bool,
}
impl AudioInputDevice {
/// List all available audio input devices.
///
/// # Example
///
/// ```no_run
/// use screencapturekit::audio_devices::AudioInputDevice;
///
/// let devices = AudioInputDevice::list();
/// for device in &devices {
/// println!("{}: {} {}", device.id, device.name,
/// if device.is_default { "(default)" } else { "" });
/// }
/// ```
#[allow(clippy::cast_possible_wrap, clippy::cast_sign_loss)]
pub fn list() -> Vec<Self> {
let count = unsafe { crate::ffi::sc_audio_get_input_device_count() };
let mut devices = Vec::with_capacity(count as usize);
for i in 0..count {
let id = unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_audio_get_input_device_id(i, buf, len)
})
};
let name = unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_audio_get_input_device_name(i, buf, len)
})
};
let is_default = unsafe { crate::ffi::sc_audio_is_default_input_device(i) };
if let (Some(id), Some(name)) = (id, name) {
devices.push(Self {
id,
name,
is_default,
});
}
}
devices
}
/// Get the default audio input device, if any.
///
/// # Example
///
/// ```no_run
/// use screencapturekit::audio_devices::AudioInputDevice;
///
/// if let Some(device) = AudioInputDevice::default_device() {
/// println!("Default microphone: {}", device.name);
/// }
/// ```
pub fn default_device() -> Option<Self> {
let id = unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_audio_get_default_input_device_id(buf, len)
})
};
let name = unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_audio_get_default_input_device_name(buf, len)
})
};
match (id, name) {
(Some(id), Some(name)) => Some(Self {
id,
name,
is_default: true,
}),
_ => None,
}
}
}