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}