fmod/studio/bank/
lookups.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 std::{ffi::c_int, mem::MaybeUninit};
8
9use crate::studio::{Bank, Bus, EventDescription, Vca};
10use crate::Guid;
11use fmod_sys::*;
12use lanyard::Utf8CString;
13
14impl Bank {
15    /// Retrieves the number of buses in the bank.
16    pub fn bus_count(&self) -> Result<c_int> {
17        let mut count = 0;
18        unsafe {
19            FMOD_Studio_Bank_GetBusCount(self.inner, &mut count).to_result()?;
20        }
21        Ok(count)
22    }
23
24    /// Retrieves a list of the buses in the bank.
25    pub fn get_bus_list(&self) -> Result<Vec<Bus>> {
26        let expected_count = self.bus_count()?;
27        let mut count = 0;
28        let mut list = vec![
29            Bus {
30                inner: std::ptr::null_mut()
31            };
32            expected_count as usize
33        ];
34
35        unsafe {
36            FMOD_Studio_Bank_GetBusList(
37                self.inner,
38                // bus is repr transparent and has the same layout as *mut FMOD_STUDIO_BUS, so this cast is ok
39                list.as_mut_ptr().cast::<*mut FMOD_STUDIO_BUS>(),
40                list.capacity() as c_int,
41                &mut count,
42            )
43            .to_result()?;
44
45            debug_assert_eq!(count, expected_count);
46
47            Ok(list)
48        }
49    }
50
51    /// Retrives the number of event descriptions in the bank.
52    ///
53    /// This function counts the events which were added to the bank by the sound designer.
54    /// The bank may contain additional events which are referenced by event instruments but were not added to the bank, and those referenced events are not counted.
55    pub fn event_count(&self) -> Result<c_int> {
56        let mut count = 0;
57        unsafe {
58            FMOD_Studio_Bank_GetEventCount(self.inner, &mut count).to_result()?;
59        }
60        Ok(count)
61    }
62
63    /// Retrieves a list of the event descriptions in the bank.
64    ///
65    /// This function counts the events which were added to the bank by the sound designer.
66    /// The bank may contain additional events which are referenced by event instruments but were not added to the bank, and those referenced events are not counted.
67    pub fn get_event_list(&self) -> Result<Vec<EventDescription>> {
68        let expected_count = self.event_count()?;
69        let mut count = 0;
70        let mut list = vec![std::ptr::null_mut(); expected_count as usize];
71
72        unsafe {
73            FMOD_Studio_Bank_GetEventList(
74                self.inner,
75                // bus is repr transparent and has the same layout as *mut FMOD_STUDIO_BUS, so this cast is ok
76                list.as_mut_ptr(),
77                list.capacity() as c_int,
78                &mut count,
79            )
80            .to_result()?;
81
82            debug_assert_eq!(count, expected_count);
83
84            Ok(std::mem::transmute::<
85                Vec<*mut fmod_sys::FMOD_STUDIO_EVENTDESCRIPTION>,
86                Vec<EventDescription>,
87            >(list))
88        }
89    }
90
91    /// Retrieves the number of string table entries in the bank.
92    pub fn string_count(&self) -> Result<c_int> {
93        let mut count = 0;
94        unsafe {
95            FMOD_Studio_Bank_GetStringCount(self.inner, &mut count).to_result()?;
96        }
97        Ok(count)
98    }
99
100    /// Retrieves a string table entry.
101    ///
102    /// May be used in conjunction with [`Bank::string_count`] to enumerate the string table in a bank.
103    pub fn get_string_info(&self, index: c_int) -> Result<(Guid, Utf8CString)> {
104        let mut string_len = 0;
105
106        // retrieve the length of the string.
107        // this includes the null terminator, so we don't need to account for that.
108        unsafe {
109            let error = FMOD_Studio_Bank_GetStringInfo(
110                self.inner,
111                index,
112                std::ptr::null_mut(),
113                std::ptr::null_mut(),
114                0,
115                &mut string_len,
116            )
117            .to_error();
118
119            // we expect the error to be fmod_err_truncated.
120            // if it isn't, we return the error.
121            match error {
122                Some(error) if error != FMOD_RESULT::FMOD_ERR_TRUNCATED => return Err(error),
123                _ => {}
124            }
125        };
126
127        let mut guid = MaybeUninit::zeroed();
128        let mut path = vec![0u8; string_len as usize];
129        let mut expected_string_len = 0;
130
131        unsafe {
132            FMOD_Studio_Bank_GetStringInfo(
133                self.inner,
134                index,
135                guid.as_mut_ptr(),
136                // u8 and i8 have the same layout, so this is ok
137                path.as_mut_ptr().cast(),
138                string_len,
139                &mut expected_string_len,
140            )
141            .to_result()?;
142
143            debug_assert_eq!(string_len, expected_string_len);
144
145            // even if fmod didn't write to guid, guid should be safe to zero initialize.
146            let guid = guid.assume_init().into();
147            // all public fmod apis return UTF-8 strings. this should be safe.
148            // if i turn out to be wrong, perhaps we should add extra error types?
149            let path = Utf8CString::from_utf8_with_nul_unchecked(path);
150
151            Ok((guid, path))
152        }
153    }
154
155    /// Retrieves the number of VCAs in the bank.
156    pub fn vca_count(&self) -> Result<c_int> {
157        let mut count = 0;
158        unsafe {
159            FMOD_Studio_Bank_GetVCACount(self.inner, &mut count).to_result()?;
160        }
161        Ok(count)
162    }
163
164    /// Retrieves a list of the VCAs in the bank.
165    pub fn get_vca_list(&self) -> Result<Vec<Vca>> {
166        let expected_count = self.event_count()?;
167        let mut count = 0;
168        let mut list = vec![
169            Vca {
170                inner: std::ptr::null_mut()
171            };
172            expected_count as usize
173        ];
174
175        unsafe {
176            FMOD_Studio_Bank_GetVCAList(
177                self.inner,
178                // bus is repr transparent and has the same layout as *mut FMOD_STUDIO_BUS, so this cast is ok
179                list.as_mut_ptr().cast::<*mut FMOD_STUDIO_VCA>(),
180                list.capacity() as c_int,
181                &mut count,
182            )
183            .to_result()?;
184
185            debug_assert_eq!(count, expected_count);
186
187            Ok(list)
188        }
189    }
190}