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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
// Copyright (c) 2024 Melody Madeline Lyons
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use std::{
ffi::{c_int, c_uint},
mem::MaybeUninit,
};
use crate::{FmodResultExt, Result};
use fmod_sys::*;
use lanyard::Utf8CString;
use crate::{DriverState, Guid, Sound, SpeakerMode, System, get_string};
#[cfg(doc)]
use crate::Mode;
impl System {
/// Retrieves the number of recording devices available for this output mode.
/// Use this to enumerate all recording devices possible so that the user can select one.
pub fn get_recording_driver_count(&self) -> Result<(c_int, c_int)> {
let mut drivers = 0;
let mut connected = 0;
unsafe {
FMOD_System_GetRecordNumDrivers(
self.inner.as_ptr(),
&raw mut drivers,
&raw mut connected,
)
.to_result()?;
}
Ok((drivers, connected))
}
/// Retrieves identification information about an audio device specified by its index, and specific to the output mode.
pub fn get_record_driver_info(
&self,
id: c_int,
) -> Result<(Utf8CString, Guid, c_int, SpeakerMode, c_int, DriverState)> {
let mut guid = MaybeUninit::zeroed();
let mut system_rate = 0;
let mut speaker_mode = 0;
let mut speaker_mode_channels = 0;
let mut state = 0;
let name = get_string(|name| unsafe {
FMOD_System_GetRecordDriverInfo(
self.inner.as_ptr(),
id,
name.as_mut_ptr().cast(),
name.len() as c_int,
guid.as_mut_ptr(),
&raw mut system_rate,
&raw mut speaker_mode,
&raw mut speaker_mode_channels,
&raw mut state,
)
})?;
unsafe {
let guid = guid.assume_init().into();
let speaker_mode = speaker_mode.try_into()?;
let state = state.into();
Ok((
name,
guid,
system_rate,
speaker_mode,
speaker_mode_channels,
state,
))
}
}
/// Retrieves the current recording position of the record buffer in PCM samples.
///
/// Will return [`FMOD_RESULT::FMOD_ERR_RECORD_DISCONNECTED`] if the driver is unplugged.
///
/// The position will return to 0 when [`System::record_stop`] is called or when a non-looping recording reaches the end.
///
/// PS4 specific note: Record devices are virtual so 'position' will continue to update if the device is unplugged (the OS is generating silence).
/// This function will still report [`FMOD_RESULT::FMOD_ERR_RECORD_DISCONNECTED`] for your information though.
pub fn get_record_position(&self, id: c_int) -> Result<c_uint> {
let mut position = 0;
unsafe {
FMOD_System_GetRecordPosition(self.inner.as_ptr(), id, &raw mut position)
.to_result()?;
}
Ok(position)
}
/// Starts the recording engine recording to a pre-created Sound object.
///
/// Will return [`FMOD_RESULT::FMOD_ERR_RECORD_DISCONNECTED`] if the driver is unplugged.
///
/// Sound must be created as [`Mode::CREATE_SAMPLE`].
/// Raw PCM data can be accessed with `Sound::lock`, `Sound::unlock` and [`System::get_record_position`].
///
/// Recording from the same driver a second time will stop the first recording.
///
/// For lowest latency set the [`Sound`] sample rate to the rate returned by `System::getRecordDriverInfo`,
/// otherwise a resampler will be allocated to handle the difference in frequencies, which adds latency.
pub fn record_start(&self, id: c_int, sound: Sound, do_loop: bool) -> Result<()> {
unsafe {
FMOD_System_RecordStart(self.inner.as_ptr(), id, sound.into(), do_loop.into())
.to_result()
}
}
/// Stops the recording engine from recording to a pre-created Sound object.
///
/// Returns no error if unplugged or already stopped.
pub fn record_stop(&self, id: c_int) -> Result<()> {
unsafe { FMOD_System_RecordStop(self.inner.as_ptr(), id).to_result() }
}
/// Retrieves the state of the FMOD recording API, ie if it is currently recording or not.
///
/// Recording can be started with [`System::record_start`] and stopped with [`System::record_stop`].
///
/// Will return [`FMOD_RESULT::FMOD_ERR_RECORD_DISCONNECTED`] if the driver is unplugged.
///
/// PS4 specific note: Record devices are virtual so 'position' will continue to update if the device is unplugged (the OS is generating silence).
/// This function will still report [`FMOD_RESULT::FMOD_ERR_RECORD_DISCONNECTED`] for your information though.
pub fn is_recording(&self, id: c_int) -> Result<bool> {
let mut recording = FMOD_BOOL::FALSE;
unsafe {
FMOD_System_IsRecording(self.inner.as_ptr(), id, &raw mut recording).to_result()?;
}
Ok(recording.into())
}
}