diff --git a/src/demo/demo.rs b/src/demo/demo.rs index 46aebb15..3c226b51 100644 --- a/src/demo/demo.rs +++ b/src/demo/demo.rs @@ -5,7 +5,6 @@ extern crate sdl2; extern crate sdl2_mixer; use std::os; -use std::default::Default; use mix = sdl2_mixer; @@ -22,9 +21,10 @@ fn main() { fn dump_info(filename: &Path) -> Result<(), ~str> { println!("linked version: {}", mix::get_linked_version()); - sdl2::init([sdl2::InitAudio, sdl2::InitTimer]); - println!("inited => {}", mix::init(Default::default())); - + sdl2::init(sdl2::InitAudio | sdl2::InitTimer); + println!("inited => {}", mix::init(sdl2_mixer::InitMp3 | sdl2_mixer::InitFlac | + sdl2_mixer::InitMod | sdl2_mixer::InitFluidSynth | + sdl2_mixer::InitModPlug | sdl2_mixer::InitOgg).get()); // TODO: 0x8010 is SDL_audio flag try!(mix::open_audio(mix::DEFAULT_FREQUENCY, 0x8010u16, 2, 1024)); mix::allocate_channels(0); diff --git a/src/sdl2_mixer/flag.rs b/src/sdl2_mixer/flag.rs new file mode 100644 index 00000000..4b573574 --- /dev/null +++ b/src/sdl2_mixer/flag.rs @@ -0,0 +1,109 @@ +// Loosely based on zlib-licensed code from RustAllegro +// https://github.com/SiegeLord/RustAllegro +// +// Implements efficient, type-safe flags with support for bitwise operators. +// +// Usage: +// +// flag_type!(FlagTypeName { +// FlagName1 = FlagValue1, +// FlagName2 = FlagValue2, +// ... +// FlagNameN = FlagValueN +// }) +// +// fn foo(flag: FlagTypeName) { +// let raw = (flag | FlagNameN).get(); +// bar(raw); +// } + +#![macro_escape] + +macro_rules! flag_type( + ($typename:ident : $supertype:ident { $($name:ident = $value:expr),* }) => { + pub struct $typename { + bits: $supertype + } + + impl $typename { + #[inline] + pub fn new(bits: $supertype) -> $typename { + $typename { bits: bits } + } + + #[inline] + pub fn get(self) -> $supertype { + self.bits + } + } + + impl ::std::default::Default for $typename { + fn default() -> $typename { + $typename::new(0) + } + } + + impl ::std::cmp::Eq for $typename { + fn eq(&self, other: &$typename) -> bool { + self.bits == other.bits + } + } + + impl ::std::cmp::TotalEq for $typename {} + + impl ::std::cmp::Ord for $typename { + fn lt(&self, other: &$typename) -> bool { + self.bits < other.bits + } + } + + impl ::std::cmp::TotalOrd for $typename { + fn cmp(&self, other: &$typename) -> Ordering { + self.bits.cmp(&other.bits) + } + } + + impl ::std::ops::Not<$typename> for $typename { + fn not(&self) -> $typename { + $typename { bits: !self.bits } + } + } + + impl ::std::ops::BitAnd<$typename, $typename> for $typename { + fn bitand(&self, rhs: &$typename) -> $typename { + $typename { bits: self.bits & rhs.bits } + } + } + + impl ::std::ops::BitOr<$typename, $typename> for $typename { + fn bitor(&self, rhs: &$typename) -> $typename { + $typename { bits: self.bits | rhs.bits } + } + } + + impl ::std::ops::BitXor<$typename, $typename> for $typename { + fn bitxor(&self, rhs: &$typename) -> $typename { + $typename { bits: self.bits ^ rhs.bits } + } + } + + impl ::std::ops::Shl<$supertype, $typename> for $typename { + fn shl(&self, rhs: &$supertype) -> $typename { + $typename { bits: self.bits << *rhs } + } + } + + impl ::std::ops::Shr<$supertype, $typename> for $typename { + fn shr(&self, rhs: &$supertype) -> $typename { + $typename { bits: self.bits >> *rhs } + } + } + + $( + pub static $name: $typename = $typename { bits: $value as $supertype }; + )+ + }; + ($typename:ident { $($name:ident = $value:expr),* }) => { + flag_type!($typename : u32 { $($name = $value),* }) + } +) diff --git a/src/sdl2_mixer/lib.rs b/src/sdl2_mixer/lib.rs index 597254ca..a30872ae 100644 --- a/src/sdl2_mixer/lib.rs +++ b/src/sdl2_mixer/lib.rs @@ -8,7 +8,7 @@ A binding for SDL2_mixer. #![comment = "SDL2_mixer bindings and wrappers"] #![license = "MIT"] -#![feature(globs)] +#![feature(globs, macro_rules)] extern crate libc; extern crate sdl2; @@ -18,8 +18,6 @@ use std::ptr; use std::cast; use std::raw; use std::c_str::CString; -use std::ops; -use std::num; use libc::{c_int, uint16_t, c_double}; use sdl2::get_error; use sdl2::rwops::RWops; @@ -47,6 +45,7 @@ mod others { #[allow(non_camel_case_types, dead_code)] mod ffi; +mod flag; // This comes from SDL_audio.h #[allow(non_camel_case_types)] @@ -111,89 +110,20 @@ pub fn get_linked_version() -> Version { } } -#[allow(visible_private_types)] -#[deriving(Clone, Eq, Hash, Show)] -pub enum InitFlag { - InitFlac, - InitMod, - InitModPlug, - InitMp3, - InitOgg, - InitFluidSynth, - InitRaw(ffi::MIX_InitFlags), -} - -impl InitFlag { - #[inline] - fn to_ll(self) -> ffi::MIX_InitFlags { - match self { - InitFlac => ffi::MIX_INIT_FLAC, - InitMod => ffi::MIX_INIT_MOD, - InitModPlug => ffi::MIX_INIT_MODPLUG, - InitMp3 => ffi::MIX_INIT_MP3, - InitOgg => ffi::MIX_INIT_OGG, - InitFluidSynth => ffi::MIX_INIT_FLUIDSYNTH, - InitRaw(val) => val, - } - } - - fn from_ll(cflag: ffi::MIX_InitFlags) -> InitFlag { - match cflag { - ffi::MIX_INIT_FLAC => InitFlac, - ffi::MIX_INIT_MOD => InitMod, - ffi::MIX_INIT_MODPLUG => InitModPlug, - ffi::MIX_INIT_MP3 => InitMp3, - ffi::MIX_INIT_OGG => InitOgg, - ffi::MIX_INIT_FLUIDSYNTH => InitFluidSynth, - val => InitRaw(val), - } - } - - pub fn mask(self, flag: InitFlag) -> bool { - self.to_ll() & flag.to_ll() == flag.to_ll() - } -} - -impl ops::BitOr for InitFlag { - fn bitor(&self, rhs: &InitFlag) -> InitFlag { - InitFlag::from_ll(self.to_ll() | rhs.to_ll()) - } -} - -impl default::Default for InitFlag { - fn default() -> InitFlag { - InitFlag::from_ll((ffi::MIX_INIT_FLAC | ffi::MIX_INIT_MOD | ffi::MIX_INIT_MODPLUG | - ffi::MIX_INIT_MP3 | ffi::MIX_INIT_OGG | ffi::MIX_INIT_FLUIDSYNTH)) - } -} - -impl num::FromPrimitive for InitFlag { - #[inline] - fn from_i64(n: i64) -> Option { - Some(InitFlag::from_ll(n as ffi::MIX_InitFlags)) - } - #[inline] - fn from_u64(n: u64) -> Option { - Some(InitFlag::from_ll(n as ffi::MIX_InitFlags)) - } -} - -impl num::ToPrimitive for InitFlag { - #[inline] - fn to_i64(&self) -> Option { - Some(self.to_ll() as i64) - } - #[inline] - fn to_u64(&self) -> Option { - Some(self.to_ll() as u64) - } -} +flag_type!(InitFlag : c_int { + InitFlac = ffi::MIX_INIT_FLAC, + InitMod = ffi::MIX_INIT_MOD, + InitModPlug = ffi::MIX_INIT_MODPLUG, + InitMp3 = ffi::MIX_INIT_MP3, + InitOgg = ffi::MIX_INIT_OGG, + InitFluidSynth = ffi::MIX_INIT_FLUIDSYNTH +}) /// Loads dynamic libraries and prepares them for use. Flags should be /// one or more flags from InitFlag. pub fn init(flags: InitFlag) -> InitFlag { - let ret = unsafe { ffi::Mix_Init(flags.to_ll() as c_int) }; - InitFlag::from_ll(ret as ffi::MIX_InitFlags) + let ret = unsafe { ffi::Mix_Init(flags.get()) }; + InitFlag::new(ret) } /// Cleans up all dynamically loaded library handles, freeing memory.