diff --git a/src/demo/demo.rs b/src/demo/demo.rs index a8a64d6a..5dbf93a8 100644 --- a/src/demo/demo.rs +++ b/src/demo/demo.rs @@ -47,6 +47,9 @@ fn dump_info(filename: &Path) -> Result<(), ~str> { println!("query spec => {}", mix::query_spec()); let music = mix::Music::from_file(filename).unwrap(); + + mix::Music::hook_finished(|| { println!("play ends! from rust cb") }); + println!("music => {:?}", music); println!("music type => {}", music.get_type()); @@ -64,6 +67,11 @@ fn dump_info(filename: &Path) -> Result<(), ~str> { sdl2::timer::delay(5000); + mix::Music::halt(); + + sdl2::timer::delay(1000); + // here will print hook_finished + mix::quit(); sdl2::quit(); diff --git a/src/sdl2_mixer/lib.rs b/src/sdl2_mixer/lib.rs index 5a98d056..39f2ed33 100644 --- a/src/sdl2_mixer/lib.rs +++ b/src/sdl2_mixer/lib.rs @@ -18,6 +18,8 @@ use std::fmt; use std::c_str::CString; use std::default; use std::ptr; +use std::cast; +use std::raw; use sdl2::get_error; use sdl2::rwops::RWops; @@ -282,6 +284,7 @@ pub enum Fading { } /// Sound effect channel. +#[deriving(Eq, Show)] pub struct Channel(int); pub fn allocate_channels(numchans: int) -> int { @@ -291,6 +294,35 @@ pub fn allocate_channels(numchans: int) -> int { } } +static mut channel_finished_callback: Option = None; + +extern "C" fn c_channel_finished_callback(ch: c_int) { + unsafe { + match channel_finished_callback { + None => (), + Some(cb) => { + let cb = cast::transmute::<_, |Channel|>(cb); + cb(Channel(ch as int)) + } + } + } +} + +pub fn set_channel_finished(f: |Channel|:'static) { + //! When channel playback is halted, then the specified channel_finished function is called. + unsafe { + channel_finished_callback = Some(cast::transmute::<_, raw::Closure>(f)); + ffi::Mix_ChannelFinished(Some(c_channel_finished_callback)); + } +} + +pub fn unset_channel_finished() { + unsafe { + ffi::Mix_ChannelFinished(None); + channel_finished_callback = None; + } +} + impl Channel { pub fn all() -> Channel { //! Represent for all channels (-1) @@ -382,8 +414,6 @@ impl Channel { unsafe { ffi::Mix_FadeOutChannel(ch as c_int, ms as c_int) as int } } - // TODO: Mix_ChannelFinished - pub fn is_playing(self) -> bool { //! if channel is playing, or not. let Channel(ch) = self; @@ -592,11 +622,24 @@ pub enum MusicType { MusicModPlug = ffi::MUS_MODPLUG as int } +// hooks +static mut music_finished_hook: Option = None; + +extern "C" fn c_music_finished_hook() { + unsafe { match music_finished_hook { + None => (), + Some(f) => { + let f = cast::transmute::<_, ||>(f); + f() + } + } } +} + /// This is an opaque data type used for Music data. #[deriving(Eq)] #[allow(raw_pointer_deriving, visible_private_types)] pub struct Music { pub raw: *ffi::Mix_Music, - pub owned: bool + pub owned: bool, } impl Drop for Music { @@ -730,9 +773,23 @@ impl Music { } // TODO: Mix_HookMusic - // TODO: Mix_HookMusicFinished // TODO: Mix_GetMusicHookData + pub fn hook_finished(f: ||) { + unsafe { + music_finished_hook = Some(cast::transmute(f)); + ffi::Mix_HookMusicFinished(Some(c_music_finished_hook)); + } + } + + pub fn unhook_finished() { + unsafe { + ffi::Mix_HookMusicFinished(None); + // unset from c, then rust, to avoid race condiction + music_finished_hook = None; + } + } + pub fn is_playing() -> bool { //! If music is actively playing, or not. unsafe { ffi::Mix_PlayingMusic() == 1 }