fmod/studio/bank/
lookups.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 std::ptr::NonNull;
8use std::{ffi::c_int, mem::MaybeUninit};
9
10use crate::Guid;
11use crate::studio::{Bank, Bus, EventDescription, Vca, get_string_out_size};
12use crate::{FmodResultExt, Result};
13use fmod_sys::*;
14use lanyard::Utf8CString;
15
16impl Bank {
17    /// Retrieves the number of buses in the bank.
18    pub fn bus_count(&self) -> Result<c_int> {
19        let mut count = 0;
20        unsafe {
21            FMOD_Studio_Bank_GetBusCount(self.inner.as_ptr(), &raw mut count).to_result()?;
22        }
23        Ok(count)
24    }
25
26    /// Retrieves a list of the buses in the bank.
27    pub fn get_bus_list(&self) -> Result<Vec<Bus>> {
28        let expected_count = self.bus_count()?;
29        let mut count = 0;
30        let mut list = vec![
31            Bus {
32                inner: NonNull::dangling(), // we can't store a *null* NonNull pointer so we use NonNull::dangling instead
33            };
34            expected_count as usize
35        ];
36
37        unsafe {
38            FMOD_Studio_Bank_GetBusList(
39                self.inner.as_ptr(),
40                // bus is repr transparent and has the same layout as *mut FMOD_STUDIO_BUS, so this cast is ok
41                list.as_mut_ptr().cast::<*mut FMOD_STUDIO_BUS>(),
42                list.capacity() as c_int,
43                &raw mut count,
44            )
45            .to_result()?;
46
47            debug_assert_eq!(count, expected_count);
48
49            Ok(list)
50        }
51    }
52
53    /// Retrieves a list of the instances.
54    ///
55    /// Fills in the provided slice instead of allocating a [`Vec`], like [`Bank::get_bus_list`] does.
56    /// Any instances not filled in are left as [`None`].
57    ///
58    /// Returns how many buses were fetched.
59    pub fn get_bus_list_into(&self, slice: &mut [Option<Bus>]) -> Result<c_int> {
60        let mut count = 0;
61
62        unsafe {
63            FMOD_Studio_Bank_GetBusList(
64                self.inner.as_ptr(),
65                // Because we use NonNull, Option<Bus> has the same layout as *mut FMOD_STUDIO_BUS, so this is ok!
66                slice.as_mut_ptr().cast(),
67                slice.len() as c_int,
68                &raw mut count,
69            )
70            .to_result()?;
71
72            Ok(count)
73        }
74    }
75
76    /// Retrives the number of event descriptions in the bank.
77    ///
78    /// This function counts the events which were added to the bank by the sound designer.
79    /// 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.
80    pub fn event_count(&self) -> Result<c_int> {
81        let mut count = 0;
82        unsafe {
83            FMOD_Studio_Bank_GetEventCount(self.inner.as_ptr(), &raw mut count).to_result()?;
84        }
85        Ok(count)
86    }
87
88    /// Retrieves a list of the event descriptions in the bank.
89    ///
90    /// This function counts the events which were added to the bank by the sound designer.
91    /// 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.
92    pub fn get_event_list(&self) -> Result<Vec<EventDescription>> {
93        let expected_count = self.event_count()?;
94        let mut count = 0;
95        let mut list = vec![std::ptr::null_mut(); expected_count as usize];
96
97        unsafe {
98            FMOD_Studio_Bank_GetEventList(
99                self.inner.as_ptr(),
100                // bus is repr transparent and has the same layout as *mut FMOD_STUDIO_BUS, so this cast is ok
101                list.as_mut_ptr(),
102                list.capacity() as c_int,
103                &raw mut count,
104            )
105            .to_result()?;
106
107            debug_assert_eq!(count, expected_count);
108
109            Ok(std::mem::transmute::<
110                Vec<*mut fmod_sys::FMOD_STUDIO_EVENTDESCRIPTION>,
111                Vec<EventDescription>,
112            >(list))
113        }
114    }
115
116    /// Retrieves a list of the instances.
117    ///
118    /// Fills in the provided slice instead of allocating a [`Vec`], like [`Bank::get_event_list`] does.
119    /// Any instances not filled in are left as [`None`].
120    ///
121    /// Returns how many events were fetched.
122    pub fn get_event_list_into(&self, slice: &mut [Option<EventDescription>]) -> Result<c_int> {
123        let mut count = 0;
124
125        unsafe {
126            FMOD_Studio_Bank_GetEventList(
127                self.inner.as_ptr(),
128                // Because we use NonNull, Option<EventDescription> has the same layout as *mut FMOD_STUDIO_EVENTDESCRIPTION, so this is ok!
129                slice.as_mut_ptr().cast(),
130                slice.len() as c_int,
131                &raw mut count,
132            )
133            .to_result()?;
134
135            Ok(count)
136        }
137    }
138
139    /// Retrieves the number of string table entries in the bank.
140    pub fn string_count(&self) -> Result<c_int> {
141        let mut count = 0;
142        unsafe {
143            FMOD_Studio_Bank_GetStringCount(self.inner.as_ptr(), &raw mut count).to_result()?;
144        }
145        Ok(count)
146    }
147
148    /// Retrieves a string table entry.
149    ///
150    /// May be used in conjunction with [`Bank::string_count`] to enumerate the string table in a bank.
151    pub fn get_string_info(&self, index: c_int) -> Result<(Guid, Utf8CString)> {
152        let mut guid = MaybeUninit::zeroed();
153        let path = get_string_out_size(|path, size, ret| unsafe {
154            FMOD_Studio_Bank_GetStringInfo(
155                self.inner.as_ptr(),
156                index,
157                guid.as_mut_ptr(),
158                path,
159                size,
160                ret,
161            )
162        })?;
163        let guid = unsafe { guid.assume_init().into() };
164        Ok((guid, path))
165    }
166
167    /// Retrieves the number of VCAs in the bank.
168    pub fn vca_count(&self) -> Result<c_int> {
169        let mut count = 0;
170        unsafe {
171            FMOD_Studio_Bank_GetVCACount(self.inner.as_ptr(), &raw mut count).to_result()?;
172        }
173        Ok(count)
174    }
175
176    /// Retrieves a list of the VCAs in the bank.
177    pub fn get_vca_list(&self) -> Result<Vec<Vca>> {
178        let expected_count = self.event_count()?;
179        let mut count = 0;
180        let mut list = vec![
181            Vca {
182                inner: NonNull::dangling(), // same trick used here as getting the bus list
183            };
184            expected_count as usize
185        ];
186
187        unsafe {
188            FMOD_Studio_Bank_GetVCAList(
189                self.inner.as_ptr(),
190                // bus is repr transparent and has the same layout as *mut FMOD_STUDIO_BUS, so this cast is ok
191                list.as_mut_ptr().cast::<*mut FMOD_STUDIO_VCA>(),
192                list.capacity() as c_int,
193                &raw mut count,
194            )
195            .to_result()?;
196
197            debug_assert_eq!(count, expected_count);
198
199            Ok(list)
200        }
201    }
202
203    /// Retrieves a list of the instances.
204    ///
205    /// Fills in the provided slice instead of allocating a [`Vec`], like [`Bank::get_vca_list`] does.
206    /// Any instances not filled in are left as [`None`].
207    ///
208    /// Returns how many VCAs were fetched.
209    pub fn get_vca_list_into(&self, slice: &mut [Option<Vca>]) -> Result<c_int> {
210        let mut count = 0;
211
212        unsafe {
213            FMOD_Studio_Bank_GetVCAList(
214                self.inner.as_ptr(),
215                // Because we use NonNull, Option<Vca> has the same layout as *mut FMOD_STUDIO_VCA, so this is ok!
216                slice.as_mut_ptr().cast(),
217                slice.len() as c_int,
218                &raw mut count,
219            )
220            .to_result()?;
221
222            Ok(count)
223        }
224    }
225}