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 fmod_sys::*;
use lanyard::{Utf8CStr, Utf8CString};
use std::ffi::{c_char, c_int, c_uint, c_void};
use crate::{Dsp, DspType, System};
use crate::{FmodResultExt, Result};
#[derive(Debug)]
pub struct DspInfo {
// FIXME: this is always 32 byes, it doesn't need to be heap allocated
pub name: Utf8CString,
pub version: c_uint,
pub channels: c_int,
pub config_width: c_int,
pub config_height: c_int,
}
impl Dsp {
/// Display or hide a DSP unit configuration dialog box inside the target window.
///
/// Some DSP plug-ins (especially VST plug-ins) use dialog boxes to display graphical user interfaces for modifying their parameters,
/// rather than using the other method of enumerating their parameters and setting them
/// with [`Dsp::set_parameter`].
///
/// To find out what size window to create to store the configuration screen, use [`Dsp::get_info`] where you can get the width and height.
///
/// # Safety
///
/// `hwnd` must be a valid window pointer.
/// On Windows, this would be a `HWND`, on X11 a window id, etc.
// FIXME Is that right?
pub unsafe fn show_config_dialogue(&self, hwnd: *mut c_void, show: bool) -> Result<()> {
unsafe { FMOD_DSP_ShowConfigDialog(self.inner.as_ptr(), hwnd, show.into()).to_result() }
}
/// Reset a DSPs internal state ready for new input signal.
///
/// This will clear all internal state derived from input signal while retaining any set parameter values.
/// The intended use of the function is to avoid audible artifacts if moving the [`Dsp`] from one part of the [`Dsp`] network to another.
pub fn reset(&self) -> Result<()> {
unsafe { FMOD_DSP_Reset(self.inner.as_ptr()).to_result() }
}
/// Frees a [`Dsp`] object.
///
/// If [`Dsp`] is not removed from the network with `ChannelControl::removeDSP` after being added with `ChannelControl::addDSP`,
/// it will not release and will instead return [`FMOD_RESULT::FMOD_ERR_DSP_INUSE`].
pub fn release(&self) -> Result<()> {
unsafe { FMOD_DSP_Release(self.inner.as_ptr()).to_result() }
}
/// Retrieves the pre-defined type of a FMOD registered [`Dsp`] unit.
pub fn get_type(&self) -> Result<DspType> {
let mut dsp_type = 0;
unsafe { FMOD_DSP_GetType(self.inner.as_ptr(), &raw mut dsp_type).to_result()? };
let dsp_type = dsp_type.try_into()?;
Ok(dsp_type)
}
/// Retrieves information about this DSP unit.
pub fn get_info(&self) -> Result<DspInfo> {
let mut buffer = [0u8; 32];
let mut version = 0;
let mut channels = 0;
let mut config_width = 0;
let mut config_height = 0;
unsafe {
FMOD_DSP_GetInfo(
self.inner.as_ptr(),
buffer.as_mut_ptr().cast::<c_char>(),
&raw mut version,
&raw mut channels,
&raw mut config_width,
&raw mut config_height,
)
.to_result()?;
}
let name =
unsafe { Utf8CStr::from_utf8_until_nul(&buffer).unwrap_unchecked() }.to_cstring();
Ok(DspInfo {
name,
version,
channels,
config_width,
config_height,
})
}
/// Retrieves statistics on the mixer thread CPU usage for this unit.
///
/// [`crate::InitFlags::PROFILE_ENABLE`] with [`crate::SystemBuilder::new`] is required to call this function.
pub fn get_cpu_usage(&self) -> Result<(c_uint, c_uint)> {
let mut exclusive = 0;
let mut inclusive = 0;
unsafe {
FMOD_DSP_GetCPUUsage(self.inner.as_ptr(), &raw mut exclusive, &raw mut inclusive)
.to_result()?;
}
Ok((exclusive, inclusive))
}
/// Sets the user data.
#[allow(clippy::not_unsafe_ptr_arg_deref)] // fmod doesn't dereference the passed in pointer, and the user dereferencing it is unsafe anyway
pub fn set_userdata(&self, userdata: *mut c_void) -> Result<()> {
unsafe { FMOD_DSP_SetUserData(self.inner.as_ptr(), userdata).to_result() }
}
/// Retrieves user data.
pub fn get_userdata(&self) -> Result<*mut c_void> {
let mut userdata = std::ptr::null_mut();
unsafe {
FMOD_DSP_GetUserData(self.inner.as_ptr(), &raw mut userdata).to_result()?;
}
Ok(userdata)
}
/// Retrieves the parent System object.
pub fn get_system(&self) -> Result<System> {
let mut system = std::ptr::null_mut();
unsafe {
FMOD_DSP_GetSystemObject(self.inner.as_ptr(), &raw mut system).to_result()?;
Ok(System::from_ffi(system))
}
}
}