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, panic_wrapper};
15use crate::{FmodResultExt, Result};
16
17#[derive(Debug, Clone, Copy)]
19pub enum ChannelControlType {
20 Channel(Channel),
22 ChannelGroup(ChannelGroup),
24}
25
26#[allow(unused_variables)]
30pub trait ChannelControlCallback {
31 fn end(channel_control: ChannelControlType) -> Result<()> {
33 Ok(())
34 }
35
36 fn virtual_voice(channel_control: ChannelControlType, is_virtual: bool) -> Result<()> {
38 Ok(())
39 }
40
41 fn sync_point(channel_control: ChannelControlType, sync_point: c_int) -> Result<()> {
45 Ok(())
46 }
47
48 fn occlusion(
53 channel_control: ChannelControlType,
54 direct: &mut c_float,
55 reverb: &mut c_float,
56 ) -> Result<()> {
57 Ok(())
58 }
59}
60
61impl Deref for ChannelControlType {
62 type Target = ChannelControl;
63
64 fn deref(&self) -> &Self::Target {
65 match self {
66 ChannelControlType::Channel(channel) => channel,
67 ChannelControlType::ChannelGroup(channel_group) => channel_group,
68 }
69 }
70}
71
72unsafe extern "C" fn callback_impl<C: ChannelControlCallback>(
73 channel_control: *mut FMOD_CHANNELCONTROL,
74 control_type: FMOD_CHANNELCONTROL_TYPE,
75 callback_type: FMOD_CHANNELCONTROL_CALLBACK_TYPE,
76 commanddata1: *mut c_void,
77 commanddata2: *mut c_void,
78) -> FMOD_RESULT {
79 panic_wrapper(|| {
80 let channel_control = match control_type {
81 FMOD_CHANNELCONTROL_CHANNEL => {
82 let channel = unsafe { Channel::from_ffi(channel_control.cast()) };
83 ChannelControlType::Channel(channel)
84 }
85 FMOD_CHANNELCONTROL_CHANNELGROUP => {
86 let channel_group = unsafe { ChannelGroup::from_ffi(channel_control.cast()) };
87 ChannelControlType::ChannelGroup(channel_group)
88 }
89 _ => return FMOD_RESULT::FMOD_ERR_INVALID_PARAM, };
91
92 let result = match callback_type {
93 FMOD_CHANNELCONTROL_CALLBACK_END => C::end(channel_control),
94 FMOD_CHANNELCONTROL_CALLBACK_VIRTUALVOICE => {
95 let is_virtual = unsafe { *commanddata1.cast::<i32>() } != 0;
96 C::virtual_voice(channel_control, is_virtual)
97 }
98 FMOD_CHANNELCONTROL_CALLBACK_SYNCPOINT => {
99 let sync_point = unsafe { *commanddata1.cast::<c_int>() };
100 C::sync_point(channel_control, sync_point)
101 }
102 FMOD_CHANNELCONTROL_CALLBACK_OCCLUSION => {
103 let direct = unsafe { &mut *commanddata1.cast::<c_float>() };
104 let reverb = unsafe { &mut *commanddata2.cast::<c_float>() };
105 C::occlusion(channel_control, &mut *direct, &mut *reverb)
106 }
107 _ => {
108 eprintln!("warning: unknown callback type {callback_type}");
109 return FMOD_RESULT::FMOD_OK;
110 }
111 };
112 FMOD_RESULT::from_result(result)
113 })
114}
115
116impl ChannelControl {
117 pub fn set_callback<C: ChannelControlCallback>(&self) -> Result<()> {
119 unsafe {
120 FMOD_ChannelControl_SetCallback(self.inner.as_ptr(), Some(callback_impl::<C>))
121 .to_result()
122 }
123 }
124}