Mercurial > sdl-ios-xcode
annotate src/cdrom/openbsd/SDL_syscdrom.c @ 3958:85b6fb6a5e3c SDL-1.2
Actually, this is a better fix...clear the error state once if everything we
need loaded; it's more efficient, and works even if the last unnecessary
xrandr symbol failed to load. Otherwise, leave the original loadso error, so
the end user can find out what symbol failed.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Wed, 13 Jun 2007 08:00:10 +0000 |
parents | 92947e3a18db |
children | 782fd950bd46 c121d94672cb a1b03ba2fcd0 |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
3 Copyright (C) 1997-2006 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
1026
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
25
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
22 #include "SDL_config.h" |
0 | 23 |
1635
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
24 #ifdef SDL_CDROM_OPENBSD |
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
25 |
0 | 26 /* Functions for system-level CD-ROM audio control */ |
27 | |
28 #include <sys/types.h> | |
29 #include <sys/ioctl.h> | |
30 #include <sys/stat.h> | |
31 #include <fcntl.h> | |
32 #include <errno.h> | |
33 #include <unistd.h> | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
34 #include <sys/ioctl.h> |
0 | 35 #include <sys/cdio.h> |
36 | |
37 #include "SDL_cdrom.h" | |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
38 #include "../SDL_syscdrom.h" |
0 | 39 |
40 | |
41 /* The maximum number of CD-ROM drives we'll detect */ | |
42 #define MAX_DRIVES 16 | |
43 | |
44 /* A list of available CD-ROM drives */ | |
45 static char *SDL_cdlist[MAX_DRIVES]; | |
46 static dev_t SDL_cdmode[MAX_DRIVES]; | |
47 | |
48 /* The system-dependent CD control functions */ | |
49 static const char *SDL_SYS_CDName(int drive); | |
50 static int SDL_SYS_CDOpen(int drive); | |
51 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom); | |
52 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position); | |
53 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length); | |
54 static int SDL_SYS_CDPause(SDL_CD *cdrom); | |
55 static int SDL_SYS_CDResume(SDL_CD *cdrom); | |
56 static int SDL_SYS_CDStop(SDL_CD *cdrom); | |
57 static int SDL_SYS_CDEject(SDL_CD *cdrom); | |
58 static void SDL_SYS_CDClose(SDL_CD *cdrom); | |
59 | |
60 /* Some ioctl() errno values which occur when the tray is empty */ | |
61 #define ERRNO_TRAYEMPTY(errno) \ | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
62 ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL) || \ |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
63 (errno == ENODEV)) |
0 | 64 |
65 /* Check a drive to see if it is a CD-ROM */ | |
66 static int CheckDrive(char *drive, struct stat *stbuf) | |
67 { | |
68 int is_cd, cdfd; | |
69 struct ioc_read_subchannel info; | |
70 | |
71 /* If it doesn't exist, return -1 */ | |
72 if ( stat(drive, stbuf) < 0 ) { | |
73 return(-1); | |
74 } | |
75 | |
76 /* If it does exist, verify that it's an available CD-ROM */ | |
77 is_cd = 0; | |
78 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) { | |
79 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0); | |
80 if ( cdfd >= 0 ) { | |
81 info.address_format = CD_MSF_FORMAT; | |
82 info.data_format = CD_CURRENT_POSITION; | |
83 info.data_len = 0; | |
84 info.data = NULL; | |
85 /* Under Linux, EIO occurs when a disk is not present. | |
86 This isn't 100% reliable, so we use the USE_MNTENT | |
87 code above instead. | |
88 */ | |
89 if ( (ioctl(cdfd, CDIOCREADSUBCHANNEL, &info) == 0) || | |
90 ERRNO_TRAYEMPTY(errno) ) { | |
91 is_cd = 1; | |
92 } | |
93 close(cdfd); | |
94 } | |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
95 else if (ERRNO_TRAYEMPTY(errno)) |
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
96 is_cd = 1; |
0 | 97 } |
98 return(is_cd); | |
99 } | |
100 | |
101 /* Add a CD-ROM drive to our list of valid drives */ | |
102 static void AddDrive(char *drive, struct stat *stbuf) | |
103 { | |
104 int i; | |
105 | |
106 if ( SDL_numcds < MAX_DRIVES ) { | |
107 /* Check to make sure it's not already in our list. | |
108 This can happen when we see a drive via symbolic link. | |
109 */ | |
110 for ( i=0; i<SDL_numcds; ++i ) { | |
111 if ( stbuf->st_rdev == SDL_cdmode[i] ) { | |
112 #ifdef DEBUG_CDROM | |
113 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]); | |
114 #endif | |
115 return; | |
116 } | |
117 } | |
118 | |
119 /* Add this drive to our list */ | |
120 i = SDL_numcds; | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
121 SDL_cdlist[i] = SDL_strdup(drive); |
0 | 122 if ( SDL_cdlist[i] == NULL ) { |
123 SDL_OutOfMemory(); | |
124 return; | |
125 } | |
126 SDL_cdmode[i] = stbuf->st_rdev; | |
127 ++SDL_numcds; | |
128 #ifdef DEBUG_CDROM | |
129 fprintf(stderr, "Added CD-ROM drive: %s\n", drive); | |
130 #endif | |
131 } | |
132 } | |
133 | |
134 int SDL_SYS_CDInit(void) | |
135 { | |
136 static char *checklist[] = { | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
137 #if defined(__OPENBSD__) |
25
3fbf86244fd2
Date: Wed, 9 May 2001 18:03:20 -0600
Sam Lantinga <slouken@lokigames.com>
parents:
1
diff
changeset
|
138 "?0 cd?c", "cdrom", NULL |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1379
diff
changeset
|
139 #elif defined(__NETBSD__) |
1026
0f3aa6ab3341
Select patches included from The NetBSD Package Collection (www.pkgsrc.org)
Sam Lantinga <slouken@libsdl.org>
parents:
769
diff
changeset
|
140 "?0 cd?d", "?0 cd?c", "cdrom", NULL |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
141 #else |
0 | 142 "?0 cd?c", "?0 acd?c", "cdrom", NULL |
1
cf2af46e9e2a
Changes since SDL 1.2.0 release
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
143 #endif |
0 | 144 }; |
145 char *SDLcdrom; | |
146 int i, j, exists; | |
147 char drive[32]; | |
148 struct stat stbuf; | |
149 | |
150 /* Fill in our driver capabilities */ | |
151 SDL_CDcaps.Name = SDL_SYS_CDName; | |
152 SDL_CDcaps.Open = SDL_SYS_CDOpen; | |
153 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; | |
154 SDL_CDcaps.Status = SDL_SYS_CDStatus; | |
155 SDL_CDcaps.Play = SDL_SYS_CDPlay; | |
156 SDL_CDcaps.Pause = SDL_SYS_CDPause; | |
157 SDL_CDcaps.Resume = SDL_SYS_CDResume; | |
158 SDL_CDcaps.Stop = SDL_SYS_CDStop; | |
159 SDL_CDcaps.Eject = SDL_SYS_CDEject; | |
160 SDL_CDcaps.Close = SDL_SYS_CDClose; | |
161 | |
162 /* Look in the environment for our CD-ROM drive list */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
163 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */ |
0 | 164 if ( SDLcdrom != NULL ) { |
165 char *cdpath, *delim; | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
166 size_t len = SDL_strlen(SDLcdrom)+1; |
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
167 cdpath = SDL_stack_alloc(char, len); |
0 | 168 if ( cdpath != NULL ) { |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
169 SDL_strlcpy(cdpath, SDLcdrom, len); |
0 | 170 SDLcdrom = cdpath; |
171 do { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
172 delim = SDL_strchr(SDLcdrom, ':'); |
0 | 173 if ( delim ) { |
174 *delim++ = '\0'; | |
175 } | |
176 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { | |
177 AddDrive(SDLcdrom, &stbuf); | |
178 } | |
179 if ( delim ) { | |
180 SDLcdrom = delim; | |
181 } else { | |
182 SDLcdrom = NULL; | |
183 } | |
184 } while ( SDLcdrom ); | |
1379
c0a74f199ecf
Use only safe string functions
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
185 SDL_stack_free(cdpath); |
0 | 186 } |
187 | |
188 /* If we found our drives, there's nothing left to do */ | |
189 if ( SDL_numcds > 0 ) { | |
190 return(0); | |
191 } | |
192 } | |
193 | |
194 /* Scan the system for CD-ROM drives */ | |
195 for ( i=0; checklist[i]; ++i ) { | |
196 if ( checklist[i][0] == '?' ) { | |
197 char *insert; | |
198 exists = 1; | |
199 for ( j=checklist[i][1]; exists; ++j ) { | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
200 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]); |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
201 insert = SDL_strchr(drive, '?'); |
0 | 202 if ( insert != NULL ) { |
203 *insert = j; | |
204 } | |
205 switch (CheckDrive(drive, &stbuf)) { | |
206 /* Drive exists and is a CD-ROM */ | |
207 case 1: | |
208 AddDrive(drive, &stbuf); | |
209 break; | |
210 /* Drive exists, but isn't a CD-ROM */ | |
211 case 0: | |
212 break; | |
213 /* Drive doesn't exist */ | |
214 case -1: | |
215 exists = 0; | |
216 break; | |
217 } | |
218 } | |
219 } else { | |
1338
604d73db6802
Removed uses of stdlib.h and string.h
Sam Lantinga <slouken@libsdl.org>
parents:
1336
diff
changeset
|
220 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]); |
0 | 221 if ( CheckDrive(drive, &stbuf) > 0 ) { |
222 AddDrive(drive, &stbuf); | |
223 } | |
224 } | |
225 } | |
226 return(0); | |
227 } | |
228 | |
229 /* General ioctl() CD-ROM command function */ | |
230 static int SDL_SYS_CDioctl(int id, int command, void *arg) | |
231 { | |
232 int retval; | |
233 | |
234 retval = ioctl(id, command, arg); | |
235 if ( retval < 0 ) { | |
236 SDL_SetError("ioctl() error: %s", strerror(errno)); | |
237 } | |
238 return(retval); | |
239 } | |
240 | |
241 static const char *SDL_SYS_CDName(int drive) | |
242 { | |
243 return(SDL_cdlist[drive]); | |
244 } | |
245 | |
246 static int SDL_SYS_CDOpen(int drive) | |
247 { | |
248 return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0)); | |
249 } | |
250 | |
251 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
252 { | |
253 struct ioc_toc_header toc; | |
254 int i, okay; | |
255 struct ioc_read_toc_entry entry; | |
256 struct cd_toc_entry data; | |
257 | |
258 okay = 0; | |
259 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) { | |
260 cdrom->numtracks = toc.ending_track-toc.starting_track+1; | |
261 if ( cdrom->numtracks > SDL_MAX_TRACKS ) { | |
262 cdrom->numtracks = SDL_MAX_TRACKS; | |
263 } | |
264 /* Read all the track TOC entries */ | |
265 for ( i=0; i<=cdrom->numtracks; ++i ) { | |
266 if ( i == cdrom->numtracks ) { | |
267 cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */ | |
268 } else { | |
269 cdrom->track[i].id = toc.starting_track+i; | |
270 } | |
271 entry.starting_track = cdrom->track[i].id; | |
272 entry.address_format = CD_MSF_FORMAT; | |
273 entry.data_len = sizeof(data); | |
274 entry.data = &data; | |
275 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS, | |
276 &entry) < 0 ) { | |
277 break; | |
278 } else { | |
279 cdrom->track[i].type = data.control; | |
280 cdrom->track[i].offset = MSF_TO_FRAMES( | |
281 data.addr.msf.minute, | |
282 data.addr.msf.second, | |
283 data.addr.msf.frame); | |
284 cdrom->track[i].length = 0; | |
285 if ( i > 0 ) { | |
286 cdrom->track[i-1].length = | |
287 cdrom->track[i].offset- | |
288 cdrom->track[i-1].offset; | |
289 } | |
290 } | |
291 } | |
292 if ( i == (cdrom->numtracks+1) ) { | |
293 okay = 1; | |
294 } | |
295 } | |
296 return(okay ? 0 : -1); | |
297 } | |
298 | |
299 /* Get CD-ROM status */ | |
300 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position) | |
301 { | |
302 CDstatus status; | |
303 struct ioc_toc_header toc; | |
304 struct ioc_read_subchannel info; | |
305 struct cd_sub_channel_info data; | |
306 | |
307 info.address_format = CD_MSF_FORMAT; | |
308 info.data_format = CD_CURRENT_POSITION; | |
309 info.track = 0; | |
310 info.data_len = sizeof(data); | |
311 info.data = &data; | |
312 if ( ioctl(cdrom->id, CDIOCREADSUBCHANNEL, &info) < 0 ) { | |
313 if ( ERRNO_TRAYEMPTY(errno) ) { | |
314 status = CD_TRAYEMPTY; | |
315 } else { | |
316 status = CD_ERROR; | |
317 } | |
318 } else { | |
319 switch (data.header.audio_status) { | |
320 case CD_AS_AUDIO_INVALID: | |
321 case CD_AS_NO_STATUS: | |
322 /* Try to determine if there's a CD available */ | |
323 if (ioctl(cdrom->id,CDIOREADTOCHEADER,&toc)==0) | |
324 status = CD_STOPPED; | |
325 else | |
326 status = CD_TRAYEMPTY; | |
327 break; | |
328 case CD_AS_PLAY_COMPLETED: | |
329 status = CD_STOPPED; | |
330 break; | |
331 case CD_AS_PLAY_IN_PROGRESS: | |
332 status = CD_PLAYING; | |
333 break; | |
334 case CD_AS_PLAY_PAUSED: | |
335 status = CD_PAUSED; | |
336 break; | |
337 default: | |
338 status = CD_ERROR; | |
339 break; | |
340 } | |
341 } | |
342 if ( position ) { | |
343 if ( status == CD_PLAYING || (status == CD_PAUSED) ) { | |
344 *position = MSF_TO_FRAMES( | |
345 data.what.position.absaddr.msf.minute, | |
346 data.what.position.absaddr.msf.second, | |
347 data.what.position.absaddr.msf.frame); | |
348 } else { | |
349 *position = 0; | |
350 } | |
351 } | |
352 return(status); | |
353 } | |
354 | |
355 /* Start play */ | |
356 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length) | |
357 { | |
358 struct ioc_play_msf playtime; | |
359 | |
360 FRAMES_TO_MSF(start, | |
361 &playtime.start_m, &playtime.start_s, &playtime.start_f); | |
362 FRAMES_TO_MSF(start+length, | |
363 &playtime.end_m, &playtime.end_s, &playtime.end_f); | |
364 #ifdef DEBUG_CDROM | |
365 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n", | |
366 playtime.start_m, playtime.start_s, playtime.start_f, | |
367 playtime.end_m, playtime.end_s, playtime.end_f); | |
368 #endif | |
369 ioctl(cdrom->id, CDIOCSTART, 0); | |
370 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPLAYMSF, &playtime)); | |
371 } | |
372 | |
373 /* Pause play */ | |
374 static int SDL_SYS_CDPause(SDL_CD *cdrom) | |
375 { | |
376 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0)); | |
377 } | |
378 | |
379 /* Resume play */ | |
380 static int SDL_SYS_CDResume(SDL_CD *cdrom) | |
381 { | |
382 return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0)); | |
383 } | |
384 | |
385 /* Stop play */ | |
386 static int SDL_SYS_CDStop(SDL_CD *cdrom) | |
387 { | |
388 return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0)); | |
389 } | |
390 | |
391 /* Eject the CD-ROM */ | |
392 static int SDL_SYS_CDEject(SDL_CD *cdrom) | |
393 { | |
394 return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0)); | |
395 } | |
396 | |
397 /* Close the CD-ROM handle */ | |
398 static void SDL_SYS_CDClose(SDL_CD *cdrom) | |
399 { | |
400 close(cdrom->id); | |
401 } | |
402 | |
403 void SDL_SYS_CDQuit(void) | |
404 { | |
405 int i; | |
406 | |
407 if ( SDL_numcds > 0 ) { | |
408 for ( i=0; i<SDL_numcds; ++i ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
409 SDL_free(SDL_cdlist[i]); |
0 | 410 } |
411 SDL_numcds = 0; | |
412 } | |
413 } | |
414 | |
1635
92947e3a18db
Make sure code is only compiled if the appropriate subsystem is enabled
Sam Lantinga <slouken@libsdl.org>
parents:
1402
diff
changeset
|
415 #endif /* SDL_CDROM_OPENBSD */ |