Merge remote-tracking branch 'upstream/master' into fixed

Conflicts:
	examples/game_controller.rs
	examples/joystick.rs
	src/sdl2/sdl.rs
This commit is contained in:
Nicholas Mazzuca
2015-02-23 01:41:49 -08:00
11 changed files with 390 additions and 209 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ impl AudioCallback for MyCallback {
}
fn main() {
sdl2::init(sdl2::INIT_AUDIO);
let _sdl_context = sdl2::init(sdl2::INIT_AUDIO).unwrap();
let desired_spec = AudioSpecDesired {
freq: 44100,
+16 -15
View File
@@ -3,12 +3,10 @@ extern crate sdl2;
use sdl2::video::{Window, WindowPos, OPENGL};
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
use sdl2::pixels::Color;
use sdl2::event::poll_event;
use sdl2::event::Event::{Quit, KeyDown};
use sdl2::keycode::KeyCode;
pub fn main() {
sdl2::init(sdl2::INIT_VIDEO);
let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
let window = match Window::new("rust-sdl2 demo: Video", WindowPos::PosCentered, WindowPos::PosCentered, 800, 600, OPENGL) {
Ok(window) => window,
@@ -25,17 +23,20 @@ pub fn main() {
drawer.clear();
drawer.present();
loop {
match poll_event() {
Quit{..} => break,
KeyDown { keycode: key, .. } => {
if key == KeyCode::Escape {
break;
}
}
_ => {}
}
}
let mut running = true;
let mut event_pump = sdl_context.event_pump();
sdl2::quit();
while running {
for event in event_pump.poll_iter() {
use sdl2::event::Event;
match event {
Event::Quit {..} | Event::KeyDown { keycode: KeyCode::Escape, .. } => {
running = false
},
_ => {}
}
}
// The rest of the game loop goes here...
}
}
+9 -13
View File
@@ -1,16 +1,13 @@
#![feature(old_io, std_misc, core)]
#![feature(core)]
extern crate sdl2;
use sdl2::{joystick, controller};
use sdl2::event::Event;
use sdl2::controller::GameController;
use std::old_io::timer::sleep;
use std::time::duration::Duration;
use std::num::SignedInt;
fn main() {
sdl2::init(sdl2::INIT_GAME_CONTROLLER);
let sdl_context = sdl2::init(sdl2::INIT_GAME_CONTROLLER).unwrap();
let available =
match joystick::num_joysticks() {
@@ -44,7 +41,7 @@ fn main() {
}
}
let controller =
let controller =
match controller {
Some(c) => c,
None => panic!("Couldn't open any controller"),
@@ -52,8 +49,12 @@ fn main() {
println!("Controller mapping: {}", controller.mapping());
loop {
match sdl2::event::poll_event() {
let mut event_pump = sdl_context.event_pump();
for event in event_pump.wait_iter() {
use sdl2::event::Event;
match event {
Event::ControllerAxisMotion{ axis, value: val, .. } => {
// Axis motion is an absolute value in the range
// [-32768, 32767]. Let's simulate a very rough dead
@@ -67,12 +68,7 @@ fn main() {
Event::ControllerButtonUp{ button, .. } =>
println!("Button {:?} up", button),
Event::Quit{..} => break,
Event::None =>
// Don't hog the CPU while waiting for events
sleep(Duration::milliseconds(100)),
_ => (),
}
}
sdl2::quit();
}
+9 -13
View File
@@ -1,15 +1,12 @@
#![feature(old_io, std_misc, core)]
#![feature(core)]
extern crate sdl2;
use sdl2::joystick::{Joystick, num_joysticks};
use sdl2::event::Event;
use std::old_io::timer::sleep;
use std::time::duration::Duration;
use std::num::SignedInt;
fn main() {
sdl2::init(sdl2::INIT_JOYSTICK);
let sdl_context = sdl2::init(sdl2::INIT_JOYSTICK).unwrap();
let available =
match num_joysticks() {
@@ -34,12 +31,16 @@ fn main() {
}
}
if joystick.is_none() {
if joystick.is_none() {
panic!("Couldn't open any joystick");
};
loop {
match sdl2::event::poll_event() {
let mut event_pump = sdl_context.event_pump();
for event in event_pump.wait_iter() {
use sdl2::event::Event;
match event {
Event::JoyAxisMotion{ axis_idx, value: val, .. } => {
// Axis motion is an absolute value in the range
// [-32768, 32767]. Let's simulate a very rough dead
@@ -55,12 +56,7 @@ fn main() {
Event::JoyHatMotion{ hat_idx, state, .. } =>
println!("Hat {} moved to {:?}", hat_idx, state),
Event::Quit{..} => break,
Event::None =>
// Don't hog the CPU while waiting for events
sleep(Duration::milliseconds(100)),
_ => (),
}
}
sdl2::quit();
}
+16 -15
View File
@@ -4,12 +4,10 @@ use sdl2::video::{Window, WindowPos, OPENGL};
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::event::poll_event;
use sdl2::event::Event::{Quit, KeyDown};
use sdl2::keycode::KeyCode;
pub fn main() {
sdl2::init(sdl2::INIT_VIDEO);
let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
let window = match Window::new("rust-sdl2 demo: Renderer + Texture", WindowPos::PosCentered, WindowPos::PosCentered, 800, 600, OPENGL) {
Ok(window) => window,
@@ -40,17 +38,20 @@ pub fn main() {
drawer.copy_ex(&texture, None, Some(Rect::new(450, 100, 256, 256)), 30.0, None, (false, false));
drawer.present();
loop {
match poll_event() {
Quit{..} => break,
KeyDown { keycode: key, .. } => {
if key == KeyCode::Escape {
break;
}
}
_ => {}
}
}
let mut running = true;
let mut event_pump = sdl_context.event_pump();
sdl2::quit();
while running {
for event in event_pump.poll_iter() {
use sdl2::event::Event;
match event {
Event::Quit {..} | Event::KeyDown { keycode: KeyCode::Escape, .. } => {
running = false
},
_ => {}
}
}
// The rest of the game loop goes here...
}
}
+16 -15
View File
@@ -4,12 +4,10 @@ use sdl2::video::{Window, WindowPos, SHOWN};
use sdl2::render::{RenderDriverIndex, ACCELERATED, Renderer};
use sdl2::pixels::PixelFormatEnum;
use sdl2::rect::Rect;
use sdl2::event::poll_event;
use sdl2::event::Event::{Quit, KeyDown};
use sdl2::keycode::KeyCode;
pub fn main() {
sdl2::init(sdl2::INIT_VIDEO);
let sdl_context = sdl2::init(sdl2::INIT_VIDEO).unwrap();
let window = match Window::new("rust-sdl2 demo: YUV", WindowPos::PosCentered, WindowPos::PosCentered, 800, 600, SHOWN) {
Ok(window) => window,
@@ -56,17 +54,20 @@ pub fn main() {
drawer.copy(&texture, None, Some(Rect::new(100, 100, 256, 256)));
drawer.present();
loop {
match poll_event() {
Quit{..} => break,
KeyDown { keycode: key, .. } => {
if key == KeyCode::Escape {
break;
}
}
_ => {}
}
}
let mut running = true;
let mut event_pump = sdl_context.event_pump();
sdl2::quit();
while running {
for event in event_pump.poll_iter() {
use sdl2::event::Event;
match event {
Event::Quit {..} | Event::KeyDown { keycode: KeyCode::Escape, .. } => {
running = false
},
_ => {}
}
}
// The rest of the game loop goes here...
}
}
+3 -3
View File
@@ -444,9 +444,9 @@ pub type SDL_EventFilter =
extern "C" {
pub fn SDL_free(mem: *const c_void);
pub fn SDL_PumpEvents();
/*pub fn SDL_PeepEvents(events: &[SDL_Event], numevents: c_int,
action: SDL_eventaction, minType: uint32_t,
maxType: uint32_t) -> c_int;*/
pub fn SDL_PeepEvents(events: *mut SDL_Event, numevents: c_int,
action: SDL_eventaction,
minType: uint32_t, maxType: uint32_t) -> c_int;
pub fn SDL_HasEvent(_type: uint32_t) -> SDL_bool;
pub fn SDL_HasEvents(minType: uint32_t, maxType: uint32_t) ->
SDL_bool;
+209 -114
View File
@@ -8,6 +8,8 @@ use libc::{c_int, c_void, uint32_t};
use std::num::FromPrimitive;
use std::ptr;
use std::borrow::ToOwned;
use std::iter::FromIterator;
use std::marker::{NoCopy, PhantomData};
use controller;
use controller::{Axis, Button};
@@ -125,9 +127,6 @@ impl WindowEventId {
/// Different event types.
pub enum Event {
None,
Quit { timestamp: u32 },
AppTerminating { timestamp: u32 },
AppLowMemory { timestamp: u32 },
@@ -361,12 +360,16 @@ pub enum Event {
_type: u32,
code: i32
},
Unknown {
timestamp: u32,
type_: u32
}
}
impl ::std::fmt::Debug for Event {
fn fmt(&self, out: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
out.write_str(match *self {
Event::None => "Event::None",
Event::Quit{..} => "Event::Quit",
Event::AppTerminating{..} => "Event::AppTerminating",
Event::AppLowMemory{..} => "Event::AppLowMemory",
@@ -405,6 +408,7 @@ impl ::std::fmt::Debug for Event {
Event::ClipboardUpdate{..} => "Event::ClipboardUpdate",
Event::DropFile{..} => "Event::DropFile",
Event::User{..} => "Event::User",
Event::Unknown{..} => "Event::Unknown",
})
}
}
@@ -412,7 +416,7 @@ impl ::std::fmt::Debug for Event {
// TODO: Remove this when from_utf8 is updated in Rust
impl Event {
fn to_ll(self) -> Option<ll::SDL_Event> {
let ret = null_event();
let ret = unsafe { mem::uninitialized() };
match self {
// just ignore timestamp
Event::User { window_id, _type, code, .. } => {
@@ -439,7 +443,7 @@ impl Event {
fn from_ll(raw: &ll::SDL_Event) -> Event {
let raw_type = raw._type();
let raw_type = if raw_type.is_null() {
return Event::None;
panic!("Event payload is null")
} else {
unsafe { *raw_type }
};
@@ -809,142 +813,233 @@ impl Event {
}
}
EventType::First | EventType::Last => Event::None,
EventType::First => panic!("Unused event, EventType::First, was encountered"),
EventType::Last => panic!("Unusable event, EventType::Last, was encountered"),
// If we have no other match and the event type is >= 32768
// this is a user event
EventType::User => {
if raw_type < 32768 {
return Event::None;
}
// The type is unknown to us.
// It's a newer SDL2 type.
let ref event = *raw.common();
let ref event = *raw.user();
Event::Unknown {
timestamp: event.timestamp,
type_: event._type
}
} else {
let ref event = *raw.user();
Event::User {
timestamp: event.timestamp,
window_id: event.windowID,
_type: raw_type,
code: event.code
Event::User {
timestamp: event.timestamp,
window_id: event.windowID,
_type: raw_type,
code: event.code
}
}
}
}} // close unsafe & match
}
}
fn null_event() -> ll::SDL_Event {
ll::SDL_Event { data: [0; 56] }
/// A thread-safe type that encapsulates SDL event-pumping functions.
pub struct EventPump<'sdl> {
_marker: NoCopy,
_sdl: PhantomData<&'sdl ()>
}
/// Pump the event loop, gathering events from the input devices.
pub fn pump_events() {
unsafe { ll::SDL_PumpEvents(); }
}
/// Prevents the event pump from moving to other threads.
/// SDL events can only be pumped on the main thread.
impl<'sdl> !Send for EventPump<'sdl> {}
/// Check for the existence of certain event types in the event queue.
pub fn has_event(_type: EventType) -> bool {
unsafe { ll::SDL_HasEvent(_type as uint32_t ) == 1 }
}
impl<'sdl> EventPump<'sdl> {
/// Polls for currently pending events.
///
/// If no events are pending, `None` is returned.
pub fn poll_event(&mut self) -> Option<Event> {
let raw = unsafe { mem::uninitialized() };
let has_pending = unsafe { ll::SDL_PollEvent(&raw) == 1 as c_int };
/// Check for the existence of a range of event types in the event queue.
pub fn has_events(min: EventType, max: EventType) -> bool {
unsafe { ll::SDL_HasEvents(min as uint32_t, max as uint32_t) == 1 }
}
if has_pending { Some(Event::from_ll(&raw)) }
else { None }
}
/// Clear events from the event queue.
pub fn flush_event(_type: EventType) {
unsafe { ll::SDL_FlushEvent(_type as uint32_t) }
}
/// Returns a polling iterator that calls `poll_event()`.
/// The iterator will terminate once there are no more pending events.
///
/// # Example
/// ```no_run
/// let mut sdl_context = sdl2::init(sdl2::INIT_EVERYTHING).unwrap();
///
/// let mut event_pump = sdl_context.event_pump();
/// for event in event_pump.poll_iter() {
/// use sdl2::event::Event;
/// match event {
/// Event::KeyDown {..} => { /*...*/ },
/// _ => ()
/// }
/// }
/// ```
pub fn poll_iter(&mut self) -> EventPollIterator {
EventPollIterator {
event_pump: unsafe { EventPump::_unchecked_new() }
}
}
/// Clear events from the event queue of a range of event types.
pub fn flush_events(min: EventType, max: EventType) {
unsafe { ll::SDL_FlushEvents(min as uint32_t, max as uint32_t) }
}
/// Pumps the event loop, gathering events from the input devices.
pub fn pump_events(&mut self) {
unsafe { ll::SDL_PumpEvents(); };
}
/// Poll for currently pending events.
pub fn poll_event() -> Event {
pump_events();
/// Waits indefinitely for the next available event.
pub fn wait_event(&mut self) -> Event {
unsafe {
let raw = mem::uninitialized();
let success = ll::SDL_WaitEvent(&raw) == 1;
let raw = null_event();
let success = unsafe { ll::SDL_PollEvent(&raw) == 1 as c_int };
if success { Event::from_ll(&raw) }
else { panic!(get_error()) }
}
}
if success { Event::from_ll(&raw) }
else { Event::None }
}
/// Waits until the specified timeout (in milliseconds) for the next available event.
pub fn wait_event_timeout(&mut self, timeout: u32) -> Option<Event> {
unsafe {
let raw = mem::uninitialized();
let success = ll::SDL_WaitEventTimeout(&raw, timeout as c_int) == 1;
/// Wait indefinitely for the next available event.
pub fn wait_event() -> SdlResult<Event> {
let raw = null_event();
let success = unsafe { ll::SDL_WaitEvent(&raw) == 1 as c_int };
if success { Some(Event::from_ll(&raw)) }
else { None }
}
}
if success { Ok(Event::from_ll(&raw)) }
else { Err(get_error()) }
}
/// Returns a waiting iterator that calls `wait_event()`.
///
/// Note: The iterator will never terminate.
pub fn wait_iter(&mut self) -> EventWaitIterator {
EventWaitIterator {
event_pump: unsafe { EventPump::_unchecked_new() }
}
}
/// Wait until the specified timeout (in milliseconds) for the next available event.
pub fn wait_event_timeout(timeout: i32) -> SdlResult<Event> {
let raw = null_event();
let success = unsafe { ll::SDL_WaitEventTimeout(&raw, timeout as c_int) ==
1 as c_int };
/// Returns a waiting iterator that calls `wait_event_timeout()`.
///
/// Note: The iterator will never terminate, unless waiting for an event
/// exceeds the specified timeout.
pub fn wait_timeout_iter(&mut self, timeout: u32) -> EventWaitTimeoutIterator {
EventWaitTimeoutIterator {
event_pump: unsafe { EventPump::_unchecked_new() },
timeout: timeout
}
}
if success { Ok(Event::from_ll(&raw)) }
else { Err(get_error()) }
}
extern "C" fn event_filter_wrapper(userdata: *const c_void, event: *const ll::SDL_Event) -> c_int {
let filter: extern fn(event: Event) -> bool = unsafe { mem::transmute(userdata) };
if event.is_null() { 1 }
else { filter(Event::from_ll(unsafe { &*event })) as c_int }
}
/// Set up a filter to process all events before they change internal state and are posted to the internal event queue.
pub fn set_event_filter(filter_func: extern fn(event: Event) -> bool) {
unsafe { ll::SDL_SetEventFilter(event_filter_wrapper,
filter_func as *const _) }
}
/// Add a callback to be triggered when an event is added to the event queue.
pub fn add_event_watch(filter_func: extern fn(event: Event) -> bool) {
unsafe { ll::SDL_AddEventWatch(event_filter_wrapper,
filter_func as *const _) }
}
/// Remove an event watch callback added.
pub fn delete_event_watch(filter_func: extern fn(event: Event) -> bool) {
unsafe { ll::SDL_DelEventWatch(event_filter_wrapper,
filter_func as *const _) }
}
/// Run a specific filter function on the current event queue, removing any events for which the filter returns 0.
pub fn filter_events(filter_func: extern fn(event: Event) -> bool) {
unsafe { ll::SDL_FilterEvents(event_filter_wrapper,
filter_func as *const _) }
}
/// Set the state of processing events.
pub fn set_event_state(_type: EventType, state: bool) {
unsafe { ll::SDL_EventState(_type as uint32_t,
state as ll::SDL_EventState); }
}
/// Get the state of processing events.
pub fn get_event_state(_type: EventType) -> bool {
unsafe { ll::SDL_EventState(_type as uint32_t, ll::SDL_QUERY)
== ll::SDL_ENABLE }
}
/// allocate a set of user-defined events, and return the beginning event number for that set of events
pub fn register_events(num_events: i32) -> Option<u32> {
let ret = unsafe { ll::SDL_RegisterEvents(num_events as c_int) };
if ret == (-1 as uint32_t) {
None
} else {
Some(ret as u32)
/// Internal use only; used by `sdl2::Sdl::event_pump()`
#[doc(hidden)]
pub unsafe fn _unchecked_new<'a>() -> EventPump<'a> {
EventPump {
_marker: NoCopy,
_sdl: PhantomData
}
}
}
/// add an event to the event queue
/// An iterator that calls `EventPump::poll_event()`.
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct EventPollIterator<'a> {
event_pump: EventPump<'a>
}
impl<'a> Iterator for EventPollIterator<'a> {
pub type Item = Event;
fn next(&mut self) -> Option<Event> {
self.event_pump.poll_event()
}
}
/// An iterator that calls `EventPump::wait_event()`.
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct EventWaitIterator<'a> {
event_pump: EventPump<'a>
}
impl<'a> Iterator for EventWaitIterator<'a> {
pub type Item = Event;
fn next(&mut self) -> Option<Event> { Some(self.event_pump.wait_event()) }
}
/// An iterator that calls `EventPump::wait_event_timeout()`.
#[must_use = "iterators are lazy and do nothing unless consumed"]
pub struct EventWaitTimeoutIterator<'a> {
event_pump: EventPump<'a>,
timeout: u32
}
impl<'a> Iterator for EventWaitTimeoutIterator<'a> {
pub type Item = Event;
fn next(&mut self) -> Option<Event> { self.event_pump.wait_event_timeout(self.timeout) }
}
/// Removes all events in the event queue that match the specified event type.
pub fn flush_event(event_type: EventType) {
unsafe { ll::SDL_FlushEvent(event_type as uint32_t) };
}
/// Removes all events in the event queue that match the specified type range.
pub fn flush_events(min_type: u32, max_type: u32) {
unsafe { ll::SDL_FlushEvents(min_type, max_type) };
}
/// Reads the events at the front of the event queue, until the maximum amount
/// of events is read.
///
/// The events will _not_ be removed from the queue.
///
/// # Example
/// ```no_run
/// use sdl2::event::{Event, peek_events};
///
/// // Read up to 1024 events
/// let events: Vec<Event> = peek_events(1024);
///
/// // Print each one
/// for event in events {
/// println!("{:?}", event);
/// }
/// ```
pub fn peek_events<B>(max_amount: u32) -> B
where B: FromIterator<Event>
{
unsafe {
let mut events = Vec::with_capacity(max_amount as usize);
let result = {
let events_ptr = events.as_mut_slice().as_mut_ptr();
ll::SDL_PeepEvents(
events_ptr,
max_amount as c_int,
ll::SDL_PEEKEVENT,
ll::SDL_FIRSTEVENT,
ll::SDL_LASTEVENT
)
};
if result < 0 {
// The only error possible is "Couldn't lock event queue"
panic!(get_error());
} else {
events.set_len(max_amount as usize);
events.iter().map(|event_raw| {
Event::from_ll(event_raw)
}).collect()
}
}
}
/// Pushes an event to the event queue.
pub fn push_event(event: Event) -> SdlResult<()> {
match event.to_ll() {
Some(raw_event) => {
@@ -953,7 +1048,7 @@ pub fn push_event(event: Event) -> SdlResult<()> {
else { Err(get_error()) }
},
None => {
Err("Unsupport event type to push back to queue.".to_owned())
Err(format!("Cannot push unsupported event type to the queue"))
}
}
}
+108 -13
View File
@@ -1,6 +1,8 @@
use std::ffi::{CStr, CString};
use std::marker::{NoCopy, PhantomData};
use sys::sdl as ll;
use event::EventPump;
bitflags! {
flags InitFlag: u32 {
@@ -27,30 +29,123 @@ pub enum Error {
pub type SdlResult<T> = Result<T, String>;
pub fn init(flags: InitFlag) -> bool {
unsafe {
ll::SDL_Init(flags.bits()) == 0
use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
/// Only one Sdl context can be alive at a time.
/// Set to false by default (not alive).
static IS_SDL_CONTEXT_ALIVE: AtomicBool = ATOMIC_BOOL_INIT;
/// The SDL context type. Initialize with `sdl2::init()`.
///
/// From a thread-safety perspective, `Sdl` represents the main thread.
/// Only one instance of `Sdl` is allowed per process, and cannot be moved or
/// used across non-main threads.
///
/// As such, `Sdl` is a useful type for ensuring that SDL types that can only
/// be used on the main thread are initialized that way.
///
/// For instance, `SDL_PumpEvents()` is not thread safe, and may only be
/// called on the main thread.
/// All functionality that calls `SDL_PumpEvents()` is thus put into an
/// `EventPump` type, which can only be obtained through `Sdl`.
/// This guarantees that the only way to call event-pumping functions is on
/// the main thread.
pub struct Sdl {
_marker: NoCopy
}
impl !Send for Sdl {}
impl !Sync for Sdl {}
impl Sdl {
/// Initializes specific SDL subsystems.
pub fn init_subsystem(&self, flags: InitFlag) -> SdlResult<Subsystem> {
unsafe {
if ll::SDL_InitSubSystem(flags.bits()) == 0 {
Ok(Subsystem {
flags: flags,
_marker: PhantomData
})
} else {
Err(get_error())
}
}
}
/// Returns the mask of the specified subsystems which have previously been initialized.
pub fn was_init(&self, flags: InitFlag) -> InitFlag {
unsafe {
let raw = ll::SDL_WasInit(flags.bits());
flags & InitFlag::from_bits(raw).unwrap()
}
}
/// Obtains the SDL event pump.
pub fn event_pump(&self) -> EventPump {
unsafe { EventPump::_unchecked_new() }
}
}
pub fn init_subsystem(flags: InitFlag) -> bool {
unsafe {
ll::SDL_InitSubSystem(flags.bits()) == 0
impl Drop for Sdl {
fn drop(&mut self) {
use std::sync::atomic::Ordering;
let was_alive = IS_SDL_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
assert!(was_alive);
unsafe { ll::SDL_Quit(); }
}
}
pub fn quit_subsystem(flags: InitFlag) {
unsafe { ll::SDL_QuitSubSystem(flags.bits()); }
/// A RAII value representing initalized SDL subsystems. See `sdl2::Sdl::init_subsystem()`.
///
/// Subsystem initialization is ref-counted. Once `Subsystem::drop()` is called,
/// the specified subsystems' ref-counts are decremented via `SDL_QuitSubSystem`.
pub struct Subsystem<'sdl> {
flags: InitFlag,
_marker: PhantomData<&'sdl Sdl>
}
pub fn quit() {
unsafe { ll::SDL_Quit(); }
#[unsafe_destructor]
impl<'sdl> Drop for Subsystem<'sdl> {
fn drop(&mut self) {
unsafe { ll::SDL_QuitSubSystem(self.flags.bits()); }
}
}
pub fn was_inited(flags: InitFlag) -> InitFlag {
/// Initializes the SDL library.
/// This must be called before using any other SDL function.
///
/// # Example
/// ```no_run
/// let sdl_context = sdl2::init(sdl2::INIT_EVERYTHING).unwrap();
///
/// let mut event_pump = sdl_context.event_pump();
/// for event in event_pump.poll_iter() {
/// // ...
/// }
///
/// // SDL_Quit() is called here as `sdl_context` is dropped.
/// ```
pub fn init(flags: InitFlag) -> SdlResult<Sdl> {
unsafe {
let raw = ll::SDL_WasInit(flags.bits());
flags & InitFlag::from_bits(raw).unwrap()
use std::sync::atomic::Ordering;
// Atomically switch the `IS_SDL_CONTEXT_ALIVE` global to true
let was_alive = IS_SDL_CONTEXT_ALIVE.swap(true, Ordering::Relaxed);
if was_alive {
IS_SDL_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
Err(format!("Cannot have more than one `Sdl` in use at the same time"))
} else {
if ll::SDL_Init(flags.bits()) == 0 {
Ok(Sdl {
_marker: NoCopy
})
} else {
IS_SDL_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
Err(get_error())
}
}
}
}
+3 -3
View File
@@ -79,7 +79,7 @@ extern "C" fn c_timer_callback(_interval: u32, param: *const c_void) -> uint32_t
fn test_timer_runs_multiple_times() {
use std::sync::{Arc, Mutex};
let _running = TIMER_INIT_LOCK.lock().unwrap();
::sdl::init(::sdl::INIT_TIMER);
::sdl::init(::sdl::INIT_TIMER).unwrap();
let local_num = Arc::new(Mutex::new(0));
let timer_num = local_num.clone();
@@ -104,7 +104,7 @@ fn test_timer_runs_multiple_times() {
fn test_timer_runs_at_least_once() {
use std::sync::{Arc, Mutex};
let _running = TIMER_INIT_LOCK.lock().unwrap();
::sdl::init(::sdl::INIT_TIMER);
::sdl::init(::sdl::INIT_TIMER).unwrap();
let local_flag = Arc::new(Mutex::new(false));
let timer_flag = local_flag.clone();
@@ -123,7 +123,7 @@ fn test_timer_runs_at_least_once() {
fn test_timer_can_be_recreated() {
use std::sync::{Arc, Mutex};
let _running = TIMER_INIT_LOCK.lock().unwrap();
::sdl::init(::sdl::INIT_TIMER);
::sdl::init(::sdl::INIT_TIMER).unwrap();
let local_num = Arc::new(Mutex::new(0));
let timer_num = local_num.clone();
-4
View File
@@ -4,8 +4,6 @@ extern crate sdl2;
#[test]
fn audio_spec_wav() {
sdl2::init(sdl2::INIT_AUDIO);
let wav = sdl2::audio::AudioSpecWAV::load_wav(&Path::new("./tests/sine.wav")).unwrap();
assert_eq!(wav.freq, 22050);
@@ -14,6 +12,4 @@ fn audio_spec_wav() {
let buffer = wav.get_buffer();
assert_eq!(buffer.len(), 4410);
sdl2::quit();
}