sdl/
cd.rs

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