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
134
135
136
137
138
139
140
141
// 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 std::ffi::c_int;
use crate::{Dsp, DspConnection, DspConnectionType};
use crate::{FmodResultExt, Result};
#[cfg(doc)]
use crate::System;
impl Dsp {
/// Adds a [`Dsp`] unit as an input to this object.
///
/// When a [`Dsp`] has multiple inputs the signals are automatically mixed together, sent to the unit's output(s).
///
/// The returned [`DspConnection`] will remain valid until the units are disconnected.
pub fn add_input(&self, input: Dsp, kind: DspConnectionType) -> Result<DspConnection> {
let mut connection = std::ptr::null_mut();
unsafe {
FMOD_DSP_AddInput(
self.inner.as_ptr(),
input.inner.as_ptr(),
&raw mut connection,
kind.into(),
)
.to_result()?;
Ok(DspConnection::from_ffi(connection))
}
}
/// Adds a [`Dsp`] unit as an impit to this object.
///
/// Unlike [`Dsp::add_input`], this takes a preallocated [`DspConnection`] created from [`System::create_dsp_connection`].
// this could be an extra enum variant instead of a new function but this is easier to understand imo?
// we'd also need 2 enums, one for create_dsp_connection, one for here...
// FIXME maybe have custom preallocated connection type to prevent UB?
// is *using* other connections that aren't prealloc'd UB?? FMOD docs why so unclear
#[cfg(fmod_gte_2_3_9)]
pub fn add_input_preallocated(&self, input: Dsp, connection: DspConnection) -> Result<()> {
// we could also use (&raw mut connection).cast() but this is easier to read
let mut raw_connection = connection.as_ptr();
unsafe {
FMOD_DSP_AddInput(
self.inner.as_ptr(),
input.inner.as_ptr(),
&raw mut raw_connection,
FMOD_DSPCONNECTION_TYPE_PREALLOCATED,
)
.to_result()
}
}
/// Retrieves the [`Dsp`] unit at the specified index in the input list.
///
/// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the input list is correct, avoid this during time sensitive operations.
///
/// The returned [`DspConnection`] will remain valid until the units are disconnected.
pub fn get_input(&self, index: c_int) -> Result<(Dsp, DspConnection)> {
let mut connection = std::ptr::null_mut();
let mut dsp = std::ptr::null_mut();
unsafe {
FMOD_DSP_GetInput(
self.inner.as_ptr(),
index,
&raw mut dsp,
&raw mut connection,
)
.to_result()?;
Ok((Dsp::from_ffi(dsp), DspConnection::from_ffi(connection)))
}
}
/// Retrieves the [`Dsp`] unit at the specified index in the output list.
///
/// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the output list is correct, avoid this during time sensitive operations.
///
/// The returned [`DspConnection`] will remain valid until the units are disconnected.
pub fn get_output(&self, index: c_int) -> Result<(Dsp, DspConnection)> {
let mut connection = std::ptr::null_mut();
let mut dsp = std::ptr::null_mut();
unsafe {
FMOD_DSP_GetOutput(
self.inner.as_ptr(),
index,
&raw mut dsp,
&raw mut connection,
)
.to_result()?;
Ok((Dsp::from_ffi(dsp), DspConnection::from_ffi(connection)))
}
}
/// Retrieves the number of [`Dsp`] units in the input list.
///
/// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the input list is correct, avoid this during time sensitive operations.
pub fn get_input_count(&self) -> Result<c_int> {
let mut count = 0;
unsafe {
FMOD_DSP_GetNumInputs(self.inner.as_ptr(), &raw mut count).to_result()?;
}
Ok(count)
}
/// Retrieves the number of [`Dsp`] units in the output list.
///
/// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the output list is correct, avoid this during time sensitive operations.
pub fn get_output_count(&self) -> Result<c_int> {
let mut count = 0;
unsafe { FMOD_DSP_GetNumOutputs(self.inner.as_ptr(), &raw mut count).to_result()? };
Ok(count)
}
/// Disconnects all inputs and/or outputs.
///
/// This is a convenience function that is faster than disconnecting all inputs and outputs individually.
pub fn disconnect_all(&self, inputs: bool, outputs: bool) -> Result<()> {
unsafe {
FMOD_DSP_DisconnectAll(self.inner.as_ptr(), inputs.into(), outputs.into()).to_result()
}
}
/// Disconnect the specified input [`Dsp`].
///
/// If target had only one output, after this operation that entire sub graph will no longer be connected to the [`Dsp`] network.
///
/// After this operation `connection` is no longer valid.
pub fn disconnect_from(
&self,
target: Option<Dsp>,
connection: Option<DspConnection>,
) -> Result<()> {
let target = target.map_or(std::ptr::null_mut(), Into::into);
let connection = connection.map_or(std::ptr::null_mut(), Into::into);
unsafe { FMOD_DSP_DisconnectFrom(self.inner.as_ptr(), target, connection).to_result() }
}
}