fmod/studio/event_description/
parameter.rs

1// Copyright (c) 2024 Lily 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 lanyard::{Utf8CStr, Utf8CString};
9use std::{ffi::c_int, mem::MaybeUninit};
10
11use crate::studio::{EventDescription, ParameterDescription, ParameterID};
12
13impl EventDescription {
14    /// Retrieves an event parameter description by name.
15    pub fn get_parameter_description_by_name(
16        &self,
17        name: &Utf8CStr,
18    ) -> Result<ParameterDescription> {
19        let mut description = MaybeUninit::zeroed();
20        unsafe {
21            FMOD_Studio_EventDescription_GetParameterDescriptionByName(
22                self.inner,
23                name.as_ptr(),
24                description.as_mut_ptr(),
25            )
26            .to_result()?;
27
28            let description = ParameterDescription::from_ffi(description.assume_init());
29            Ok(description)
30        }
31    }
32
33    /// Retrieves an event parameter description by id.
34    pub fn get_parameter_description_by_id(&self, id: ParameterID) -> Result<ParameterDescription> {
35        let mut description = MaybeUninit::zeroed();
36        unsafe {
37            FMOD_Studio_EventDescription_GetParameterDescriptionByID(
38                self.inner,
39                id.into(),
40                description.as_mut_ptr(),
41            )
42            .to_result()?;
43
44            let description = ParameterDescription::from_ffi(description.assume_init());
45            Ok(description)
46        }
47    }
48
49    /// Retrieves an event parameter description by index.
50    ///
51    /// May be used in combination with [`EventDescription::parameter_description_count`] to enumerate event parameters.
52    ///
53    /// Note: The order of parameters is not necessarily the same as what is shown in the FMOD Studio event editor.
54    pub fn get_parameter_description_by_index(&self, index: c_int) -> Result<ParameterDescription> {
55        let mut description = MaybeUninit::zeroed();
56        unsafe {
57            FMOD_Studio_EventDescription_GetParameterDescriptionByIndex(
58                self.inner,
59                index,
60                description.as_mut_ptr(),
61            )
62            .to_result()?;
63
64            let description = ParameterDescription::from_ffi(description.assume_init());
65            Ok(description)
66        }
67    }
68
69    /// Retrieves the number of parameters in the event.
70    ///
71    /// May be used in conjunction with [`EventDescription::get_parameter_description_by_index`] to enumerate event parameters.
72    pub fn parameter_description_count(&self) -> Result<c_int> {
73        let mut count = 0;
74        unsafe {
75            FMOD_Studio_EventDescription_GetParameterDescriptionCount(self.inner, &mut count)
76                .to_result()?;
77        }
78        Ok(count)
79    }
80
81    /// Retrieves an event parameter label by name or path.
82    ///
83    /// `name` can be the short name (such as `Wind`) or the full path (such as `parameter:/Ambience/Wind`).
84    /// Path lookups will only succeed if the strings bank has been loaded.
85    pub fn get_parameter_label_by_name(
86        &self,
87        name: &Utf8CStr,
88        label_index: c_int,
89    ) -> Result<Utf8CString> {
90        let mut string_len = 0;
91
92        // retrieve the length of the string.
93        // this includes the null terminator, so we don't need to account for that.
94        unsafe {
95            let error = FMOD_Studio_EventDescription_GetParameterLabelByName(
96                self.inner,
97                name.as_ptr(),
98                label_index,
99                std::ptr::null_mut(),
100                0,
101                &mut string_len,
102            )
103            .to_error();
104
105            // we expect the error to be fmod_err_truncated.
106            // if it isn't, we return the error.
107            match error {
108                Some(error) if error != FMOD_RESULT::FMOD_ERR_TRUNCATED => return Err(error),
109                _ => {}
110            }
111        };
112
113        let mut path = vec![0u8; string_len as usize];
114        let mut expected_string_len = 0;
115
116        unsafe {
117            FMOD_Studio_EventDescription_GetParameterLabelByName(
118                self.inner,
119                name.as_ptr(),
120                label_index,
121                // u8 and i8 have the same layout, so this is ok
122                path.as_mut_ptr().cast(),
123                string_len,
124                &mut expected_string_len,
125            )
126            .to_result()?;
127
128            debug_assert_eq!(string_len, expected_string_len);
129
130            // all public fmod apis return UTF-8 strings. this should be safe.
131            // if i turn out to be wrong, perhaps we should add extra error types?
132            let path = Utf8CString::from_utf8_with_nul_unchecked(path);
133
134            Ok(path)
135        }
136    }
137
138    /// Retrieves an event parameter label by ID.
139    pub fn get_parameter_label_by_id(
140        &self,
141        id: ParameterID,
142        label_index: c_int,
143    ) -> Result<Utf8CString> {
144        let mut string_len = 0;
145
146        // retrieve the length of the string.
147        // this includes the null terminator, so we don't need to account for that.
148        unsafe {
149            let error = FMOD_Studio_EventDescription_GetParameterLabelByID(
150                self.inner,
151                id.into(),
152                label_index,
153                std::ptr::null_mut(),
154                0,
155                &mut string_len,
156            )
157            .to_error();
158
159            // we expect the error to be fmod_err_truncated.
160            // if it isn't, we return the error.
161            match error {
162                Some(error) if error != FMOD_RESULT::FMOD_ERR_TRUNCATED => return Err(error),
163                _ => {}
164            }
165        };
166
167        let mut path = vec![0u8; string_len as usize];
168        let mut expected_string_len = 0;
169
170        unsafe {
171            FMOD_Studio_EventDescription_GetParameterLabelByID(
172                self.inner,
173                id.into(),
174                label_index,
175                // u8 and i8 have the same layout, so this is ok
176                path.as_mut_ptr().cast(),
177                string_len,
178                &mut expected_string_len,
179            )
180            .to_result()?;
181
182            debug_assert_eq!(string_len, expected_string_len);
183
184            // all public fmod apis return UTF-8 strings. this should be safe.
185            // if i turn out to be wrong, perhaps we should add extra error types?
186            let path = Utf8CString::from_utf8_with_nul_unchecked(path);
187
188            Ok(path)
189        }
190    }
191
192    /// Retrieves an event parameter label by index.
193    ///
194    /// May be used in combination with [`EventDescription::parameter_description_count`] to enumerate event parameters.
195    pub fn get_parameter_label_by_index(
196        &self,
197        index: c_int,
198        label_index: c_int,
199    ) -> Result<Utf8CString> {
200        let mut string_len = 0;
201
202        // retrieve the length of the string.
203        // this includes the null terminator, so we don't need to account for that.
204        unsafe {
205            let error = FMOD_Studio_EventDescription_GetParameterLabelByIndex(
206                self.inner,
207                index,
208                label_index,
209                std::ptr::null_mut(),
210                0,
211                &mut string_len,
212            )
213            .to_error();
214
215            // we expect the error to be fmod_err_truncated.
216            // if it isn't, we return the error.
217            match error {
218                Some(error) if error != FMOD_RESULT::FMOD_ERR_TRUNCATED => return Err(error),
219                _ => {}
220            }
221        };
222
223        let mut path = vec![0u8; string_len as usize];
224        let mut expected_string_len = 0;
225
226        unsafe {
227            FMOD_Studio_EventDescription_GetParameterLabelByIndex(
228                self.inner,
229                index,
230                label_index,
231                // u8 and i8 have the same layout, so this is ok
232                path.as_mut_ptr().cast(),
233                string_len,
234                &mut expected_string_len,
235            )
236            .to_result()?;
237
238            debug_assert_eq!(string_len, expected_string_len);
239
240            // all public fmod apis return UTF-8 strings. this should be safe.
241            // if i turn out to be wrong, perhaps we should add extra error types?
242            let path = Utf8CString::from_utf8_with_nul_unchecked(path);
243
244            Ok(path)
245        }
246    }
247}