fmod/studio/bank/
general.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::Utf8CString;
9use std::ffi::c_void;
10use std::mem::MaybeUninit;
11
12use crate::studio::Bank;
13use crate::Guid;
14
15impl Bank {
16    /// Retrieves the GUID.
17    pub fn get_id(&self) -> Result<Guid> {
18        let mut guid = MaybeUninit::zeroed();
19        unsafe {
20            FMOD_Studio_Bank_GetID(self.inner, guid.as_mut_ptr()).to_result()?;
21
22            let guid = guid.assume_init().into();
23
24            Ok(guid)
25        }
26    }
27
28    /// Retrieves the path.
29    pub fn get_path(&self) -> Result<Utf8CString> {
30        let mut string_len = 0;
31
32        // retrieve the length of the string.
33        // this includes the null terminator, so we don't need to account for that.
34        unsafe {
35            let error =
36                FMOD_Studio_Bank_GetPath(self.inner, std::ptr::null_mut(), 0, &mut string_len)
37                    .to_error();
38
39            // we expect the error to be fmod_err_truncated.
40            // if it isn't, we return the error.
41            match error {
42                Some(error) if error != FMOD_RESULT::FMOD_ERR_TRUNCATED => return Err(error),
43                _ => {}
44            }
45        };
46
47        let mut path = vec![0u8; string_len as usize];
48        let mut expected_string_len = 0;
49
50        unsafe {
51            FMOD_Studio_Bank_GetPath(
52                self.inner,
53                // u8 and i8 have the same layout, so this is ok
54                path.as_mut_ptr().cast(),
55                string_len,
56                &mut expected_string_len,
57            )
58            .to_result()?;
59
60            debug_assert_eq!(string_len, expected_string_len);
61
62            // all public fmod apis return UTF-8 strings. this should be safe.
63            // if i turn out to be wrong, perhaps we should add extra error types?
64            let path = Utf8CString::from_utf8_with_nul_unchecked(path);
65
66            Ok(path)
67        }
68    }
69
70    /// Checks that the Bank reference is valid.
71    pub fn is_valid(&self) -> bool {
72        unsafe { FMOD_Studio_Bank_IsValid(self.inner).into() }
73    }
74
75    #[allow(clippy::not_unsafe_ptr_arg_deref)] // fmod doesn't dereference the passed in pointer, and the user dereferencing it is unsafe anyway
76    pub fn set_raw_userdata(&self, userdata: *mut c_void) -> Result<()> {
77        unsafe { FMOD_Studio_Bank_SetUserData(self.inner, userdata).to_result() }
78    }
79
80    pub fn get_raw_userdata(&self) -> Result<*mut c_void> {
81        let mut userdata = std::ptr::null_mut();
82        unsafe {
83            FMOD_Studio_Bank_GetUserData(self.inner, &mut userdata).to_result()?;
84        }
85        Ok(userdata)
86    }
87}
88
89#[cfg(feature = "userdata-abstraction")]
90impl Bank {
91    pub fn set_userdata(&self, userdata: crate::userdata::Userdata) -> Result<()> {
92        use crate::userdata::{insert_userdata, set_userdata};
93
94        let pointer = self.get_raw_userdata()?;
95        if pointer.is_null() {
96            let key = insert_userdata(userdata, *self);
97            self.set_raw_userdata(key.into())?;
98        } else {
99            set_userdata(pointer.into(), userdata);
100        }
101
102        Ok(())
103    }
104
105    pub fn get_userdata(&self) -> Result<Option<crate::userdata::Userdata>> {
106        use crate::userdata::get_userdata;
107
108        let pointer = self.get_raw_userdata()?;
109        Ok(get_userdata(pointer.into()))
110    }
111}