sdl/
cd.rs

1use libc::c_int;
2use std::str;
3use std::ffi::CStr;
4
5use get_error;
6
7pub mod ll {
8    #![allow(non_camel_case_types)]
9
10    use libc::{c_int, uint8_t, uint16_t, uint32_t};
11    use libc::types::os::arch::c95::c_schar;
12
13    pub type CDstatus = c_int;
14
15    pub const CD_TRAYEMPTY: CDstatus = 0;
16    pub const CD_STOPPED: CDstatus = 1;
17    pub const CD_PLAYING: CDstatus = 2;
18    pub const CD_PAUSED: CDstatus = 3;
19    pub const CD_ERROR: CDstatus = -1;
20
21    #[repr(C)]
22    #[derive(Copy, Clone)]
23    pub struct SDL_CDtrack {
24        pub id: uint8_t,
25        pub _type: uint8_t,
26        pub unused: uint16_t,
27        pub length: uint32_t,
28        pub offset: uint32_t
29    }
30
31    #[repr(C)]
32    #[derive(Copy)]
33    pub struct SDL_CD {
34        pub id: c_int,
35        pub status: CDstatus,
36        pub numtracks: c_int,
37        pub cur_track: c_int,
38        pub cur_frame: c_int,
39        pub track: [SDL_CDtrack; 100],
40    }
41
42    impl Clone for SDL_CD {
43        fn clone(&self) -> SDL_CD {
44            *self
45        }
46    }
47
48    extern "C" {
49        pub fn SDL_CDNumDrives() -> c_int;
50        pub fn SDL_CDName(drive: c_int) -> *const c_schar;
51        pub fn SDL_CDOpen(drive: c_int) -> *mut SDL_CD;
52        pub fn SDL_CDStatus(cdrom: *mut SDL_CD) -> CDstatus;
53        pub fn SDL_CDClose(cdrom: *mut SDL_CD);
54        pub fn SDL_CDStop(cdrom: *mut SDL_CD) -> c_int;
55        pub fn SDL_CDEject(cdrom: *mut SDL_CD) -> c_int;
56        pub fn SDL_CDResume(cdrom: *mut SDL_CD) -> c_int;
57        pub fn SDL_CDPlay(cdrom: *mut SDL_CD, start: c_int, length: c_int) -> c_int;
58        pub fn SDL_CDPlayTracks(cdrom: *mut SDL_CD,
59                                start_track: c_int,
60                                start_frame: c_int,
61                                ntracks: c_int,
62                                nframes: c_int) -> c_int;
63        pub fn SDL_CDPause(cdrom: *mut SDL_CD) -> c_int;
64    }
65}
66
67pub fn get_num_drives() -> isize {
68    unsafe { ll::SDL_CDNumDrives() as isize }
69}
70
71pub fn get_drive_name(index: isize) -> Result<String, String> {
72    unsafe {
73        let cstr = ll::SDL_CDName(index as c_int);
74
75        if cstr.is_null() {
76            Err(get_error())
77        } else {
78            Ok(str::from_utf8(CStr::from_ptr(cstr).to_bytes()).unwrap().to_string())
79        }
80    }
81}
82
83#[derive(PartialEq)]
84pub struct CD {
85    pub raw: *mut ll::SDL_CD
86}
87
88fn wrap_cd(raw: *mut ll::SDL_CD) -> CD {
89    CD { raw: raw }
90}
91
92#[derive(PartialEq, Eq, Copy, Clone)]
93pub enum Status {
94    TrayEmpty = ll::CD_TRAYEMPTY as isize,
95    Stopped = ll::CD_STOPPED as isize,
96    Playing = ll::CD_PLAYING as isize,
97    Paused = ll::CD_PAUSED as isize,
98    Error = ll::CD_ERROR as isize
99}
100
101impl CD {
102    pub fn open(index: isize) -> Result<CD, String> {
103        unsafe {
104            let raw = ll::SDL_CDOpen(index as c_int);
105
106            if raw.is_null() { Err(get_error()) }
107            else { Ok(wrap_cd(raw)) }
108        }
109    }
110
111    pub fn get_status(&self) -> Status {
112        unsafe {
113            // FIXME: Rust doesn't like us matching using staticants here for some reason
114            match ll::SDL_CDStatus(self.raw) {
115                0 => Status::TrayEmpty,
116                1 => Status::Stopped,
117                2 => Status::Playing,
118                3 => Status::Paused,
119                -1 => Status::Error,
120                _ => Status::Error
121            }
122        }
123    }
124
125    pub fn play(&self, start: isize, len: isize) -> bool {
126        unsafe { ll::SDL_CDPlay(self.raw, start as c_int, len as c_int) == 0 }
127    }
128
129    pub fn play_tracks(&self, start_track: isize, start_frame: isize, ntracks: isize,
130                   nframes: isize) -> bool {
131        unsafe {
132            ll::SDL_CDPlayTracks(self.raw, start_track as c_int, start_frame as c_int,
133                                 ntracks as c_int, nframes as c_int) == 0
134        }
135    }
136
137    pub fn pause(&self) -> bool {
138        unsafe { ll::SDL_CDPause(self.raw) == 0 }
139    }
140
141    pub fn resume(&self) -> bool {
142        unsafe { ll::SDL_CDResume(self.raw) == 0 }
143    }
144
145    pub fn stop(&self) -> bool {
146        unsafe { ll::SDL_CDStop(self.raw) == 0 }
147    }
148}
149
150impl Drop for CD {
151    fn drop(&mut self) {
152        unsafe { ll::SDL_CDClose(self.raw); }
153    }
154}