sdl/
sdl.rs

1use std::ffi::{CStr, CString};
2use std::str;
3
4// Setup linking for all targets.
5#[cfg(target_os = "macos")]
6mod mac {
7    #[cfg(mac_framework)]
8    #[link(name = "SDL", kind = "framework")]
9    extern "C" {}
10
11    #[cfg(not(mac_framework))]
12    #[link(name = "SDL")]
13    extern "C" {}
14}
15
16#[cfg(not(target_os = "macos"))]
17mod others {
18    #[link(name = "SDL")]
19    extern "C" {}
20}
21
22pub mod ll {
23    #![allow(non_camel_case_types)]
24
25    use std::ffi::c_char;
26
27    use libc::{c_int, c_uint, uint32_t};
28
29    pub type SDL_errorcode = c_uint;
30    pub const SDL_ENOMEM: SDL_errorcode = 0;
31    pub const SDL_EFREAD: SDL_errorcode = 1;
32    pub const SDL_EFWRITE: SDL_errorcode = 2;
33    pub const SDL_EFSEEK: SDL_errorcode = 3;
34    pub const SDL_UNSUPPORTED: SDL_errorcode = 4;
35    pub const SDL_LASTERROR: SDL_errorcode = 5;
36
37    pub type SDL_InitFlag = uint32_t;
38    pub const SDL_INIT_TIMER: SDL_InitFlag = 0x00000001;
39    pub const SDL_INIT_AUDIO: SDL_InitFlag = 0x00000010;
40    pub const SDL_INIT_VIDEO: SDL_InitFlag = 0x00000020;
41    pub const SDL_INIT_CDROM: SDL_InitFlag = 0x00000100;
42    pub const SDL_INIT_JOYSTICK: SDL_InitFlag = 0x00000200;
43    pub const SDL_INIT_NOPARACHUTE: SDL_InitFlag = 0x00100000;
44    pub const SDL_INIT_EVENTTHREAD: SDL_InitFlag = 0x01000000;
45    pub const SDL_INIT_EVERYTHING: SDL_InitFlag = 0x0000FFFF;
46
47    extern "C" {
48        pub fn SDL_ClearError();
49        pub fn SDL_Error(code: SDL_errorcode);
50        pub fn SDL_SetError(fmt: *const c_char);
51        pub fn SDL_GetError() -> *mut c_char;
52        pub fn SDL_Quit();
53        pub fn SDL_QuitSubSystem(flags: SDL_InitFlag);
54        pub fn SDL_Init(flags: uint32_t) -> c_int;
55        pub fn SDL_InitSubSystem(flags: SDL_InitFlag) -> c_int;
56        pub fn SDL_WasInit(flags: SDL_InitFlag) -> SDL_InitFlag;
57        pub fn SDL_GetTicks() -> uint32_t;
58    }
59}
60
61#[repr(C)]
62#[derive(PartialEq, Copy, Clone)]
63pub struct Rect {
64    pub x: i16,
65    pub y: i16,
66    pub w: u16,
67    pub h: u16,
68}
69
70#[allow(non_snake_case)]
71pub fn Rect(x: i16, y: i16, w: u16, h: u16) -> Rect {
72    Rect {
73        x: x,
74        y: y,
75        w: w,
76        h: h,
77    }
78}
79
80impl Rect {
81    pub fn new(x: i16, y: i16, w: u16, h: u16) -> Rect {
82        Rect {
83            x: x,
84            y: y,
85            w: w,
86            h: h,
87        }
88    }
89}
90
91#[derive(PartialEq, Eq, Copy, Clone)]
92pub enum InitFlag {
93    Timer = ll::SDL_INIT_TIMER as isize,
94    Audio = ll::SDL_INIT_AUDIO as isize,
95    Video = ll::SDL_INIT_VIDEO as isize,
96    CDRom = ll::SDL_INIT_CDROM as isize,
97    Joystick = ll::SDL_INIT_JOYSTICK as isize,
98    NoParachute = ll::SDL_INIT_NOPARACHUTE as isize,
99    EventThread = ll::SDL_INIT_EVENTTHREAD as isize,
100    Everything = ll::SDL_INIT_EVERYTHING as isize,
101}
102
103#[derive(PartialEq, Eq, Copy, Clone)]
104pub enum Error {
105    NoMem = ll::SDL_ENOMEM as isize,
106    Read = ll::SDL_EFREAD as isize,
107    Write = ll::SDL_EFWRITE as isize,
108    Seek = ll::SDL_EFSEEK as isize,
109    Unsupported = ll::SDL_UNSUPPORTED as isize,
110}
111
112pub fn init(flags: &[InitFlag]) -> bool {
113    unsafe {
114        ll::SDL_Init(
115            flags
116                .iter()
117                .fold(0u32, |flags, &flag| flags | flag as ll::SDL_InitFlag),
118        ) == 0
119    }
120}
121
122pub fn init_subsystem(flags: &[InitFlag]) -> bool {
123    unsafe {
124        ll::SDL_InitSubSystem(
125            flags
126                .iter()
127                .fold(0u32, |flags, &flag| flags | flag as ll::SDL_InitFlag),
128        ) == 0
129    }
130}
131
132pub fn quit_subsystem(flags: &[InitFlag]) {
133    let flags = flags
134        .iter()
135        .fold(0u32, |flags, &flag| flags | flag as ll::SDL_InitFlag);
136
137    unsafe {
138        ll::SDL_QuitSubSystem(flags);
139    }
140}
141
142pub fn quit() {
143    unsafe {
144        ll::SDL_Quit();
145    }
146}
147
148pub fn was_inited(flags: &[InitFlag]) -> Vec<InitFlag> {
149    let flags = flags
150        .iter()
151        .fold(0u32, |flags, &flag| flags | flag as ll::SDL_InitFlag);
152    let bitflags = unsafe { ll::SDL_WasInit(flags) };
153
154    let flags = [
155        InitFlag::Timer,
156        InitFlag::Audio,
157        InitFlag::Video,
158        InitFlag::CDRom,
159        InitFlag::Joystick,
160        InitFlag::NoParachute,
161        InitFlag::EventThread,
162        InitFlag::Everything,
163    ];
164
165    flags
166        .iter()
167        .filter_map(|&flag| {
168            if bitflags & (flag as ll::SDL_InitFlag) != 0 {
169                Some(flag)
170            } else {
171                None
172            }
173        })
174        .collect()
175}
176
177pub fn get_error() -> String {
178    unsafe {
179        let cstr = ll::SDL_GetError();
180        let slice = CStr::from_ptr(cstr).to_bytes();
181
182        str::from_utf8(slice).unwrap().to_string()
183    }
184}
185
186pub fn set_error(err: &str) {
187    let err_str = CString::new(err.as_bytes()).unwrap();
188    unsafe {
189        ll::SDL_SetError(err_str.as_ptr());
190    }
191}
192
193pub fn set_error_from_code(err: Error) {
194    unsafe { ll::SDL_Error(err as ll::SDL_errorcode) }
195}
196
197pub fn clear_error() {
198    unsafe {
199        ll::SDL_ClearError();
200    }
201}
202
203pub fn get_ticks() -> usize {
204    unsafe { ll::SDL_GetTicks() as usize }
205}