add finished hook/callback to lib

This commit is contained in:
Andelf
2014-04-14 18:41:52 +08:00
parent 31545e0e60
commit c3beb759d0
2 changed files with 69 additions and 4 deletions
+8
View File
@@ -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();
+61 -4
View File
@@ -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<raw::Closure> = 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<raw::Closure> = 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 }