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}