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