fmod/studio/system/
bank.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;
9use std::ffi::c_int;
10
11use crate::studio::{Bank, LoadBankFlags, System};
12use crate::Guid;
13
14impl System {
15    // TODO: load bank with callbacks
16    pub fn load_bank_custom(&self) -> Result<Bank> {
17        todo!()
18    }
19
20    /// Sample data must be loaded separately.
21    ///
22    /// By default this function will block until the file load finishes.
23    ///
24    /// Using the [`LoadBankFlags::NONBLOCKING`] flag will cause the bank to be loaded asynchronously.
25    /// In that case this function will always return [`Ok`] and bank will contain a valid bank handle.
26    /// Load errors for asynchronous banks can be detected by calling [`Bank::get_loading_state`].
27    /// Failed asynchronous banks should be released by calling [`Bank::unload`].
28    ///
29    /// If a bank has been split, separating out assets and optionally streams from the metadata bank, all parts must be loaded before any APIs that use the data are called.
30    /// It is recommended you load each part one after another (order is not important), then proceed with dependent API calls such as [`Bank::load_sample_data`] or [`System::get_event`].
31    pub fn load_bank_file(&self, filename: &Utf8CStr, load_flags: LoadBankFlags) -> Result<Bank> {
32        let mut bank = std::ptr::null_mut();
33        unsafe {
34            FMOD_Studio_System_LoadBankFile(
35                self.inner,
36                filename.as_ptr(),
37                load_flags.bits(),
38                &mut bank,
39            )
40            .to_result()?;
41            Ok(Bank::from(bank))
42        }
43    }
44
45    /// Sample data must be loaded separately.
46    ///
47    /// This function is the safe counterpart of [`System::load_bank_pointer`].
48    /// FMOD will allocate an internal buffer and copy the data from the passed in buffer before using it.
49    /// The buffer passed to this function may be cleaned up at any time after this function returns.
50    ///
51    /// By default this function will block until the load finishes.
52    ///
53    /// Using the [`LoadBankFlags::NONBLOCKING`] flag will cause the bank to be loaded asynchronously.
54    /// In that case this function will always return [`Ok`] and bank will contain a valid bank handle.
55    /// Load errors for asynchronous banks can be detected by calling [`Bank::get_loading_state`].
56    /// Failed asynchronous banks should be released by calling [`Bank::unload`].
57    ///
58    /// This function is not compatible with [`AdvancedSettings::encryption_key`], using them together will cause an error to be returned.
59    ///
60    /// If a bank has been split, separating out assets and optionally streams from the metadata bank, all parts must be loaded before any APIs that use the data are called.
61    /// It is recommended you load each part one after another (order is not important), then proceed with dependent API calls such as [`Bank::load_sample_data`] or [`System::get_event`].
62    pub fn load_bank_memory(&self, buffer: &[u8], flags: LoadBankFlags) -> Result<Bank> {
63        let mut bank = std::ptr::null_mut();
64        unsafe {
65            FMOD_Studio_System_LoadBankMemory(
66                self.inner,
67                buffer.as_ptr().cast::<i8>(),
68                buffer.len() as c_int,
69                FMOD_STUDIO_LOAD_MEMORY,
70                flags.bits(),
71                &mut bank,
72            )
73            .to_result()?;
74            Ok(Bank::from(bank))
75        }
76    }
77
78    /// Sample data must be loaded separately.
79    ///
80    /// This function is the unsafe counterpart of [`System::load_bank_memory`].
81    /// FMOD will use the passed memory buffer directly.
82    ///
83    /// By default this function will block until the load finishes.
84    ///
85    /// Using the [`LoadBankFlags::NONBLOCKING`] flag will cause the bank to be loaded asynchronously.
86    /// In that case this function will always return [`Ok`] and bank will contain a valid bank handle.
87    /// Load errors for asynchronous banks can be detected by calling [`Bank::get_loading_state`].
88    /// Failed asynchronous banks should be released by calling [`Bank::unload`].
89    ///
90    /// This function is not compatible with [`AdvancedSettings::encryption_key`], using them together will cause an error to be returned.
91    ///
92    /// If a bank has been split, separating out assets and optionally streams from the metadata bank, all parts must be loaded before any APIs that use the data are called.
93    /// It is recommended you load each part one after another (order is not important), then proceed with dependent API calls such as [`Bank::load_sample_data`] or [`System::get_event`].
94    ///
95    /// # Safety
96    /// When using this function the buffer must be aligned to [`FMOD_STUDIO_LOAD_MEMORY_ALIGNMENT`]
97    /// and the memory must persist until the bank has been fully unloaded, which can be some time after calling [`Bank::unload`] to unload the bank.
98    /// You can ensure the memory is not being freed prematurely by only freeing it after receiving the [`FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD`] callback.
99    pub unsafe fn load_bank_pointer(
100        &self,
101        buffer: *const [u8],
102        flags: LoadBankFlags,
103    ) -> Result<Bank> {
104        let mut bank = std::ptr::null_mut();
105        unsafe {
106            FMOD_Studio_System_LoadBankMemory(
107                self.inner,
108                buffer.cast::<i8>(),
109                (*buffer).len() as c_int,
110                FMOD_STUDIO_LOAD_MEMORY_POINT,
111                flags.bits(),
112                &mut bank,
113            )
114            .to_result()?;
115            Ok(Bank::from(bank))
116        }
117    }
118
119    /// Unloads all currently loaded banks.
120    pub fn unload_all_banks(&self) -> Result<()> {
121        unsafe { FMOD_Studio_System_UnloadAll(self.inner).to_result() }
122    }
123
124    /// Retrieves a loaded bank
125    ///
126    /// `path_or_id` may be a path, such as `bank:/Weapons` or an ID string such as `{793cddb6-7fa1-4e06-b805-4c74c0fd625b}`.
127    ///
128    /// Note that path lookups will only succeed if the strings bank has been loaded.
129    pub fn get_bank(&self, path_or_id: &Utf8CStr) -> Result<Bank> {
130        let mut bank = std::ptr::null_mut();
131        unsafe {
132            FMOD_Studio_System_GetBank(self.inner, path_or_id.as_ptr(), &mut bank).to_result()?;
133            Ok(Bank::from(bank))
134        }
135    }
136
137    /// Retrieves a loaded bank.
138    pub fn get_bank_by_id(&self, id: Guid) -> Result<Bank> {
139        let mut bank = std::ptr::null_mut();
140        unsafe {
141            FMOD_Studio_System_GetBankByID(self.inner, &id.into(), &mut bank).to_result()?;
142            Ok(Bank::from(bank))
143        }
144    }
145
146    /// Retrieves the number of loaded banks.
147    pub fn bank_count(&self) -> Result<c_int> {
148        let mut count = 0;
149        unsafe {
150            FMOD_Studio_System_GetBankCount(self.inner, &mut count).to_result()?;
151        }
152        Ok(count)
153    }
154
155    pub fn get_bank_list(&self) -> Result<Vec<Bank>> {
156        let expected_count = self.bank_count()?;
157        let mut count = 0;
158        let mut list = vec![std::ptr::null_mut(); expected_count as usize];
159
160        unsafe {
161            FMOD_Studio_System_GetBankList(
162                self.inner,
163                // bank is repr transparent and has the same layout as *mut FMOD_STUDIO_BANK, so this cast is ok
164                list.as_mut_ptr(),
165                list.capacity() as c_int,
166                &mut count,
167            )
168            .to_result()?;
169
170            debug_assert_eq!(count, expected_count);
171
172            Ok(std::mem::transmute::<
173                Vec<*mut fmod_sys::FMOD_STUDIO_BANK>,
174                Vec<Bank>,
175            >(list))
176        }
177    }
178}