fmod/core/dsp/connections.rs
1// Copyright (c) 2024 Melody Madeline Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use fmod_sys::*;
8use std::ffi::c_int;
9
10use crate::{Dsp, DspConnection, DspConnectionType};
11use crate::{FmodResultExt, Result};
12
13#[cfg(doc)]
14use crate::System;
15
16impl Dsp {
17 /// Adds a [`Dsp`] unit as an input to this object.
18 ///
19 /// When a [`Dsp`] has multiple inputs the signals are automatically mixed together, sent to the unit's output(s).
20 ///
21 /// The returned [`DspConnection`] will remain valid until the units are disconnected.
22 pub fn add_input(&self, input: Dsp, kind: DspConnectionType) -> Result<DspConnection> {
23 let mut connection = std::ptr::null_mut();
24 unsafe {
25 FMOD_DSP_AddInput(
26 self.inner.as_ptr(),
27 input.inner.as_ptr(),
28 &raw mut connection,
29 kind.into(),
30 )
31 .to_result()?;
32 Ok(DspConnection::from_ffi(connection))
33 }
34 }
35
36 /// Adds a [`Dsp`] unit as an impit to this object.
37 ///
38 /// Unlike [`Dsp::add_input`], this takes a preallocated [`DspConnection`] created from [`System::create_dsp_connection`].
39 // this could be an extra enum variant instead of a new function but this is easier to understand imo?
40 // we'd also need 2 enums, one for create_dsp_connection, one for here...
41 // FIXME maybe have custom preallocated connection type to prevent UB?
42 // is *using* other connections that aren't prealloc'd UB?? FMOD docs why so unclear
43 #[cfg(fmod_gte_2_3_9)]
44 pub fn add_input_preallocated(&self, input: Dsp, connection: DspConnection) -> Result<()> {
45 // we could also use (&raw mut connection).cast() but this is easier to read
46 let mut raw_connection = connection.as_ptr();
47 unsafe {
48 FMOD_DSP_AddInput(
49 self.inner.as_ptr(),
50 input.inner.as_ptr(),
51 &raw mut raw_connection,
52 FMOD_DSPCONNECTION_TYPE_PREALLOCATED,
53 )
54 .to_result()
55 }
56 }
57
58 /// Retrieves the [`Dsp`] unit at the specified index in the input list.
59 ///
60 /// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the input list is correct, avoid this during time sensitive operations.
61 ///
62 /// The returned [`DspConnection`] will remain valid until the units are disconnected.
63 pub fn get_input(&self, index: c_int) -> Result<(Dsp, DspConnection)> {
64 let mut connection = std::ptr::null_mut();
65 let mut dsp = std::ptr::null_mut();
66 unsafe {
67 FMOD_DSP_GetInput(
68 self.inner.as_ptr(),
69 index,
70 &raw mut dsp,
71 &raw mut connection,
72 )
73 .to_result()?;
74 Ok((Dsp::from_ffi(dsp), DspConnection::from_ffi(connection)))
75 }
76 }
77
78 /// Retrieves the [`Dsp`] unit at the specified index in the output list.
79 ///
80 /// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the output list is correct, avoid this during time sensitive operations.
81 ///
82 /// The returned [`DspConnection`] will remain valid until the units are disconnected.
83 pub fn get_output(&self, index: c_int) -> Result<(Dsp, DspConnection)> {
84 let mut connection = std::ptr::null_mut();
85 let mut dsp = std::ptr::null_mut();
86 unsafe {
87 FMOD_DSP_GetOutput(
88 self.inner.as_ptr(),
89 index,
90 &raw mut dsp,
91 &raw mut connection,
92 )
93 .to_result()?;
94 Ok((Dsp::from_ffi(dsp), DspConnection::from_ffi(connection)))
95 }
96 }
97
98 /// Retrieves the number of [`Dsp`] units in the input list.
99 ///
100 /// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the input list is correct, avoid this during time sensitive operations.
101 pub fn get_input_count(&self) -> Result<c_int> {
102 let mut count = 0;
103 unsafe {
104 FMOD_DSP_GetNumInputs(self.inner.as_ptr(), &raw mut count).to_result()?;
105 }
106 Ok(count)
107 }
108
109 /// Retrieves the number of [`Dsp`] units in the output list.
110 ///
111 /// This will flush the [`Dsp`] queue (which blocks against the mixer) to ensure the output list is correct, avoid this during time sensitive operations.
112 pub fn get_output_count(&self) -> Result<c_int> {
113 let mut count = 0;
114 unsafe { FMOD_DSP_GetNumOutputs(self.inner.as_ptr(), &raw mut count).to_result()? };
115 Ok(count)
116 }
117
118 /// Disconnects all inputs and/or outputs.
119 ///
120 /// This is a convenience function that is faster than disconnecting all inputs and outputs individually.
121 pub fn disconnect_all(&self, inputs: bool, outputs: bool) -> Result<()> {
122 unsafe {
123 FMOD_DSP_DisconnectAll(self.inner.as_ptr(), inputs.into(), outputs.into()).to_result()
124 }
125 }
126
127 /// Disconnect the specified input [`Dsp`].
128 ///
129 /// If target had only one output, after this operation that entire sub graph will no longer be connected to the [`Dsp`] network.
130 ///
131 /// After this operation `connection` is no longer valid.
132 pub fn disconnect_from(
133 &self,
134 target: Option<Dsp>,
135 connection: Option<DspConnection>,
136 ) -> Result<()> {
137 let target = target.map_or(std::ptr::null_mut(), Into::into);
138 let connection = connection.map_or(std::ptr::null_mut(), Into::into);
139 unsafe { FMOD_DSP_DisconnectFrom(self.inner.as_ptr(), target, connection).to_result() }
140 }
141}