use crate::utils::ffi_string::{ffi_string_from_buffer, SMALL_BUFFER_SIZE};
use super::internal::SCStreamConfiguration;
#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum AudioSampleRate {
Rate8000 = 8000,
Rate16000 = 16000,
Rate24000 = 24000,
#[default]
Rate48000 = 48000,
}
impl AudioSampleRate {
#[must_use]
pub const fn as_hz(self) -> i32 {
self as i32
}
#[must_use]
pub const fn from_hz(hz: i32) -> Option<Self> {
match hz {
8000 => Some(Self::Rate8000),
16000 => Some(Self::Rate16000),
24000 => Some(Self::Rate24000),
48000 => Some(Self::Rate48000),
_ => None,
}
}
}
impl std::fmt::Display for AudioSampleRate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{} Hz", self.as_hz())
}
}
impl From<AudioSampleRate> for i32 {
fn from(rate: AudioSampleRate) -> Self {
rate.as_hz()
}
}
#[repr(i32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum AudioChannelCount {
Mono = 1,
#[default]
Stereo = 2,
}
impl AudioChannelCount {
#[must_use]
pub const fn as_count(self) -> i32 {
self as i32
}
#[must_use]
pub const fn from_count(count: i32) -> Option<Self> {
match count {
1 => Some(Self::Mono),
2 => Some(Self::Stereo),
_ => None,
}
}
}
impl std::fmt::Display for AudioChannelCount {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Mono => write!(f, "Mono (1 channel)"),
Self::Stereo => write!(f, "Stereo (2 channels)"),
}
}
}
impl From<AudioChannelCount> for i32 {
fn from(count: AudioChannelCount) -> Self {
count.as_count()
}
}
impl SCStreamConfiguration {
pub fn set_captures_audio(&mut self, captures_audio: bool) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_captures_audio(self.as_ptr(), captures_audio);
}
self
}
#[must_use]
pub fn with_captures_audio(mut self, captures_audio: bool) -> Self {
self.set_captures_audio(captures_audio);
self
}
pub fn captures_audio(&self) -> bool {
unsafe { crate::ffi::sc_stream_configuration_get_captures_audio(self.as_ptr()) }
}
pub fn set_sample_rate(&mut self, sample_rate: impl Into<i32>) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_sample_rate(
self.as_ptr(),
sample_rate.into() as isize,
);
}
self
}
#[must_use]
pub fn with_sample_rate(mut self, sample_rate: impl Into<i32>) -> Self {
self.set_sample_rate(sample_rate);
self
}
pub fn sample_rate(&self) -> i32 {
#[allow(clippy::cast_possible_truncation)]
unsafe {
crate::ffi::sc_stream_configuration_get_sample_rate(self.as_ptr()) as i32
}
}
pub fn audio_sample_rate(&self) -> Option<AudioSampleRate> {
AudioSampleRate::from_hz(self.sample_rate())
}
pub fn set_channel_count(&mut self, channel_count: impl Into<i32>) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_channel_count(
self.as_ptr(),
channel_count.into() as isize,
);
}
self
}
#[must_use]
pub fn with_channel_count(mut self, channel_count: impl Into<i32>) -> Self {
self.set_channel_count(channel_count);
self
}
pub fn channel_count(&self) -> i32 {
#[allow(clippy::cast_possible_truncation)]
unsafe {
crate::ffi::sc_stream_configuration_get_channel_count(self.as_ptr()) as i32
}
}
pub fn audio_channel_count(&self) -> Option<AudioChannelCount> {
AudioChannelCount::from_count(self.channel_count())
}
pub fn set_captures_microphone(&mut self, captures_microphone: bool) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_captures_microphone(
self.as_ptr(),
captures_microphone,
);
}
self
}
#[must_use]
pub fn with_captures_microphone(mut self, captures_microphone: bool) -> Self {
self.set_captures_microphone(captures_microphone);
self
}
pub fn captures_microphone(&self) -> bool {
unsafe { crate::ffi::sc_stream_configuration_get_captures_microphone(self.as_ptr()) }
}
pub fn set_excludes_current_process_audio(&mut self, excludes: bool) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_excludes_current_process_audio(
self.as_ptr(),
excludes,
);
}
self
}
#[must_use]
pub fn with_excludes_current_process_audio(mut self, excludes: bool) -> Self {
self.set_excludes_current_process_audio(excludes);
self
}
pub fn excludes_current_process_audio(&self) -> bool {
unsafe {
crate::ffi::sc_stream_configuration_get_excludes_current_process_audio(self.as_ptr())
}
}
pub fn set_microphone_capture_device_id(&mut self, device_id: &str) -> &mut Self {
unsafe {
if let Ok(c_id) = std::ffi::CString::new(device_id) {
crate::ffi::sc_stream_configuration_set_microphone_capture_device_id(
self.as_ptr(),
c_id.as_ptr(),
);
}
}
self
}
#[must_use]
pub fn with_microphone_capture_device_id(mut self, device_id: &str) -> Self {
self.set_microphone_capture_device_id(device_id);
self
}
pub fn clear_microphone_capture_device_id(&mut self) -> &mut Self {
unsafe {
crate::ffi::sc_stream_configuration_set_microphone_capture_device_id(
self.as_ptr(),
std::ptr::null(),
);
}
self
}
pub fn microphone_capture_device_id(&self) -> Option<String> {
unsafe {
ffi_string_from_buffer(SMALL_BUFFER_SIZE, |buf, len| {
crate::ffi::sc_stream_configuration_get_microphone_capture_device_id(
self.as_ptr(),
buf,
len,
)
})
}
}
}