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 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}