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}