fmod/core/channel_control/
callback.rs1use fmod_sys::*;
8use std::{
9 ffi::{c_float, c_int},
10 ops::Deref,
11 os::raw::c_void,
12};
13
14use crate::{Channel, ChannelControl, ChannelGroup};
15
16pub enum ChannelControlType {
17 Channel(Channel),
18 ChannelGroup(ChannelGroup),
19}
20
21#[allow(unused_variables)]
22pub trait ChannelControlCallback {
23 fn end(channel_control: ChannelControlType) -> Result<()> {
24 Ok(())
25 }
26
27 fn virtual_voice(channel_control: ChannelControlType, is_virtual: bool) -> Result<()> {
28 Ok(())
29 }
30
31 fn sync_point(channel_control: ChannelControlType, sync_point: c_int) -> Result<()> {
32 Ok(())
33 }
34
35 fn occlusion(
37 channel_control: ChannelControlType,
38 direct: &mut c_float,
39 reverb: &mut c_float,
40 ) -> Result<()> {
41 Ok(())
42 }
43}
44
45impl Deref for ChannelControlType {
46 type Target = ChannelControl;
47
48 fn deref(&self) -> &Self::Target {
49 match self {
50 ChannelControlType::Channel(channel) => channel,
51 ChannelControlType::ChannelGroup(channel_group) => channel_group,
52 }
53 }
54}
55
56unsafe extern "C" fn callback_impl<C: ChannelControlCallback>(
57 channel_control: *mut FMOD_CHANNELCONTROL,
58 control_type: FMOD_CHANNELCONTROL_TYPE,
59 callback_type: FMOD_CHANNELCONTROL_CALLBACK_TYPE,
60 commanddata1: *mut c_void,
61 commanddata2: *mut c_void,
62) -> FMOD_RESULT {
63 let channel_control = match control_type {
64 FMOD_CHANNELCONTROL_CHANNEL => {
65 let channel = Channel::from(channel_control.cast::<FMOD_CHANNEL>());
66 ChannelControlType::Channel(channel)
67 }
68 FMOD_CHANNELCONTROL_CHANNELGROUP => {
69 let channel_group = ChannelGroup::from(channel_control.cast::<FMOD_CHANNELGROUP>());
70 ChannelControlType::ChannelGroup(channel_group)
71 }
72 _ => return FMOD_RESULT::FMOD_ERR_INVALID_PARAM, };
74
75 match callback_type {
76 FMOD_CHANNELCONTROL_CALLBACK_END => C::end(channel_control).into(),
77 FMOD_CHANNELCONTROL_CALLBACK_VIRTUALVOICE => {
78 let is_virtual = unsafe { *commanddata1.cast::<i32>() } != 0;
79 C::virtual_voice(channel_control, is_virtual).into()
80 }
81 FMOD_CHANNELCONTROL_CALLBACK_SYNCPOINT => {
82 let sync_point = unsafe { *commanddata1.cast::<c_int>() };
83 C::sync_point(channel_control, sync_point).into()
84 }
85 FMOD_CHANNELCONTROL_CALLBACK_OCCLUSION => {
86 let direct = unsafe { &mut *commanddata1.cast::<c_float>() };
87 let reverb = unsafe { &mut *commanddata2.cast::<c_float>() };
88 C::occlusion(channel_control, &mut *direct, &mut *reverb).into()
89 }
90 _ => {
91 eprintln!("warning: unknown callback type {callback_type}");
92 FMOD_RESULT::FMOD_OK
93 }
94 }
95}
96
97impl ChannelControl {
98 pub fn set_callback<C: ChannelControlCallback>(&self) -> Result<()> {
99 unsafe { FMOD_ChannelControl_SetCallback(self.inner, Some(callback_impl::<C>)).to_result() }
100 }
101}