1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
// Copyright (c) 2024 Lily Lyons
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
use fmod_sys::*;
use std::ffi::c_void;
use crate::{Sound, System};
impl Sound {
/// Frees a sound object.
///
/// This will stop any instances of this sound, and free the sound object and its children if it is a multi-sound object.
/// If the sound was opened with FMOD_NONBLOCKING and hasn't finished opening yet, it will block.
/// Additionally, if the sound is still playing or has recently been stopped, the release may stall, as the mixer may still be using the sound.
/// Using Sound::getOpenState and checking the open state for FMOD_OPENSTATE_READY and FMOD_OPENSTATE_ERROR is a good way to avoid stalls.
pub fn release(&self) -> Result<()> {
// release userdata
#[cfg(feature = "userdata-abstraction")]
let userdata = self.get_raw_userdata()?;
unsafe {
FMOD_Sound_Release(self.inner).to_result()?;
}
// release/remove userdata if it is not null
#[cfg(feature = "userdata-abstraction")]
if !userdata.is_null() {
crate::userdata::remove_userdata(userdata.into());
self.set_raw_userdata(std::ptr::null_mut())?;
}
Ok(())
}
#[allow(clippy::not_unsafe_ptr_arg_deref)] // fmod doesn't dereference the passed in pointer, and the user dereferencing it is unsafe anyway
pub fn set_raw_userdata(&self, userdata: *mut c_void) -> Result<()> {
unsafe { FMOD_Sound_SetUserData(self.inner, userdata).to_result() }
}
pub fn get_raw_userdata(&self) -> Result<*mut c_void> {
let mut userdata = std::ptr::null_mut();
unsafe {
FMOD_Sound_GetUserData(self.inner, &mut userdata).to_result()?;
}
Ok(userdata)
}
/// Retrieves the parent System object.
pub fn get_system(&self) -> Result<System> {
let mut system = std::ptr::null_mut();
unsafe {
FMOD_Sound_GetSystemObject(self.inner, &mut system).to_result()?;
}
Ok(system.into())
}
}
#[cfg(feature = "userdata-abstraction")]
impl Sound {
pub fn set_userdata(&self, userdata: crate::userdata::Userdata) -> Result<()> {
use crate::userdata::{insert_userdata, set_userdata};
let pointer = self.get_raw_userdata()?;
if pointer.is_null() {
let key = insert_userdata(userdata, *self);
self.set_raw_userdata(key.into())?;
} else {
set_userdata(pointer.into(), userdata);
}
Ok(())
}
pub fn get_userdata(&self) -> Result<Option<crate::userdata::Userdata>> {
use crate::userdata::get_userdata;
let pointer = self.get_raw_userdata()?;
Ok(get_userdata(pointer.into()))
}
}