fmod/studio/system/
callback.rs1use fmod_sys::*;
8use std::ffi::c_void;
9
10use crate::studio::{Bank, System, SystemCallbackMask};
11
12#[cfg(feature = "userdata-abstraction")]
13use crate::userdata::{get_userdata, insert_userdata, set_userdata, Userdata};
14
15#[cfg(feature = "userdata-abstraction")]
16#[allow(unused_variables)]
17pub trait SystemCallback {
18 fn preupdate(system: System, userdata: Option<Userdata>) -> Result<()> {
19 Ok(())
20 }
21
22 fn postupdate(system: System, userdata: Option<Userdata>) -> Result<()> {
23 Ok(())
24 }
25
26 fn bank_unload(system: System, bank: Bank, userdata: Option<Userdata>) -> Result<()> {
27 Ok(())
28 }
29
30 fn liveupdate_connected(system: System, userdata: Option<Userdata>) -> Result<()> {
31 Ok(())
32 }
33
34 fn liveupdate_disconnected(system: System, userdata: Option<Userdata>) -> Result<()> {
35 Ok(())
36 }
37}
38
39#[cfg(not(feature = "userdata-abstraction"))]
40#[allow(unused_variables)]
41pub trait SystemCallback {
42 fn preupdate(system: System, userdata: *mut c_void) -> Result<()> {
43 Ok(())
44 }
45
46 fn postupdate(system: System, userdata: *mut c_void) -> Result<()> {
47 Ok(())
48 }
49
50 fn bank_unload(system: System, bank: Bank, userdata: *mut c_void) -> Result<()> {
51 Ok(())
52 }
53
54 fn liveupdate_connected(system: System, userdata: *mut c_void) -> Result<()> {
55 Ok(())
56 }
57
58 fn liveupdate_disconnected(system: System, userdata: *mut c_void) -> Result<()> {
59 Ok(())
60 }
61}
62
63unsafe extern "C" fn callback_impl<C: SystemCallback>(
64 system: *mut FMOD_STUDIO_SYSTEM,
65 kind: FMOD_SYSTEM_CALLBACK_TYPE,
66 command_data: *mut c_void,
67 userdata: *mut c_void,
68) -> FMOD_RESULT {
69 let system = System::from(system);
71
72 #[cfg(feature = "userdata-abstraction")]
73 let userdata = get_userdata(userdata.into());
74
75 let result = match kind {
76 FMOD_STUDIO_SYSTEM_CALLBACK_PREUPDATE => C::preupdate(system, userdata),
77 FMOD_STUDIO_SYSTEM_CALLBACK_POSTUPDATE => C::postupdate(system, userdata),
78 FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD => {
79 let bank = Bank::from(command_data.cast());
80 C::bank_unload(system, bank, userdata)
81 }
82 FMOD_STUDIO_SYSTEM_CALLBACK_LIVEUPDATE_CONNECTED => {
83 C::liveupdate_connected(system, userdata)
84 }
85 FMOD_STUDIO_SYSTEM_CALLBACK_LIVEUPDATE_DISCONNECTED => {
86 C::liveupdate_disconnected(system, userdata)
87 }
88 _ => {
89 eprintln!("warning: unknown event callback type {kind}");
90 return FMOD_RESULT::FMOD_OK;
91 }
92 };
93 result.into()
94}
95
96#[cfg(feature = "userdata-abstraction")]
97impl System {
98 pub fn set_userdata(&self, userdata: Userdata) -> Result<()> {
99 let pointer = self.get_raw_userdata()?;
100 if pointer.is_null() {
101 let key = insert_userdata(userdata, *self);
102 self.set_raw_userdata(key.into())?;
103 } else {
104 set_userdata(pointer.into(), userdata);
105 }
106
107 Ok(())
108 }
109
110 pub fn get_userdata(&self) -> Result<Option<Userdata>> {
111 let pointer = self.get_raw_userdata()?;
112 Ok(get_userdata(pointer.into()))
113 }
114}
115
116impl System {
117 #[allow(clippy::not_unsafe_ptr_arg_deref)] pub fn set_raw_userdata(&self, userdata: *mut c_void) -> Result<()> {
119 unsafe { FMOD_Studio_System_SetUserData(self.inner, userdata).to_result() }
120 }
121
122 pub fn get_raw_userdata(&self) -> Result<*mut c_void> {
123 let mut userdata = std::ptr::null_mut();
124 unsafe {
125 FMOD_Studio_System_GetUserData(self.inner, &mut userdata).to_result()?;
126 }
127 Ok(userdata)
128 }
129
130 pub fn set_callback<C: SystemCallback>(&self, mask: SystemCallbackMask) -> Result<()> {
131 unsafe {
132 FMOD_Studio_System_SetCallback(self.inner, Some(callback_impl::<C>), mask.into())
133 .to_result()
134 }
135 }
136}