summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/src/cdrom
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/src/cdrom')
-rw-r--r--apps/plugins/sdl/src/cdrom/aix/SDL_syscdrom.c660
-rw-r--r--apps/plugins/sdl/src/cdrom/beos/SDL_syscdrom.cc410
-rw-r--r--apps/plugins/sdl/src/cdrom/bsdi/SDL_syscdrom.c542
-rw-r--r--apps/plugins/sdl/src/cdrom/dc/SDL_syscdrom.c167
-rw-r--r--apps/plugins/sdl/src/cdrom/freebsd/SDL_syscdrom.c406
-rw-r--r--apps/plugins/sdl/src/cdrom/linux/SDL_syscdrom.c564
-rw-r--r--apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom.c525
-rw-r--r--apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom_c.h140
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c360
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h178
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c610
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c636
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h69
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c199
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h116
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c514
-rw-r--r--apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h136
-rw-r--r--apps/plugins/sdl/src/cdrom/mint/SDL_syscdrom.c317
-rw-r--r--apps/plugins/sdl/src/cdrom/openbsd/SDL_syscdrom.c416
-rw-r--r--apps/plugins/sdl/src/cdrom/os2/SDL_syscdrom.c393
-rw-r--r--apps/plugins/sdl/src/cdrom/osf/SDL_syscdrom.c444
-rw-r--r--apps/plugins/sdl/src/cdrom/qnx/SDL_syscdrom.c551
-rw-r--r--apps/plugins/sdl/src/cdrom/win32/SDL_syscdrom.c386
23 files changed, 0 insertions, 8739 deletions
diff --git a/apps/plugins/sdl/src/cdrom/aix/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/aix/SDL_syscdrom.c
deleted file mode 100644
index e7e05585e3..0000000000
--- a/apps/plugins/sdl/src/cdrom/aix/SDL_syscdrom.c
+++ /dev/null
@@ -1,660 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Carsten Griwodz
20 griff@kom.tu-darmstadt.de
21
22 based on linux/SDL_syscdrom.c by Sam Lantinga
23*/
24#include "SDL_config.h"
25
26#ifdef SDL_CDROM_AIX
27
28/* Functions for system-level CD-ROM audio control */
29
30/*#define DEBUG_CDROM 1*/
31
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <fcntl.h>
35#include <errno.h>
36#include <unistd.h>
37
38#include <sys/ioctl.h>
39#include <sys/devinfo.h>
40#include <sys/mntctl.h>
41#include <sys/statfs.h>
42#include <sys/vmount.h>
43#include <fstab.h>
44#include <sys/scdisk.h>
45
46#include "SDL_cdrom.h"
47#include "../SDL_syscdrom.h"
48
49/* The maximum number of CD-ROM drives we'll detect */
50#define MAX_DRIVES 16
51
52/* A list of available CD-ROM drives */
53static char *SDL_cdlist[MAX_DRIVES];
54static dev_t SDL_cdmode[MAX_DRIVES];
55
56/* The system-dependent CD control functions */
57static const char *SDL_SYS_CDName(int drive);
58static int SDL_SYS_CDOpen(int drive);
59static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
60static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
61static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
62static int SDL_SYS_CDPause(SDL_CD *cdrom);
63static int SDL_SYS_CDResume(SDL_CD *cdrom);
64static int SDL_SYS_CDStop(SDL_CD *cdrom);
65static int SDL_SYS_CDEject(SDL_CD *cdrom);
66static void SDL_SYS_CDClose(SDL_CD *cdrom);
67static int SDL_SYS_CDioctl(int id, int command, void *arg);
68
69/* Check a drive to see if it is a CD-ROM */
70static int CheckDrive(char *drive, struct stat *stbuf)
71{
72 int is_cd;
73 int cdfd;
74 int ret;
75 struct devinfo info;
76
77 /* If it doesn't exist, return -1 */
78 if ( stat(drive, stbuf) < 0 ) {
79 return -1;
80 }
81
82 /* If it does exist, verify that it's an available CD-ROM */
83 is_cd = 0;
84 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) {
85 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
86 if ( cdfd >= 0 ) {
87 ret = SDL_SYS_CDioctl( cdfd, IOCINFO, &info );
88 if ( ret < 0 ) {
89 /* Some kind of error */
90 is_cd = 0;
91 } else {
92 if ( info.devtype == DD_CDROM ) {
93 is_cd = 1;
94 } else {
95 is_cd = 0;
96 }
97 }
98 close(cdfd);
99 }
100#ifdef DEBUG_CDROM
101 else
102 {
103 fprintf(stderr, "Could not open drive %s (%s)\n", drive, strerror(errno));
104 }
105#endif
106 }
107 return is_cd;
108}
109
110/* Add a CD-ROM drive to our list of valid drives */
111static void AddDrive(char *drive, struct stat *stbuf)
112{
113 int i;
114
115 if ( SDL_numcds < MAX_DRIVES ) {
116 /* Check to make sure it's not already in our list.
117 This can happen when we see a drive via symbolic link.
118 */
119 for ( i=0; i<SDL_numcds; ++i ) {
120 if ( stbuf->st_rdev == SDL_cdmode[i] ) {
121#ifdef DEBUG_CDROM
122 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
123#endif
124 return;
125 }
126 }
127
128 /* Add this drive to our list */
129 i = SDL_numcds;
130 SDL_cdlist[i] = SDL_strdup(drive);
131 if ( SDL_cdlist[i] == NULL ) {
132 SDL_OutOfMemory();
133 return;
134 }
135 SDL_cdmode[i] = stbuf->st_rdev;
136 ++SDL_numcds;
137#ifdef DEBUG_CDROM
138 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
139#endif
140 }
141}
142
143static void CheckMounts()
144{
145 char* buffer;
146 int bufsz;
147 struct vmount* ptr;
148 int ret;
149
150 buffer = (char*)SDL_malloc(10);
151 bufsz = 10;
152 if ( buffer==NULL )
153 {
154 fprintf(stderr, "Could not allocate 10 bytes in aix/SDL_syscdrom.c:CheckMounts\n" );
155 exit ( -10 );
156 }
157
158 do
159 {
160 /* mntctrl() returns an array of all mounted filesystems */
161 ret = mntctl ( MCTL_QUERY, bufsz, buffer );
162 if ( ret == 0 )
163 {
164 /* Buffer was too small, realloc. */
165 bufsz = *(int*)buffer; /* Required size is in first word. */
166 /* (whatever a word is in AIX 4.3.3) */
167 /* int seems to be OK in 32bit mode. */
168 SDL_free(buffer);
169 buffer = (char*)SDL_malloc(bufsz);
170 if ( buffer==NULL )
171 {
172 fprintf(stderr,
173 "Could not allocate %d bytes in aix/SDL_syscdrom.c:CheckMounts\n",
174 bufsz );
175 exit ( -10 );
176 }
177 }
178 else if ( ret < 0 )
179 {
180#ifdef DEBUG_CDROM
181 fprintf(stderr, "Error reading vmount structures\n");
182#endif
183 return;
184 }
185 }
186 while ( ret == 0 );
187
188#ifdef DEBUG_CDROM
189 fprintf ( stderr, "Read %d vmount structures\n",ret );
190#endif
191 ptr = (struct vmount*)buffer;
192 do
193 {
194 switch(ptr->vmt_gfstype)
195 {
196 case MNT_CDROM :
197 {
198 struct stat stbuf;
199 char* text;
200
201 text = (char*)ptr + ptr->vmt_data[VMT_OBJECT].vmt_off;
202#ifdef DEBUG_CDROM
203 fprintf(stderr, "Checking mount path: %s mounted on %s\n",
204 text, (char*)ptr + ptr->vmt_data[VMT_STUB].vmt_off );
205#endif
206 if ( CheckDrive( text, &stbuf) > 0)
207 {
208 AddDrive( text, &stbuf);
209 }
210 }
211 break;
212 default :
213 break;
214 }
215 ptr = (struct vmount*)((char*)ptr + ptr->vmt_length);
216 ret--;
217 }
218 while ( ret > 0 );
219
220 free ( buffer );
221}
222
223static int CheckNonmounts()
224{
225#ifdef _THREAD_SAFE
226 AFILE_t fsFile = NULL;
227 int passNo = 0;
228 int ret;
229 struct fstab entry;
230 struct stat stbuf;
231
232 ret = setfsent_r( &fsFile, &passNo );
233 if ( ret != 0 ) return -1;
234 do
235 {
236 ret = getfsent_r ( &entry, &fsFile, &passNo );
237 if ( ret == 0 ) {
238 char* l = SDL_strrchr(entry.fs_spec,'/');
239 if ( l != NULL ) {
240 if ( !SDL_strncmp("cd",++l,2) ) {
241#ifdef DEBUG_CDROM
242 fprintf(stderr,
243 "Found unmounted CD ROM drive with device name %s\n",
244 entry.fs_spec);
245#endif
246 if ( CheckDrive( entry.fs_spec, &stbuf) > 0)
247 {
248 AddDrive( entry.fs_spec, &stbuf);
249 }
250 }
251 }
252 }
253 }
254 while ( ret == 0 );
255 ret = endfsent_r ( &fsFile );
256 if ( ret != 0 ) return -1;
257 return 0;
258#else
259 struct fstab* entry;
260 struct stat stbuf;
261
262 setfsent();
263 do
264 {
265 entry = getfsent();
266 if ( entry != NULL ) {
267 char* l = SDL_strrchr(entry->fs_spec,'/');
268 if ( l != NULL ) {
269 if ( !SDL_strncmp("cd",++l,2) ) {
270#ifdef DEBUG_CDROM
271 fprintf(stderr,"Found unmounted CD ROM drive with device name %s", entry->fs_spec);
272#endif
273 if ( CheckDrive( entry->fs_spec, &stbuf) > 0)
274 {
275 AddDrive( entry->fs_spec, &stbuf);
276 }
277 }
278 }
279 }
280 }
281 while ( entry != NULL );
282 endfsent();
283#endif
284}
285
286int SDL_SYS_CDInit(void)
287{
288 char *SDLcdrom;
289 struct stat stbuf;
290
291 /* Fill in our driver capabilities */
292 SDL_CDcaps.Name = SDL_SYS_CDName;
293 SDL_CDcaps.Open = SDL_SYS_CDOpen;
294 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
295 SDL_CDcaps.Status = SDL_SYS_CDStatus;
296 SDL_CDcaps.Play = SDL_SYS_CDPlay;
297 SDL_CDcaps.Pause = SDL_SYS_CDPause;
298 SDL_CDcaps.Resume = SDL_SYS_CDResume;
299 SDL_CDcaps.Stop = SDL_SYS_CDStop;
300 SDL_CDcaps.Eject = SDL_SYS_CDEject;
301 SDL_CDcaps.Close = SDL_SYS_CDClose;
302
303 /* Look in the environment for our CD-ROM drive list */
304 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
305 if ( SDLcdrom != NULL ) {
306 char *cdpath, *delim;
307 size_t len = SDL_strlen(SDLcdrom)+1;
308 cdpath = SDL_stack_alloc(char, len);
309 if ( cdpath != NULL ) {
310 SDL_strlcpy(cdpath, SDLcdrom, len);
311 SDLcdrom = cdpath;
312 do {
313 delim = SDL_strchr(SDLcdrom, ':');
314 if ( delim ) {
315 *delim++ = '\0';
316 }
317#ifdef DEBUG_CDROM
318 fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom);
319#endif
320 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
321 AddDrive(SDLcdrom, &stbuf);
322 }
323 if ( delim ) {
324 SDLcdrom = delim;
325 } else {
326 SDLcdrom = NULL;
327 }
328 } while ( SDLcdrom );
329 SDL_stack_free(cdpath);
330 }
331
332 /* If we found our drives, there's nothing left to do */
333 if ( SDL_numcds > 0 ) {
334 return(0);
335 }
336 }
337
338 CheckMounts();
339 CheckNonmounts();
340
341 return 0;
342}
343
344/* General ioctl() CD-ROM command function */
345static int SDL_SYS_CDioctl(int id, int command, void *arg)
346{
347 int retval;
348
349 retval = ioctl(id, command, arg);
350 if ( retval < 0 ) {
351 SDL_SetError("ioctl() error: %s", strerror(errno));
352 }
353 return retval;
354}
355
356static const char *SDL_SYS_CDName(int drive)
357{
358 return(SDL_cdlist[drive]);
359}
360
361static int SDL_SYS_CDOpen(int drive)
362{
363 int fd;
364 char* lastsl;
365 char* cdromname;
366 size_t len;
367
368 /*
369 * We found /dev/cd? drives and that is in our list. But we can
370 * open only the /dev/rcd? versions of those devices for Audio CD.
371 */
372 len = SDL_strlen(SDL_cdlist[drive])+2;
373 cdromname = (char*)SDL_malloc(len);
374 SDL_strlcpy(cdromname,SDL_cdlist[drive],len);
375 lastsl = SDL_strrchr(cdromname,'/');
376 if (lastsl) {
377 *lastsl = 0;
378 SDL_strlcat(cdromname,"/r",len);
379 lastsl = SDL_strrchr(SDL_cdlist[drive],'/');
380 if (lastsl) {
381 lastsl++;
382 SDL_strlcat(cdromname,lastsl,len);
383 }
384 }
385
386#ifdef DEBUG_CDROM
387 fprintf(stderr, "Should open drive %s, opening %s\n", SDL_cdlist[drive], cdromname);
388#endif
389
390 /*
391 * Use exclusive access. Don't use SC_DIAGNOSTICS as xmcd does because they
392 * require root priviledges, and we don't want that. SC_SINGLE provides
393 * exclusive access with less trouble.
394 */
395 fd = openx(cdromname, O_RDONLY, NULL, SC_SINGLE);
396 if ( fd < 0 )
397 {
398#ifdef DEBUG_CDROM
399 fprintf(stderr, "Could not open drive %s (%s)\n", cdromname, strerror(errno));
400#endif
401 }
402 else
403 {
404 struct mode_form_op cdMode;
405 int ret;
406#ifdef DEBUG_CDROM
407 cdMode.action = CD_GET_MODE;
408 ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode);
409 if ( ret < 0 ) {
410 fprintf(stderr,
411 "Could not get drive mode for %s (%s)\n",
412 cdromname, strerror(errno));
413 } else {
414 switch(cdMode.cd_mode_form) {
415 case CD_MODE1 :
416 fprintf(stderr,
417 "Drive mode for %s is %s\n",
418 cdromname, "CD-ROM Data Mode 1");
419 break;
420 case CD_MODE2_FORM1 :
421 fprintf(stderr,
422 "Drive mode for %s is %s\n",
423 cdromname, "CD-ROM XA Data Mode 2 Form 1");
424 break;
425 case CD_MODE2_FORM2 :
426 fprintf(stderr,
427 "Drive mode for %s is %s\n",
428 cdromname, "CD-ROM XA Data Mode 2 Form 2");
429 break;
430 case CD_DA :
431 fprintf(stderr,
432 "Drive mode for %s is %s\n",
433 cdromname, "CD-DA");
434 break;
435 default :
436 fprintf(stderr,
437 "Drive mode for %s is %s\n",
438 cdromname, "unknown");
439 break;
440 }
441 }
442#endif
443
444 cdMode.action = CD_CHG_MODE;
445 cdMode.cd_mode_form = CD_DA;
446 ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode);
447 if ( ret < 0 ) {
448#ifdef DEBUG_CDROM
449 fprintf(stderr,
450 "Could not set drive mode for %s (%s)\n",
451 cdromname, strerror(errno));
452#endif
453 SDL_SetError("ioctl() error: Could not set CD drive mode, %s",
454 strerror(errno));
455 } else {
456#ifdef DEBUG_CDROM
457 fprintf(stderr,
458 "Drive mode for %s set to CD_DA\n",
459 cdromname);
460#endif
461 }
462 }
463 SDL_free(cdromname);
464 return fd;
465}
466
467static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
468{
469 struct cd_audio_cmd cmd;
470 struct cd_audio_cmd entry;
471 int i;
472 int okay;
473
474 cmd.audio_cmds = CD_TRK_INFO_AUDIO;
475 cmd.msf_flag = FALSE;
476 if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) {
477 return -1;
478 }
479
480 okay = 0;
481 cdrom->numtracks = cmd.indexing.track_index.last_track
482 - cmd.indexing.track_index.first_track+1;
483 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
484 cdrom->numtracks = SDL_MAX_TRACKS;
485 }
486
487 /* Read all the track TOC entries */
488 for ( i=0; i<=cdrom->numtracks; ++i ) {
489 if ( i == cdrom->numtracks ) {
490 cdrom->track[i].id = 0xAA;;
491 } else {
492 cdrom->track[i].id = cmd.indexing.track_index.first_track+i;
493 }
494 entry.audio_cmds = CD_GET_TRK_MSF;
495 entry.indexing.track_msf.track = cdrom->track[i].id;
496 if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &entry) < 0 ) {
497 break;
498 } else {
499 cdrom->track[i].type = 0; /* don't know how to detect 0x04 data track */
500 cdrom->track[i].offset = MSF_TO_FRAMES(
501 entry.indexing.track_msf.mins,
502 entry.indexing.track_msf.secs,
503 entry.indexing.track_msf.frames);
504 cdrom->track[i].length = 0;
505 if ( i > 0 ) {
506 cdrom->track[i-1].length = cdrom->track[i].offset
507 - cdrom->track[i-1].offset;
508 }
509 }
510 }
511 if ( i == (cdrom->numtracks+1) ) {
512 okay = 1;
513 }
514 return(okay ? 0 : -1);
515}
516
517/* Get CD-ROM status */
518static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
519{
520 CDstatus status;
521 struct cd_audio_cmd cmd;
522 cmd.audio_cmds = CD_INFO_AUDIO;
523
524 if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) {
525#ifdef DEBUG_CDROM
526 fprintf(stderr, "ioctl failed in SDL_SYS_CDStatus (%s)\n", SDL_GetError());
527#endif
528 status = CD_ERROR;
529 } else {
530 switch (cmd.status) {
531 case CD_NO_AUDIO:
532 case CD_COMPLETED:
533 status = CD_STOPPED;
534 break;
535 case CD_PLAY_AUDIO:
536 status = CD_PLAYING;
537 break;
538 case CD_PAUSE_AUDIO:
539 status = CD_PAUSED;
540 break;
541 case CD_NOT_VALID:
542#ifdef DEBUG_CDROM
543 fprintf(stderr, "cdStatus failed with CD_NOT_VALID\n");
544#endif
545 status = CD_ERROR;
546 break;
547 case CD_STATUS_ERROR:
548#ifdef DEBUG_CDROM
549 fprintf(stderr, "cdStatus failed with CD_STATUS_ERROR\n");
550#endif
551 status = CD_ERROR;
552 break;
553 default:
554#ifdef DEBUG_CDROM
555 fprintf(stderr, "cdStatus failed with unknown error\n");
556#endif
557 status = CD_ERROR;
558 break;
559 }
560 }
561 if ( position ) {
562 if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
563 *position = MSF_TO_FRAMES( cmd.indexing.info_audio.current_mins,
564 cmd.indexing.info_audio.current_secs,
565 cmd.indexing.info_audio.current_frames);
566 } else {
567 *position = 0;
568 }
569 }
570 return status;
571}
572
573/* Start play */
574static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
575{
576 struct cd_audio_cmd cmd;
577
578 /*
579 * My CD Rom is muted by default. I think I read that this is new with
580 * AIX 4.3. SDL does not change the volume, so I need a kludge. Maybe
581 * its better to do this elsewhere?
582 */
583 cmd.audio_cmds = CD_PLAY_AUDIO | CD_SET_VOLUME;
584 cmd.msf_flag = TRUE;
585 FRAMES_TO_MSF(start,
586 &cmd.indexing.msf.first_mins,
587 &cmd.indexing.msf.first_secs,
588 &cmd.indexing.msf.first_frames);
589 FRAMES_TO_MSF(start+length,
590 &cmd.indexing.msf.last_mins,
591 &cmd.indexing.msf.last_secs,
592 &cmd.indexing.msf.last_frames);
593 cmd.volume_type = CD_VOLUME_ALL;
594 cmd.all_channel_vol = 255; /* This is a uchar. What is a good value? No docu! */
595 cmd.out_port_0_sel = CD_AUDIO_CHNL_0;
596 cmd.out_port_1_sel = CD_AUDIO_CHNL_1;
597 cmd.out_port_2_sel = CD_AUDIO_CHNL_2;
598 cmd.out_port_3_sel = CD_AUDIO_CHNL_3;
599
600#ifdef DEBUG_CDROM
601 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
602 cmd.indexing.msf.first_mins,
603 cmd.indexing.msf.first_secs,
604 cmd.indexing.msf.first_frames,
605 cmd.indexing.msf.last_mins,
606 cmd.indexing.msf.last_secs,
607 cmd.indexing.msf.last_frames);
608#endif
609 return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
610}
611
612/* Pause play */
613static int SDL_SYS_CDPause(SDL_CD *cdrom)
614{
615 struct cd_audio_cmd cmd;
616 cmd.audio_cmds = CD_PAUSE_AUDIO;
617 return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
618}
619
620/* Resume play */
621static int SDL_SYS_CDResume(SDL_CD *cdrom)
622{
623 struct cd_audio_cmd cmd;
624 cmd.audio_cmds = CD_RESUME_AUDIO;
625 return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
626}
627
628/* Stop play */
629static int SDL_SYS_CDStop(SDL_CD *cdrom)
630{
631 struct cd_audio_cmd cmd;
632 cmd.audio_cmds = CD_STOP_AUDIO;
633 return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
634}
635
636/* Eject the CD-ROM */
637static int SDL_SYS_CDEject(SDL_CD *cdrom)
638{
639 return(SDL_SYS_CDioctl(cdrom->id, DKEJECT, 0));
640}
641
642/* Close the CD-ROM handle */
643static void SDL_SYS_CDClose(SDL_CD *cdrom)
644{
645 close(cdrom->id);
646}
647
648void SDL_SYS_CDQuit(void)
649{
650 int i;
651
652 if ( SDL_numcds > 0 ) {
653 for ( i=0; i<SDL_numcds; ++i ) {
654 SDL_free(SDL_cdlist[i]);
655 }
656 SDL_numcds = 0;
657 }
658}
659
660#endif /* SDL_CDROM_AIX */
diff --git a/apps/plugins/sdl/src/cdrom/beos/SDL_syscdrom.cc b/apps/plugins/sdl/src/cdrom/beos/SDL_syscdrom.cc
deleted file mode 100644
index 9a62c38399..0000000000
--- a/apps/plugins/sdl/src/cdrom/beos/SDL_syscdrom.cc
+++ /dev/null
@@ -1,410 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_BEOS
25
26/* Functions for system-level CD-ROM audio control on BeOS
27 (not completely implemented yet)
28 */
29
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <unistd.h>
33
34#include <scsi.h>
35#include <Directory.h>
36#include <Entry.h>
37#include <Path.h>
38
39#include "SDL_cdrom.h"
40extern "C" {
41#include "../SDL_syscdrom.h"
42}
43
44/* Constants to help us get at the SCSI table-of-contents info */
45#define CD_NUMTRACKS(toc) toc.toc_data[3]
46#define CD_TRACK(toc, track) (&toc.toc_data[6+(track)*8])
47#define CD_TRACK_N(toc, track) CD_TRACK(toc, track)[0]
48#define CD_TRACK_M(toc, track) CD_TRACK(toc, track)[3]
49#define CD_TRACK_S(toc, track) CD_TRACK(toc, track)[4]
50#define CD_TRACK_F(toc, track) CD_TRACK(toc, track)[5]
51
52/* Constants to help us get at the SCSI position info */
53#define POS_TRACK(pos) pos.position[6]
54#define POS_ABS_M(pos) pos.position[9]
55#define POS_ABS_S(pos) pos.position[10]
56#define POS_ABS_F(pos) pos.position[11]
57#define POS_REL_M(pos) pos.position[13]
58#define POS_REL_S(pos) pos.position[14]
59#define POS_REL_F(pos) pos.position[15]
60
61/* The maximum number of CD-ROM drives we'll detect */
62#define MAX_DRIVES 16
63
64/* A list of available CD-ROM drives */
65static char *SDL_cdlist[MAX_DRIVES];
66
67/* The system-dependent CD control functions */
68static const char *SDL_SYS_CDName(int drive);
69static int SDL_SYS_CDOpen(int drive);
70static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
71static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
72static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
73static int SDL_SYS_CDPause(SDL_CD *cdrom);
74static int SDL_SYS_CDResume(SDL_CD *cdrom);
75static int SDL_SYS_CDStop(SDL_CD *cdrom);
76static int SDL_SYS_CDEject(SDL_CD *cdrom);
77static void SDL_SYS_CDClose(SDL_CD *cdrom);
78int try_dir(const char *directory);
79
80
81/* Check a drive to see if it is a CD-ROM */
82static int CheckDrive(char *drive)
83{
84 struct stat stbuf;
85 int is_cd, cdfd;
86 device_geometry info;
87
88 /* If it doesn't exist, return -1 */
89 if ( stat(drive, &stbuf) < 0 ) {
90 return(-1);
91 }
92
93 /* If it does exist, verify that it's an available CD-ROM */
94 is_cd = 0;
95 cdfd = open(drive, 0);
96 if ( cdfd >= 0 ) {
97 if ( ioctl(cdfd, B_GET_GEOMETRY, &info) == B_NO_ERROR ) {
98 if ( info.device_type == B_CD ) {
99 is_cd = 1;
100 }
101 }
102 close(cdfd);
103 } else {
104 /* This can happen when the drive is open .. (?) */;
105 is_cd = 1;
106 }
107 return(is_cd);
108}
109
110/* Add a CD-ROM drive to our list of valid drives */
111static void AddDrive(char *drive)
112{
113 int i;
114 size_t len;
115
116 if ( SDL_numcds < MAX_DRIVES ) {
117 /* Add this drive to our list */
118 i = SDL_numcds;
119 len = SDL_strlen(drive)+1;
120 SDL_cdlist[i] = (char *)SDL_malloc(len);
121 if ( SDL_cdlist[i] == NULL ) {
122 SDL_OutOfMemory();
123 return;
124 }
125 SDL_strlcpy(SDL_cdlist[i], drive, len);
126 ++SDL_numcds;
127#ifdef CDROM_DEBUG
128 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
129#endif
130 }
131}
132
133/* IDE bus scanning magic */
134enum {
135 IDE_GET_DEVICES_INFO = B_DEVICE_OP_CODES_END + 50,
136};
137struct ide_ctrl_info {
138 bool ide_0_present;
139 bool ide_0_master_present;
140 bool ide_0_slave_present;
141 int ide_0_master_type;
142 int ide_0_slave_type;
143 bool ide_1_present;
144 bool ide_1_master_present;
145 bool ide_1_slave_present;
146 int ide_1_master_type;
147 int ide_1_slave_type;
148};
149
150int SDL_SYS_CDInit(void)
151{
152 char *SDLcdrom;
153
154 /* Fill in our driver capabilities */
155 SDL_CDcaps.Name = SDL_SYS_CDName;
156 SDL_CDcaps.Open = SDL_SYS_CDOpen;
157 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
158 SDL_CDcaps.Status = SDL_SYS_CDStatus;
159 SDL_CDcaps.Play = SDL_SYS_CDPlay;
160 SDL_CDcaps.Pause = SDL_SYS_CDPause;
161 SDL_CDcaps.Resume = SDL_SYS_CDResume;
162 SDL_CDcaps.Stop = SDL_SYS_CDStop;
163 SDL_CDcaps.Eject = SDL_SYS_CDEject;
164 SDL_CDcaps.Close = SDL_SYS_CDClose;
165
166 /* Look in the environment for our CD-ROM drive list */
167 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
168 if ( SDLcdrom != NULL ) {
169 char *cdpath, *delim;
170 size_t len = SDL_strlen(SDLcdrom)+1;
171 cdpath = SDL_stack_alloc(char, len);
172 if ( cdpath != NULL ) {
173 SDL_strlcpy(cdpath, SDLcdrom, len);
174 SDLcdrom = cdpath;
175 do {
176 delim = SDL_strchr(SDLcdrom, ':');
177 if ( delim ) {
178 *delim++ = '\0';
179 }
180 if ( CheckDrive(SDLcdrom) > 0 ) {
181 AddDrive(SDLcdrom);
182 }
183 if ( delim ) {
184 SDLcdrom = delim;
185 } else {
186 SDLcdrom = NULL;
187 }
188 } while ( SDLcdrom );
189 SDL_stack_free(cdpath);
190 }
191
192 /* If we found our drives, there's nothing left to do */
193 if ( SDL_numcds > 0 ) {
194 return(0);
195 }
196 }
197
198 /* Scan the system for CD-ROM drives */
199 try_dir("/dev/disk");
200 return 0;
201}
202
203
204int try_dir(const char *directory)
205{
206 BDirectory dir;
207 dir.SetTo(directory);
208 if(dir.InitCheck() != B_NO_ERROR) {
209 return false;
210 }
211 dir.Rewind();
212 BEntry entry;
213 while(dir.GetNextEntry(&entry) >= 0) {
214 BPath path;
215 const char *name;
216 entry_ref e;
217
218 if(entry.GetPath(&path) != B_NO_ERROR)
219 continue;
220 name = path.Path();
221
222 if(entry.GetRef(&e) != B_NO_ERROR)
223 continue;
224
225 if(entry.IsDirectory()) {
226 if(SDL_strcmp(e.name, "floppy") == 0)
227 continue; /* ignore floppy (it is not silent) */
228 int devfd = try_dir(name);
229 if(devfd >= 0)
230 return devfd;
231 }
232 else {
233 int devfd;
234 device_geometry g;
235
236 if(SDL_strcmp(e.name, "raw") != 0)
237 continue; /* ignore partitions */
238
239 devfd = open(name, O_RDONLY);
240 if(devfd < 0)
241 continue;
242
243 if(ioctl(devfd, B_GET_GEOMETRY, &g, sizeof(g)) >= 0) {
244 if(g.device_type == B_CD)
245 {
246 AddDrive(strdup(name));
247 }
248 }
249 close(devfd);
250 }
251 }
252 return B_ERROR;
253}
254
255
256/* General ioctl() CD-ROM command function */
257static int SDL_SYS_CDioctl(int index, int command, void *arg)
258{
259 int okay;
260 int fd;
261
262 okay = 0;
263 fd = open(SDL_cdlist[index], 0);
264 if ( fd >= 0 ) {
265 if ( ioctl(fd, command, arg) == B_NO_ERROR ) {
266 okay = 1;
267 }
268 close(fd);
269 }
270 return(okay ? 0 : -1);
271}
272
273static const char *SDL_SYS_CDName(int drive)
274{
275 return(SDL_cdlist[drive]);
276}
277
278static int SDL_SYS_CDOpen(int drive)
279{
280 return(drive);
281}
282
283static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
284{
285 int i;
286 scsi_toc toc;
287
288 if ( SDL_SYS_CDioctl(cdrom->id, B_SCSI_GET_TOC, &toc) == 0 ) {
289 cdrom->numtracks = CD_NUMTRACKS(toc);
290 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
291 cdrom->numtracks = SDL_MAX_TRACKS;
292 }
293 for ( i=0; i<=cdrom->numtracks; ++i ) {
294 cdrom->track[i].id = CD_TRACK_N(toc, i);
295 /* FIXME: How do we tell on BeOS? */
296 cdrom->track[i].type = SDL_AUDIO_TRACK;
297 cdrom->track[i].offset = MSF_TO_FRAMES(
298 CD_TRACK_M(toc, i),
299 CD_TRACK_S(toc, i),
300 CD_TRACK_F(toc, i));
301 cdrom->track[i].length = 0;
302 if ( i > 0 ) {
303 cdrom->track[i-1].length =
304 cdrom->track[i].offset-
305 cdrom->track[i-1].offset;
306 }
307 }
308 return(0);
309 } else {
310 return(-1);
311 }
312}
313
314/* Get CD-ROM status */
315static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
316{
317 CDstatus status;
318 int fd;
319 int cur_frame;
320 scsi_position pos;
321
322 fd = open(SDL_cdlist[cdrom->id], 0);
323 cur_frame = 0;
324 if ( fd >= 0 ) {
325 if ( ioctl(fd, B_SCSI_GET_POSITION, &pos) == B_NO_ERROR ) {
326 cur_frame = MSF_TO_FRAMES(
327 POS_ABS_M(pos), POS_ABS_S(pos), POS_ABS_F(pos));
328 }
329 if ( ! pos.position[1] || (pos.position[1] >= 0x13) ||
330 ((pos.position[1] == 0x12) && (!pos.position[6])) ) {
331 status = CD_STOPPED;
332 } else
333 if ( pos.position[1] == 0x11 ) {
334 status = CD_PLAYING;
335 } else {
336 status = CD_PAUSED;
337 }
338 close(fd);
339 } else {
340 status = CD_TRAYEMPTY;
341 }
342 if ( position ) {
343 *position = cur_frame;
344 }
345 return(status);
346}
347
348/* Start play */
349static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
350{
351 int okay;
352 int fd;
353 scsi_play_position pos;
354
355 okay = 0;
356 fd = open(SDL_cdlist[cdrom->id], 0);
357 if ( fd >= 0 ) {
358 FRAMES_TO_MSF(start, &pos.start_m, &pos.start_s, &pos.start_f);
359 FRAMES_TO_MSF(start+length, &pos.end_m, &pos.end_s, &pos.end_f);
360 if ( ioctl(fd, B_SCSI_PLAY_POSITION, &pos) == B_NO_ERROR ) {
361 okay = 1;
362 }
363 close(fd);
364 }
365 return(okay ? 0 : -1);
366}
367
368/* Pause play */
369static int SDL_SYS_CDPause(SDL_CD *cdrom)
370{
371 return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_PAUSE_AUDIO, 0));
372}
373
374/* Resume play */
375static int SDL_SYS_CDResume(SDL_CD *cdrom)
376{
377 return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_RESUME_AUDIO, 0));
378}
379
380/* Stop play */
381static int SDL_SYS_CDStop(SDL_CD *cdrom)
382{
383 return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_STOP_AUDIO, 0));
384}
385
386/* Eject the CD-ROM */
387static int SDL_SYS_CDEject(SDL_CD *cdrom)
388{
389 return(SDL_SYS_CDioctl(cdrom->id, B_SCSI_EJECT, 0));
390}
391
392/* Close the CD-ROM handle */
393static void SDL_SYS_CDClose(SDL_CD *cdrom)
394{
395 close(cdrom->id);
396}
397
398void SDL_SYS_CDQuit(void)
399{
400 int i;
401
402 if ( SDL_numcds > 0 ) {
403 for ( i=0; i<SDL_numcds; ++i ) {
404 SDL_free(SDL_cdlist[i]);
405 }
406 SDL_numcds = 0;
407 }
408}
409
410#endif /* SDL_CDROM_BEOS */
diff --git a/apps/plugins/sdl/src/cdrom/bsdi/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/bsdi/SDL_syscdrom.c
deleted file mode 100644
index 61edb819d2..0000000000
--- a/apps/plugins/sdl/src/cdrom/bsdi/SDL_syscdrom.c
+++ /dev/null
@@ -1,542 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_BSDI
25
26/*
27 * Functions for system-level CD-ROM audio control for BSD/OS 4.x
28 * This started life out as a copy of the freebsd/SDL_cdrom.c file but was
29 * heavily modified. Works for standard (MMC) SCSI and ATAPI CDrom drives.
30 *
31 * Steven Schultz - sms@to.gd-es.com
32*/
33
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <err.h>
38#include <unistd.h>
39#include <sys/ioctl.h>
40#include </sys/dev/scsi/scsi.h>
41#include </sys/dev/scsi/scsi_ioctl.h>
42
43#include "SDL_cdrom.h"
44#include "../SDL_syscdrom.h"
45
46/*
47 * The msf_to_frame and frame_to_msf were yanked from libcdrom and inlined
48 * here so that -lcdrom doesn't have to be dragged in for something so simple.
49*/
50
51#define FRAMES_PER_SECOND 75
52#define FRAMES_PER_MINUTE (FRAMES_PER_SECOND * 60)
53
54int
55msf_to_frame(int minute, int second, int frame)
56 {
57 return(minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame);
58 }
59
60void
61frame_to_msf(int frame, int *minp, int *secp, int *framep)
62 {
63 *minp = frame / FRAMES_PER_MINUTE;
64 *secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
65 *framep = frame % FRAMES_PER_SECOND;
66 }
67
68/* The maximum number of CD-ROM drives we'll detect */
69#define MAX_DRIVES 16
70
71/* A list of available CD-ROM drives */
72static char *SDL_cdlist[MAX_DRIVES];
73static dev_t SDL_cdmode[MAX_DRIVES];
74
75/* The system-dependent CD control functions */
76static const char *SDL_SYS_CDName(int drive);
77static int SDL_SYS_CDOpen(int drive);
78static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
79static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
80static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
81static int SDL_SYS_CDPause(SDL_CD *cdrom);
82static int SDL_SYS_CDResume(SDL_CD *cdrom);
83static int SDL_SYS_CDStop(SDL_CD *cdrom);
84static int SDL_SYS_CDEject(SDL_CD *cdrom);
85static void SDL_SYS_CDClose(SDL_CD *cdrom);
86
87typedef struct scsi_cdb cdb_t;
88
89static int scsi_cmd(int fd,
90 struct scsi_cdb *cdb,
91 int cdblen,
92 int rw,
93 caddr_t data,
94 int datalen,
95 struct scsi_user_cdb *sus)
96 {
97 int scsistatus;
98 unsigned char *cp;
99 struct scsi_user_cdb suc;
100
101 /* safety checks */
102 if (!cdb) return(-1);
103 if (rw != SUC_READ && rw != SUC_WRITE) return(-1);
104
105 suc.suc_flags = rw;
106 suc.suc_cdblen = cdblen;
107 bcopy(cdb, suc.suc_cdb, cdblen);
108 suc.suc_datalen = datalen;
109 suc.suc_data = data;
110 suc.suc_timeout = 10; /* 10 secs max for TUR or SENSE */
111 if (ioctl(fd, SCSIRAWCDB, &suc) == -1)
112 return(-11);
113 scsistatus = suc.suc_sus.sus_status;
114 cp = suc.suc_sus.sus_sense;
115
116/*
117 * If a place to copy the sense data back to has been provided then the
118 * caller is responsible for checking the errors and printing any information
119 * out if the status was not successful.
120*/
121 if (scsistatus != 0 && !sus)
122 {
123 fprintf(stderr,"scsistatus = %x cmd = %x\n",
124 scsistatus, cdb[0]);
125 fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
126 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
127 cp[6], cp[7], cp[8], cp[9], cp[10], cp[11],
128 cp[12], cp[13], cp[14], cp[15]);
129 return(1);
130 }
131 if (sus)
132 bcopy(&suc, sus, sizeof (struct scsi_user_cdb));
133 if (scsistatus)
134 return(1); /* Return non-zero for unsuccessful status */
135 return(0);
136 }
137
138/* request vendor brand and model */
139unsigned char *Inquiry(int fd)
140 {
141 static struct scsi_cdb6 cdb =
142 {
143 0x12,
144 0, 0, 0,
145 56,
146 0
147 };
148 static unsigned char Inqbuffer[56];
149
150 if (scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, Inqbuffer,
151 sizeof(Inqbuffer), 0))
152 return("\377");
153 return(Inqbuffer);
154 }
155
156#define ADD_SENSECODE 12
157#define ADD_SC_QUALIFIER 13
158
159int TestForMedium(int fd)
160 {
161 int sts, asc, ascq;
162 struct scsi_user_cdb sus;
163 static struct scsi_cdb6 cdb =
164 {
165 CMD_TEST_UNIT_READY, /* command */
166 0, /* reserved */
167 0, /* reserved */
168 0, /* reserved */
169 0, /* reserved */
170 0 /* reserved */
171 };
172
173again: sts = scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, 0, 0, &sus);
174 asc = sus.suc_sus.sus_sense[ADD_SENSECODE];
175 ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER];
176 if (asc == 0x3a && ascq == 0x0) /* no medium */
177 return(0);
178 if (asc == 0x28 && ascq == 0x0) /* medium changed */
179 goto again;
180 if (asc == 0x4 && ascq == 0x1 ) /* coming ready */
181 {
182 sleep(2);
183 goto again;
184 }
185 return(1);
186 }
187
188/* Check a drive to see if it is a CD-ROM */
189static int CheckDrive(char *drive, struct stat *stbuf)
190{
191 int is_cd = 0, cdfd;
192 char *p;
193
194 /* If it doesn't exist, return -1 */
195 if ( stat(drive, stbuf) < 0 ) {
196 return(-1);
197 }
198
199 /* If it does exist, verify that it's an available CD-ROM */
200 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
201 if ( cdfd >= 0 ) {
202 p = Inquiry(cdfd);
203 if (*p == TYPE_ROM)
204 is_cd = 1;
205 close(cdfd);
206 }
207 return(is_cd);
208}
209
210/* Add a CD-ROM drive to our list of valid drives */
211static void AddDrive(char *drive, struct stat *stbuf)
212{
213 int i;
214
215 if ( SDL_numcds < MAX_DRIVES ) {
216 /* Check to make sure it's not already in our list.
217 This can happen when we see a drive via symbolic link.
218 */
219 for ( i=0; i<SDL_numcds; ++i ) {
220 if ( stbuf->st_rdev == SDL_cdmode[i] ) {
221#ifdef DEBUG_CDROM
222 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
223#endif
224 return;
225 }
226 }
227
228 /* Add this drive to our list */
229 i = SDL_numcds;
230 SDL_cdlist[i] = SDL_strdup(drive);
231 if ( SDL_cdlist[i] == NULL ) {
232 SDL_OutOfMemory();
233 return;
234 }
235 SDL_cdmode[i] = stbuf->st_rdev;
236 ++SDL_numcds;
237#ifdef DEBUG_CDROM
238 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
239#endif
240 }
241}
242
243int SDL_SYS_CDInit(void)
244{
245 /* checklist: /dev/rsr?c */
246 static char *checklist[] = {
247 "?0 rsr?", NULL
248 };
249 char *SDLcdrom;
250 int i, j, exists;
251 char drive[32];
252 struct stat stbuf;
253
254 /* Fill in our driver capabilities */
255 SDL_CDcaps.Name = SDL_SYS_CDName;
256 SDL_CDcaps.Open = SDL_SYS_CDOpen;
257 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
258 SDL_CDcaps.Status = SDL_SYS_CDStatus;
259 SDL_CDcaps.Play = SDL_SYS_CDPlay;
260 SDL_CDcaps.Pause = SDL_SYS_CDPause;
261 SDL_CDcaps.Resume = SDL_SYS_CDResume;
262 SDL_CDcaps.Stop = SDL_SYS_CDStop;
263 SDL_CDcaps.Eject = SDL_SYS_CDEject;
264 SDL_CDcaps.Close = SDL_SYS_CDClose;
265
266 /* Look in the environment for our CD-ROM drive list */
267 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
268 if ( SDLcdrom != NULL ) {
269 char *cdpath, *delim;
270 size_t len = SDL_strlen(SDLcdrom)+1;
271 cdpath = SDL_stack_alloc(char, len);
272 if ( cdpath != NULL ) {
273 SDL_strlcpy(cdpath, SDLcdrom, len);
274 SDLcdrom = cdpath;
275 do {
276 delim = SDL_strchr(SDLcdrom, ':');
277 if ( delim ) {
278 *delim++ = '\0';
279 }
280 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
281 AddDrive(SDLcdrom, &stbuf);
282 }
283 if ( delim ) {
284 SDLcdrom = delim;
285 } else {
286 SDLcdrom = NULL;
287 }
288 } while ( SDLcdrom );
289 SDL_stack_free(cdpath);
290 }
291
292 /* If we found our drives, there's nothing left to do */
293 if ( SDL_numcds > 0 ) {
294 return(0);
295 }
296 }
297
298 /* Scan the system for CD-ROM drives */
299 for ( i=0; checklist[i]; ++i ) {
300 if ( checklist[i][0] == '?' ) {
301 char *insert;
302 exists = 1;
303 for ( j=checklist[i][1]; exists; ++j ) {
304 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc", &checklist[i][3]);
305 insert = SDL_strchr(drive, '?');
306 if ( insert != NULL ) {
307 *insert = j;
308 }
309 switch (CheckDrive(drive, &stbuf)) {
310 /* Drive exists and is a CD-ROM */
311 case 1:
312 AddDrive(drive, &stbuf);
313 break;
314 /* Drive exists, but isn't a CD-ROM */
315 case 0:
316 break;
317 /* Drive doesn't exist */
318 case -1:
319 exists = 0;
320 break;
321 }
322 }
323 } else {
324 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
325 if ( CheckDrive(drive, &stbuf) > 0 ) {
326 AddDrive(drive, &stbuf);
327 }
328 }
329 }
330 return(0);
331}
332
333static const char *SDL_SYS_CDName(int drive)
334{
335 return(SDL_cdlist[drive]);
336}
337
338static int SDL_SYS_CDOpen(int drive)
339{
340 return(open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0));
341}
342
343static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
344 {
345 u_char cdb[10], buf[4], *p, *toc;
346 struct scsi_user_cdb sus;
347 int i, sts, first_track, last_track, ntracks, toc_size;
348
349 bzero(cdb, sizeof (cdb));
350 cdb[0] = 0x43; /* Read TOC */
351 cdb[1] = 0x2; /* MSF */
352 cdb[8] = 4; /* size TOC header */
353 sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, 4, &sus);
354 if (sts < 0)
355 return(-1);
356 first_track = buf[2];
357 last_track = buf[3];
358 ntracks = last_track - first_track + 1;
359 cdrom->numtracks = ntracks;
360 toc_size = 4 + (ntracks + 1) * 8;
361 toc = (u_char *)SDL_malloc(toc_size);
362 if (toc == NULL)
363 return(-1);
364 bzero(cdb, sizeof (cdb));
365 cdb[0] = 0x43;
366 cdb[1] = 0x2;
367 cdb[6] = first_track;
368 cdb[7] = toc_size >> 8;
369 cdb[8] = toc_size & 0xff;
370 sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, toc, toc_size,
371 &sus);
372 if (sts < 0)
373 {
374 SDL_free(toc);
375 return(-1);
376 }
377
378 for (i = 0, p = toc+4; i <= ntracks; i++, p+= 8)
379 {
380 if (i == ntracks)
381 cdrom->track[i].id = 0xAA; /* Leadout */
382 else
383 cdrom->track[i].id = first_track + i;
384 if (p[1] & 0x20)
385 cdrom->track[i].type = SDL_DATA_TRACK;
386 else
387 cdrom->track[i].type = SDL_AUDIO_TRACK;
388 cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]);
389 cdrom->track[i].length = 0;
390 if (i > 0)
391 cdrom->track[i-1].length = cdrom->track[i].offset -
392 cdrom->track[i-1].offset;
393 }
394 SDL_free(toc);
395 return(0);
396 }
397
398/* Get CD-ROM status */
399static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
400 {
401 CDstatus status;
402 u_char cdb[10], buf[16];
403 int sts;
404 struct scsi_user_cdb sus;
405
406 bzero(cdb, sizeof (cdb));
407 cdb[0] = 0x42; /* read subq */
408 cdb[1] = 0x2; /* MSF */
409 cdb[2] = 0x40; /* q channel */
410 cdb[3] = 1; /* current pos */
411 cdb[7] = sizeof (buf) >> 8;
412 cdb[8] = sizeof (buf) & 0xff;
413 sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, sizeof (buf),
414 &sus);
415 if (sts < 0)
416 return(-1);
417 if (sts)
418 {
419 if (TestForMedium(cdrom->id) == 0)
420 status = CD_TRAYEMPTY;
421 else
422 status = CD_ERROR;
423 }
424 else
425 {
426 switch (buf[1])
427 {
428 case 0x11:
429 status = CD_PLAYING;
430 break;
431 case 0x12:
432 status = CD_PAUSED;
433 break;
434 case 0x13:
435 case 0x14:
436 case 0x15:
437 status = CD_STOPPED;
438 break;
439 default:
440 status = CD_ERROR;
441 break;
442 }
443 }
444 if (position)
445 {
446 if ( status == CD_PLAYING || (status == CD_PAUSED) )
447 *position = msf_to_frame(buf[9], buf[10], buf[11]);
448 else
449 *position = 0;
450 }
451 return(status);
452 }
453
454/* Start play */
455static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
456 {
457 u_char cdb[10];
458 int sts, minute, second, frame, eminute, esecond, eframe;
459 struct scsi_user_cdb sus;
460
461 bzero(cdb, sizeof(cdb));
462 cdb[0] = 0x47; /* Play */
463 frame_to_msf(start, &minute, &second, &frame);
464 frame_to_msf(start + length, &eminute, &esecond, &eframe);
465 cdb[3] = minute;
466 cdb[4] = second;
467 cdb[5] = frame;
468 cdb[6] = eminute;
469 cdb[7] = esecond;
470 cdb[8] = eframe;
471 sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus);
472 return(sts);
473 }
474
475static int
476pauseresume(SDL_CD *cdrom, int flag)
477 {
478 u_char cdb[10];
479 struct scsi_user_cdb sus;
480
481 bzero(cdb, sizeof (cdb));
482 cdb[0] = 0x4b;
483 cdb[8] = flag & 0x1;
484 return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus));
485 }
486
487/* Pause play */
488static int SDL_SYS_CDPause(SDL_CD *cdrom)
489{
490 return(pauseresume(cdrom, 0));
491}
492
493/* Resume play */
494static int SDL_SYS_CDResume(SDL_CD *cdrom)
495{
496 return(pauseresume(cdrom, 1));
497}
498
499/* Stop play */
500static int SDL_SYS_CDStop(SDL_CD *cdrom)
501{
502 u_char cdb[6];
503 struct scsi_user_cdb sus;
504
505 bzero(cdb, sizeof (cdb));
506 cdb[0] = 0x1b; /* stop */
507 cdb[1] = 1; /* immediate */
508 return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
509}
510
511/* Eject the CD-ROM */
512static int SDL_SYS_CDEject(SDL_CD *cdrom)
513{
514 u_char cdb[6];
515 struct scsi_user_cdb sus;
516
517 bzero(cdb, sizeof (cdb));
518 cdb[0] = 0x1b; /* stop */
519 cdb[1] = 1; /* immediate */
520 cdb[4] = 2; /* eject */
521 return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
522}
523
524/* Close the CD-ROM handle */
525static void SDL_SYS_CDClose(SDL_CD *cdrom)
526 {
527 close(cdrom->id);
528 }
529
530void SDL_SYS_CDQuit(void)
531{
532 int i;
533
534 if ( SDL_numcds > 0 ) {
535 for ( i=0; i<SDL_numcds; ++i ) {
536 SDL_free(SDL_cdlist[i]);
537 }
538 }
539 SDL_numcds = 0;
540}
541
542#endif /* SDL_CDROM_BSDI */
diff --git a/apps/plugins/sdl/src/cdrom/dc/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/dc/SDL_syscdrom.c
deleted file mode 100644
index 445ad7c25a..0000000000
--- a/apps/plugins/sdl/src/cdrom/dc/SDL_syscdrom.c
+++ /dev/null
@@ -1,167 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_DC
25
26/* Functions for system-level CD-ROM audio control */
27
28#include <dc/cdrom.h>
29#include <dc/spu.h>
30
31#include "SDL_cdrom.h"
32#include "../SDL_syscdrom.h"
33
34/* The system-dependent CD control functions */
35static const char *SDL_SYS_CDName(int drive);
36static int SDL_SYS_CDOpen(int drive);
37static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
38static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
39static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
40static int SDL_SYS_CDPause(SDL_CD *cdrom);
41static int SDL_SYS_CDResume(SDL_CD *cdrom);
42static int SDL_SYS_CDStop(SDL_CD *cdrom);
43static int SDL_SYS_CDEject(SDL_CD *cdrom);
44static void SDL_SYS_CDClose(SDL_CD *cdrom);
45
46
47int SDL_SYS_CDInit(void)
48{
49 /* Fill in our driver capabilities */
50 SDL_CDcaps.Name = SDL_SYS_CDName;
51 SDL_CDcaps.Open = SDL_SYS_CDOpen;
52 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
53 SDL_CDcaps.Status = SDL_SYS_CDStatus;
54 SDL_CDcaps.Play = SDL_SYS_CDPlay;
55 SDL_CDcaps.Pause = SDL_SYS_CDPause;
56 SDL_CDcaps.Resume = SDL_SYS_CDResume;
57 SDL_CDcaps.Stop = SDL_SYS_CDStop;
58 SDL_CDcaps.Eject = SDL_SYS_CDEject;
59 SDL_CDcaps.Close = SDL_SYS_CDClose;
60
61 return(0);
62}
63
64static const char *SDL_SYS_CDName(int drive)
65{
66 return "/cd";
67}
68
69static int SDL_SYS_CDOpen(int drive)
70{
71 return(drive);
72}
73
74#define TRACK_CDDA 0
75static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
76{
77 CDROM_TOC toc;
78 int ret,i;
79
80 ret = cdrom_read_toc(&toc,0);
81 if (ret!=ERR_OK) {
82 return -1;
83 }
84
85 cdrom->numtracks = TOC_TRACK(toc.last)-TOC_TRACK(toc.first)+1;
86 for(i=0;i<cdrom->numtracks;i++) {
87 unsigned long entry = toc.entry[i];
88 cdrom->track[i].id = i+1;
89 cdrom->track[i].type = (TOC_CTRL(toc.entry[i])==TRACK_CDDA)?SDL_AUDIO_TRACK:SDL_DATA_TRACK;
90 cdrom->track[i].offset = TOC_LBA(entry)-150;
91 cdrom->track[i].length = TOC_LBA((i+1<toc.last)?toc.entry[i+1]:toc.leadout_sector)-TOC_LBA(entry);
92 }
93
94 return 0;
95}
96
97/* Get CD-ROM status */
98static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
99{
100 int ret,dc_status,disc_type;
101
102 ret = cdrom_get_status(&dc_status,&disc_type);
103 if (ret!=ERR_OK) return CD_ERROR;
104
105 switch(dc_status) {
106// case CD_STATUS_BUSY:
107 case CD_STATUS_PAUSED:
108 return CD_PAUSED;
109 case CD_STATUS_STANDBY:
110 return CD_STOPPED;
111 case CD_STATUS_PLAYING:
112 return CD_PLAYING;
113// case CD_STATUS_SEEKING:
114// case CD_STATUS_SCANING:
115 case CD_STATUS_OPEN:
116 case CD_STATUS_NO_DISC:
117 return CD_TRAYEMPTY;
118 default:
119 return CD_ERROR;
120 }
121}
122
123/* Start play */
124static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
125{
126 int ret = cdrom_cdda_play(start-150,start-150+length,1,CDDA_SECTORS);
127 return ret==ERR_OK?0:-1;
128}
129
130/* Pause play */
131static int SDL_SYS_CDPause(SDL_CD *cdrom)
132{
133 int ret=cdrom_cdda_pause();
134 return ret==ERR_OK?0:-1;
135}
136
137/* Resume play */
138static int SDL_SYS_CDResume(SDL_CD *cdrom)
139{
140 int ret=cdrom_cdda_resume();
141 return ret==ERR_OK?0:-1;
142}
143
144/* Stop play */
145static int SDL_SYS_CDStop(SDL_CD *cdrom)
146{
147 int ret=cdrom_spin_down();
148 return ret==ERR_OK?0:-1;
149}
150
151/* Eject the CD-ROM */
152static int SDL_SYS_CDEject(SDL_CD *cdrom)
153{
154 return -1;
155}
156
157/* Close the CD-ROM handle */
158static void SDL_SYS_CDClose(SDL_CD *cdrom)
159{
160}
161
162void SDL_SYS_CDQuit(void)
163{
164
165}
166
167#endif /* SDL_CDROM_DC */
diff --git a/apps/plugins/sdl/src/cdrom/freebsd/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/freebsd/SDL_syscdrom.c
deleted file mode 100644
index 0260c9489f..0000000000
--- a/apps/plugins/sdl/src/cdrom/freebsd/SDL_syscdrom.c
+++ /dev/null
@@ -1,406 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_FREEBSD
25
26/* Functions for system-level CD-ROM audio control */
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <errno.h>
32#include <unistd.h>
33#include <sys/cdio.h>
34
35#include "SDL_cdrom.h"
36#include "../SDL_syscdrom.h"
37
38
39/* The maximum number of CD-ROM drives we'll detect */
40#define MAX_DRIVES 16
41
42/* A list of available CD-ROM drives */
43static char *SDL_cdlist[MAX_DRIVES];
44static dev_t SDL_cdmode[MAX_DRIVES];
45
46/* The system-dependent CD control functions */
47static const char *SDL_SYS_CDName(int drive);
48static int SDL_SYS_CDOpen(int drive);
49static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
50static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
51static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
52static int SDL_SYS_CDPause(SDL_CD *cdrom);
53static int SDL_SYS_CDResume(SDL_CD *cdrom);
54static int SDL_SYS_CDStop(SDL_CD *cdrom);
55static int SDL_SYS_CDEject(SDL_CD *cdrom);
56static void SDL_SYS_CDClose(SDL_CD *cdrom);
57
58/* Some ioctl() errno values which occur when the tray is empty */
59#define ERRNO_TRAYEMPTY(errno) \
60 ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL))
61
62/* Check a drive to see if it is a CD-ROM */
63static int CheckDrive(char *drive, struct stat *stbuf)
64{
65 int is_cd, cdfd;
66 struct ioc_read_subchannel info;
67
68 /* If it doesn't exist, return -1 */
69 if ( stat(drive, stbuf) < 0 ) {
70 return(-1);
71 }
72
73 /* If it does exist, verify that it's an available CD-ROM */
74 is_cd = 0;
75 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) {
76 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
77 if ( cdfd >= 0 ) {
78 info.address_format = CD_MSF_FORMAT;
79 info.data_format = CD_CURRENT_POSITION;
80 info.data_len = 0;
81 info.data = NULL;
82 /* Under Linux, EIO occurs when a disk is not present.
83 This isn't 100% reliable, so we use the USE_MNTENT
84 code above instead.
85 */
86 if ( (ioctl(cdfd, CDIOCREADSUBCHANNEL, &info) == 0) ||
87 ERRNO_TRAYEMPTY(errno) ) {
88 is_cd = 1;
89 }
90 close(cdfd);
91 }
92 }
93 return(is_cd);
94}
95
96/* Add a CD-ROM drive to our list of valid drives */
97static void AddDrive(char *drive, struct stat *stbuf)
98{
99 int i;
100
101 if ( SDL_numcds < MAX_DRIVES ) {
102 /* Check to make sure it's not already in our list.
103 This can happen when we see a drive via symbolic link.
104 */
105 for ( i=0; i<SDL_numcds; ++i ) {
106 if ( stbuf->st_rdev == SDL_cdmode[i] ) {
107#ifdef DEBUG_CDROM
108 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
109#endif
110 return;
111 }
112 }
113
114 /* Add this drive to our list */
115 i = SDL_numcds;
116 SDL_cdlist[i] = SDL_strdup(drive);
117 if ( SDL_cdlist[i] == NULL ) {
118 SDL_OutOfMemory();
119 return;
120 }
121 SDL_cdmode[i] = stbuf->st_rdev;
122 ++SDL_numcds;
123#ifdef DEBUG_CDROM
124 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
125#endif
126 }
127}
128
129int SDL_SYS_CDInit(void)
130{
131 /* checklist: /dev/cdrom,/dev/cd?c /dev/acd?c
132 /dev/matcd?c /dev/mcd?c /dev/scd?c */
133 static char *checklist[] = {
134 "cdrom", "?0 cd?", "?0 acd?", "?0 matcd?", "?0 mcd?", "?0 scd?",NULL
135 };
136 char *SDLcdrom;
137 int i, j, exists;
138 char drive[32];
139 struct stat stbuf;
140
141 /* Fill in our driver capabilities */
142 SDL_CDcaps.Name = SDL_SYS_CDName;
143 SDL_CDcaps.Open = SDL_SYS_CDOpen;
144 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
145 SDL_CDcaps.Status = SDL_SYS_CDStatus;
146 SDL_CDcaps.Play = SDL_SYS_CDPlay;
147 SDL_CDcaps.Pause = SDL_SYS_CDPause;
148 SDL_CDcaps.Resume = SDL_SYS_CDResume;
149 SDL_CDcaps.Stop = SDL_SYS_CDStop;
150 SDL_CDcaps.Eject = SDL_SYS_CDEject;
151 SDL_CDcaps.Close = SDL_SYS_CDClose;
152
153 /* Look in the environment for our CD-ROM drive list */
154 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
155 if ( SDLcdrom != NULL ) {
156 char *cdpath, *delim;
157 size_t len = SDL_strlen(SDLcdrom)+1;
158 cdpath = SDL_stack_alloc(char, len);
159 if ( cdpath != NULL ) {
160 SDL_strlcpy(cdpath, SDLcdrom, len);
161 SDLcdrom = cdpath;
162 do {
163 delim = SDL_strchr(SDLcdrom, ':');
164 if ( delim ) {
165 *delim++ = '\0';
166 }
167 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
168 AddDrive(SDLcdrom, &stbuf);
169 }
170 if ( delim ) {
171 SDLcdrom = delim;
172 } else {
173 SDLcdrom = NULL;
174 }
175 } while ( SDLcdrom );
176 SDL_stack_free(cdpath);
177 }
178
179 /* If we found our drives, there's nothing left to do */
180 if ( SDL_numcds > 0 ) {
181 return(0);
182 }
183 }
184
185 /* Scan the system for CD-ROM drives */
186 for ( i=0; checklist[i]; ++i ) {
187 if ( checklist[i][0] == '?' ) {
188 char *insert;
189 exists = 1;
190 for ( j=checklist[i][1]; exists; ++j ) {
191 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc", &checklist[i][3]);
192 insert = SDL_strchr(drive, '?');
193 if ( insert != NULL ) {
194 *insert = j;
195 }
196 switch (CheckDrive(drive, &stbuf)) {
197 /* Drive exists and is a CD-ROM */
198 case 1:
199 AddDrive(drive, &stbuf);
200 break;
201 /* Drive exists, but isn't a CD-ROM */
202 case 0:
203 break;
204 /* Drive doesn't exist */
205 case -1:
206 exists = 0;
207 break;
208 }
209 }
210 } else {
211 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
212 if ( CheckDrive(drive, &stbuf) > 0 ) {
213 AddDrive(drive, &stbuf);
214 }
215 }
216 }
217 return(0);
218}
219
220/* General ioctl() CD-ROM command function */
221static int SDL_SYS_CDioctl(int id, int command, void *arg)
222{
223 int retval;
224
225 retval = ioctl(id, command, arg);
226 if ( retval < 0 ) {
227 SDL_SetError("ioctl() error: %s", strerror(errno));
228 }
229 return(retval);
230}
231
232static const char *SDL_SYS_CDName(int drive)
233{
234 return(SDL_cdlist[drive]);
235}
236
237static int SDL_SYS_CDOpen(int drive)
238{
239 return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0));
240}
241
242static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
243{
244 struct ioc_toc_header toc;
245 int i, okay;
246 struct ioc_read_toc_entry entry;
247 struct cd_toc_entry data;
248
249 okay = 0;
250 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) {
251 cdrom->numtracks = toc.ending_track-toc.starting_track+1;
252 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
253 cdrom->numtracks = SDL_MAX_TRACKS;
254 }
255 /* Read all the track TOC entries */
256 for ( i=0; i<=cdrom->numtracks; ++i ) {
257 if ( i == cdrom->numtracks ) {
258 cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */
259 } else {
260 cdrom->track[i].id = toc.starting_track+i;
261 }
262 entry.starting_track = cdrom->track[i].id;
263 entry.address_format = CD_MSF_FORMAT;
264 entry.data_len = sizeof(data);
265 entry.data = &data;
266 if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS,
267 &entry) < 0 ) {
268 break;
269 } else {
270 cdrom->track[i].type = data.control;
271 cdrom->track[i].offset = MSF_TO_FRAMES(
272 data.addr.msf.minute,
273 data.addr.msf.second,
274 data.addr.msf.frame);
275 cdrom->track[i].length = 0;
276 if ( i > 0 ) {
277 cdrom->track[i-1].length =
278 cdrom->track[i].offset-
279 cdrom->track[i-1].offset;
280 }
281 }
282 }
283 if ( i == (cdrom->numtracks+1) ) {
284 okay = 1;
285 }
286 }
287 return(okay ? 0 : -1);
288}
289
290/* Get CD-ROM status */
291static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
292{
293 CDstatus status;
294 struct ioc_toc_header toc;
295 struct ioc_read_subchannel info;
296 struct cd_sub_channel_info data;
297
298 info.address_format = CD_MSF_FORMAT;
299 info.data_format = CD_CURRENT_POSITION;
300 info.track = 0;
301 info.data_len = sizeof(data);
302 info.data = &data;
303 if ( ioctl(cdrom->id, CDIOCREADSUBCHANNEL, &info) < 0 ) {
304 if ( ERRNO_TRAYEMPTY(errno) ) {
305 status = CD_TRAYEMPTY;
306 } else {
307 status = CD_ERROR;
308 }
309 } else {
310 switch (data.header.audio_status) {
311 case CD_AS_AUDIO_INVALID:
312 case CD_AS_NO_STATUS:
313 /* Try to determine if there's a CD available */
314 if (ioctl(cdrom->id,CDIOREADTOCHEADER,&toc)==0)
315 status = CD_STOPPED;
316 else
317 status = CD_TRAYEMPTY;
318 break;
319 case CD_AS_PLAY_COMPLETED:
320 status = CD_STOPPED;
321 break;
322 case CD_AS_PLAY_IN_PROGRESS:
323 status = CD_PLAYING;
324 break;
325 case CD_AS_PLAY_PAUSED:
326 status = CD_PAUSED;
327 break;
328 default:
329 status = CD_ERROR;
330 break;
331 }
332 }
333 if ( position ) {
334 if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
335 *position = MSF_TO_FRAMES(
336 data.what.position.absaddr.msf.minute,
337 data.what.position.absaddr.msf.second,
338 data.what.position.absaddr.msf.frame);
339 } else {
340 *position = 0;
341 }
342 }
343 return(status);
344}
345
346/* Start play */
347static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
348{
349 struct ioc_play_msf playtime;
350
351 FRAMES_TO_MSF(start,
352 &playtime.start_m, &playtime.start_s, &playtime.start_f);
353 FRAMES_TO_MSF(start+length,
354 &playtime.end_m, &playtime.end_s, &playtime.end_f);
355#ifdef DEBUG_CDROM
356 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
357 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
358 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
359#endif
360 ioctl(cdrom->id, CDIOCSTART, 0);
361 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPLAYMSF, &playtime));
362}
363
364/* Pause play */
365static int SDL_SYS_CDPause(SDL_CD *cdrom)
366{
367 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0));
368}
369
370/* Resume play */
371static int SDL_SYS_CDResume(SDL_CD *cdrom)
372{
373 return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0));
374}
375
376/* Stop play */
377static int SDL_SYS_CDStop(SDL_CD *cdrom)
378{
379 return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0));
380}
381
382/* Eject the CD-ROM */
383static int SDL_SYS_CDEject(SDL_CD *cdrom)
384{
385 return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0));
386}
387
388/* Close the CD-ROM handle */
389static void SDL_SYS_CDClose(SDL_CD *cdrom)
390{
391 close(cdrom->id);
392}
393
394void SDL_SYS_CDQuit(void)
395{
396 int i;
397
398 if ( SDL_numcds > 0 ) {
399 for ( i=0; i<SDL_numcds; ++i ) {
400 SDL_free(SDL_cdlist[i]);
401 }
402 SDL_numcds = 0;
403 }
404}
405
406#endif /* SDL_CDROM_FREEBSD */
diff --git a/apps/plugins/sdl/src/cdrom/linux/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/linux/SDL_syscdrom.c
deleted file mode 100644
index 68040575b5..0000000000
--- a/apps/plugins/sdl/src/cdrom/linux/SDL_syscdrom.c
+++ /dev/null
@@ -1,564 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_LINUX
25
26/* Functions for system-level CD-ROM audio control */
27
28#include <string.h> /* For strerror() */
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <sys/ioctl.h>
32#include <fcntl.h>
33#include <errno.h>
34#include <unistd.h>
35#ifdef __LINUX__
36#ifdef HAVE_LINUX_VERSION_H
37/* linux 2.6.9 workaround */
38#include <linux/version.h>
39#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,9)
40#include <asm/types.h>
41#define __le64 __u64
42#define __le32 __u32
43#define __le16 __u16
44#define __be64 __u64
45#define __be32 __u32
46#define __be16 __u16
47#endif /* linux 2.6.9 workaround */
48#endif /* HAVE_LINUX_VERSION_H */
49#include <linux/cdrom.h>
50#endif
51#ifdef __SVR4
52#include <sys/cdio.h>
53#endif
54
55/* Define this to use the alternative getmntent() code */
56#ifndef __SVR4
57#define USE_MNTENT
58#endif
59
60#ifdef USE_MNTENT
61#if defined(__USLC__)
62#include <sys/mntent.h>
63#else
64#include <mntent.h>
65#endif
66
67#ifndef _PATH_MNTTAB
68#ifdef MNTTAB
69#define _PATH_MNTTAB MNTTAB
70#else
71#define _PATH_MNTTAB "/etc/fstab"
72#endif
73#endif /* !_PATH_MNTTAB */
74
75#ifndef _PATH_MOUNTED
76#define _PATH_MOUNTED "/etc/mtab"
77#endif /* !_PATH_MOUNTED */
78
79#ifndef MNTTYPE_CDROM
80#define MNTTYPE_CDROM "iso9660"
81#endif
82#ifndef MNTTYPE_SUPER
83#define MNTTYPE_SUPER "supermount"
84#endif
85#endif /* USE_MNTENT */
86
87#include "SDL_cdrom.h"
88#include "../SDL_syscdrom.h"
89
90
91/* The maximum number of CD-ROM drives we'll detect */
92#define MAX_DRIVES 16
93
94/* A list of available CD-ROM drives */
95static char *SDL_cdlist[MAX_DRIVES];
96static dev_t SDL_cdmode[MAX_DRIVES];
97
98/* The system-dependent CD control functions */
99static const char *SDL_SYS_CDName(int drive);
100static int SDL_SYS_CDOpen(int drive);
101static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
102static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
103static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
104static int SDL_SYS_CDPause(SDL_CD *cdrom);
105static int SDL_SYS_CDResume(SDL_CD *cdrom);
106static int SDL_SYS_CDStop(SDL_CD *cdrom);
107static int SDL_SYS_CDEject(SDL_CD *cdrom);
108static void SDL_SYS_CDClose(SDL_CD *cdrom);
109
110/* Some ioctl() errno values which occur when the tray is empty */
111#ifndef ENOMEDIUM
112#define ENOMEDIUM ENOENT
113#endif
114#define ERRNO_TRAYEMPTY(errno) \
115 ((errno == EIO) || (errno == ENOENT) || \
116 (errno == EINVAL) || (errno == ENOMEDIUM))
117
118/* Check a drive to see if it is a CD-ROM */
119static int CheckDrive(char *drive, char *mnttype, struct stat *stbuf)
120{
121 int is_cd, cdfd;
122 struct cdrom_subchnl info;
123
124 /* If it doesn't exist, return -1 */
125 if ( stat(drive, stbuf) < 0 ) {
126 return(-1);
127 }
128
129 /* If it does exist, verify that it's an available CD-ROM */
130 is_cd = 0;
131 if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) {
132 cdfd = open(drive, (O_RDONLY|O_NONBLOCK), 0);
133 if ( cdfd >= 0 ) {
134 info.cdsc_format = CDROM_MSF;
135 /* Under Linux, EIO occurs when a disk is not present.
136 */
137 if ( (ioctl(cdfd, CDROMSUBCHNL, &info) == 0) ||
138 ERRNO_TRAYEMPTY(errno) ) {
139 is_cd = 1;
140 }
141 close(cdfd);
142 }
143#ifdef USE_MNTENT
144 /* Even if we can't read it, it might be mounted */
145 else if ( mnttype && (SDL_strcmp(mnttype, MNTTYPE_CDROM) == 0) ) {
146 is_cd = 1;
147 }
148#endif
149 }
150 return(is_cd);
151}
152
153/* Add a CD-ROM drive to our list of valid drives */
154static void AddDrive(char *drive, struct stat *stbuf)
155{
156 int i;
157
158 if ( SDL_numcds < MAX_DRIVES ) {
159 /* Check to make sure it's not already in our list.
160 This can happen when we see a drive via symbolic link.
161 */
162 for ( i=0; i<SDL_numcds; ++i ) {
163 if ( stbuf->st_rdev == SDL_cdmode[i] ) {
164#ifdef DEBUG_CDROM
165 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
166#endif
167 return;
168 }
169 }
170
171 /* Add this drive to our list */
172 i = SDL_numcds;
173 SDL_cdlist[i] = SDL_strdup(drive);
174 if ( SDL_cdlist[i] == NULL ) {
175 SDL_OutOfMemory();
176 return;
177 }
178 SDL_cdmode[i] = stbuf->st_rdev;
179 ++SDL_numcds;
180#ifdef DEBUG_CDROM
181 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
182#endif
183 }
184}
185
186#ifdef USE_MNTENT
187static void CheckMounts(const char *mtab)
188{
189 FILE *mntfp;
190 struct mntent *mntent;
191 struct stat stbuf;
192
193 mntfp = setmntent(mtab, "r");
194 if ( mntfp != NULL ) {
195 char *tmp;
196 char *mnt_type;
197 size_t mnt_type_len;
198 char *mnt_dev;
199 size_t mnt_dev_len;
200
201 while ( (mntent=getmntent(mntfp)) != NULL ) {
202 mnt_type_len = SDL_strlen(mntent->mnt_type) + 1;
203 mnt_type = SDL_stack_alloc(char, mnt_type_len);
204 if (mnt_type == NULL)
205 continue; /* maybe you'll get lucky next time. */
206
207 mnt_dev_len = SDL_strlen(mntent->mnt_fsname) + 1;
208 mnt_dev = SDL_stack_alloc(char, mnt_dev_len);
209 if (mnt_dev == NULL) {
210 SDL_stack_free(mnt_type);
211 continue;
212 }
213
214 SDL_strlcpy(mnt_type, mntent->mnt_type, mnt_type_len);
215 SDL_strlcpy(mnt_dev, mntent->mnt_fsname, mnt_dev_len);
216
217 /* Handle "supermount" filesystem mounts */
218 if ( SDL_strcmp(mnt_type, MNTTYPE_SUPER) == 0 ) {
219 tmp = SDL_strstr(mntent->mnt_opts, "fs=");
220 if ( tmp ) {
221 SDL_stack_free(mnt_type);
222 mnt_type = SDL_strdup(tmp + SDL_strlen("fs="));
223 if ( mnt_type ) {
224 tmp = SDL_strchr(mnt_type, ',');
225 if ( tmp ) {
226 *tmp = '\0';
227 }
228 }
229 }
230 tmp = SDL_strstr(mntent->mnt_opts, "dev=");
231 if ( tmp ) {
232 SDL_stack_free(mnt_dev);
233 mnt_dev = SDL_strdup(tmp + SDL_strlen("dev="));
234 if ( mnt_dev ) {
235 tmp = SDL_strchr(mnt_dev, ',');
236 if ( tmp ) {
237 *tmp = '\0';
238 }
239 }
240 }
241 }
242 if ( SDL_strcmp(mnt_type, MNTTYPE_CDROM) == 0 ) {
243#ifdef DEBUG_CDROM
244 fprintf(stderr, "Checking mount path from %s: %s mounted on %s of %s\n",
245 mtab, mnt_dev, mntent->mnt_dir, mnt_type);
246#endif
247 if (CheckDrive(mnt_dev, mnt_type, &stbuf) > 0) {
248 AddDrive(mnt_dev, &stbuf);
249 }
250 }
251 SDL_stack_free(mnt_dev);
252 SDL_stack_free(mnt_type);
253 }
254 endmntent(mntfp);
255 }
256}
257#endif /* USE_MNTENT */
258
259int SDL_SYS_CDInit(void)
260{
261 /* checklist: /dev/cdrom, /dev/hd?, /dev/scd? /dev/sr? */
262 static char *checklist[] = {
263 "cdrom", "?a hd?", "?0 scd?", "?0 sr?", NULL
264 };
265 char *SDLcdrom;
266 int i, j, exists;
267 char drive[32];
268 struct stat stbuf;
269
270 /* Fill in our driver capabilities */
271 SDL_CDcaps.Name = SDL_SYS_CDName;
272 SDL_CDcaps.Open = SDL_SYS_CDOpen;
273 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
274 SDL_CDcaps.Status = SDL_SYS_CDStatus;
275 SDL_CDcaps.Play = SDL_SYS_CDPlay;
276 SDL_CDcaps.Pause = SDL_SYS_CDPause;
277 SDL_CDcaps.Resume = SDL_SYS_CDResume;
278 SDL_CDcaps.Stop = SDL_SYS_CDStop;
279 SDL_CDcaps.Eject = SDL_SYS_CDEject;
280 SDL_CDcaps.Close = SDL_SYS_CDClose;
281
282 /* Look in the environment for our CD-ROM drive list */
283 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
284 if ( SDLcdrom != NULL ) {
285 char *cdpath, *delim;
286 size_t len = SDL_strlen(SDLcdrom)+1;
287 cdpath = SDL_stack_alloc(char, len);
288 if ( cdpath != NULL ) {
289 SDL_strlcpy(cdpath, SDLcdrom, len);
290 SDLcdrom = cdpath;
291 do {
292 delim = SDL_strchr(SDLcdrom, ':');
293 if ( delim ) {
294 *delim++ = '\0';
295 }
296#ifdef DEBUG_CDROM
297 fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom);
298#endif
299 if ( CheckDrive(SDLcdrom, NULL, &stbuf) > 0 ) {
300 AddDrive(SDLcdrom, &stbuf);
301 }
302 if ( delim ) {
303 SDLcdrom = delim;
304 } else {
305 SDLcdrom = NULL;
306 }
307 } while ( SDLcdrom );
308 SDL_stack_free(cdpath);
309 }
310
311 /* If we found our drives, there's nothing left to do */
312 if ( SDL_numcds > 0 ) {
313 return(0);
314 }
315 }
316
317#ifdef USE_MNTENT
318 /* Check /dev/cdrom first :-) */
319 if (CheckDrive("/dev/cdrom", NULL, &stbuf) > 0) {
320 AddDrive("/dev/cdrom", &stbuf);
321 }
322
323 /* Now check the currently mounted CD drives */
324 CheckMounts(_PATH_MOUNTED);
325
326 /* Finally check possible mountable drives in /etc/fstab */
327 CheckMounts(_PATH_MNTTAB);
328
329 /* If we found our drives, there's nothing left to do */
330 if ( SDL_numcds > 0 ) {
331 return(0);
332 }
333#endif /* USE_MNTENT */
334
335 /* Scan the system for CD-ROM drives.
336 Not always 100% reliable, so use the USE_MNTENT code above first.
337 */
338 for ( i=0; checklist[i]; ++i ) {
339 if ( checklist[i][0] == '?' ) {
340 char *insert;
341 exists = 1;
342 for ( j=checklist[i][1]; exists; ++j ) {
343 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]);
344 insert = SDL_strchr(drive, '?');
345 if ( insert != NULL ) {
346 *insert = j;
347 }
348#ifdef DEBUG_CDROM
349 fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive);
350#endif
351 switch (CheckDrive(drive, NULL, &stbuf)) {
352 /* Drive exists and is a CD-ROM */
353 case 1:
354 AddDrive(drive, &stbuf);
355 break;
356 /* Drive exists, but isn't a CD-ROM */
357 case 0:
358 break;
359 /* Drive doesn't exist */
360 case -1:
361 exists = 0;
362 break;
363 }
364 }
365 } else {
366 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
367#ifdef DEBUG_CDROM
368 fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive);
369#endif
370 if ( CheckDrive(drive, NULL, &stbuf) > 0 ) {
371 AddDrive(drive, &stbuf);
372 }
373 }
374 }
375 return(0);
376}
377
378/* General ioctl() CD-ROM command function */
379static int SDL_SYS_CDioctl(int id, int command, void *arg)
380{
381 int retval;
382
383 retval = ioctl(id, command, arg);
384 if ( retval < 0 ) {
385 SDL_SetError("ioctl() error: %s", strerror(errno));
386 }
387 return(retval);
388}
389
390static const char *SDL_SYS_CDName(int drive)
391{
392 return(SDL_cdlist[drive]);
393}
394
395static int SDL_SYS_CDOpen(int drive)
396{
397 return(open(SDL_cdlist[drive], (O_RDONLY|O_NONBLOCK), 0));
398}
399
400static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
401{
402 struct cdrom_tochdr toc;
403 int i, okay;
404 struct cdrom_tocentry entry;
405
406 okay = 0;
407 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) == 0 ) {
408 cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1;
409 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
410 cdrom->numtracks = SDL_MAX_TRACKS;
411 }
412 /* Read all the track TOC entries */
413 for ( i=0; i<=cdrom->numtracks; ++i ) {
414 if ( i == cdrom->numtracks ) {
415 cdrom->track[i].id = CDROM_LEADOUT;
416 } else {
417 cdrom->track[i].id = toc.cdth_trk0+i;
418 }
419 entry.cdte_track = cdrom->track[i].id;
420 entry.cdte_format = CDROM_MSF;
421 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY,
422 &entry) < 0 ) {
423 break;
424 } else {
425 if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) {
426 cdrom->track[i].type = SDL_DATA_TRACK;
427 } else {
428 cdrom->track[i].type = SDL_AUDIO_TRACK;
429 }
430 cdrom->track[i].offset = MSF_TO_FRAMES(
431 entry.cdte_addr.msf.minute,
432 entry.cdte_addr.msf.second,
433 entry.cdte_addr.msf.frame);
434 cdrom->track[i].length = 0;
435 if ( i > 0 ) {
436 cdrom->track[i-1].length =
437 cdrom->track[i].offset-
438 cdrom->track[i-1].offset;
439 }
440 }
441 }
442 if ( i == (cdrom->numtracks+1) ) {
443 okay = 1;
444 }
445 }
446 return(okay ? 0 : -1);
447}
448
449/* Get CD-ROM status */
450static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
451{
452 CDstatus status;
453 struct cdrom_tochdr toc;
454 struct cdrom_subchnl info;
455
456 info.cdsc_format = CDROM_MSF;
457 if ( ioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) {
458 if ( ERRNO_TRAYEMPTY(errno) ) {
459 status = CD_TRAYEMPTY;
460 } else {
461 status = CD_ERROR;
462 }
463 } else {
464 switch (info.cdsc_audiostatus) {
465 case CDROM_AUDIO_INVALID:
466 case CDROM_AUDIO_NO_STATUS:
467 /* Try to determine if there's a CD available */
468 if (ioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0)
469 status = CD_STOPPED;
470 else
471 status = CD_TRAYEMPTY;
472 break;
473 case CDROM_AUDIO_COMPLETED:
474 status = CD_STOPPED;
475 break;
476 case CDROM_AUDIO_PLAY:
477 status = CD_PLAYING;
478 break;
479 case CDROM_AUDIO_PAUSED:
480 /* Workaround buggy CD-ROM drive */
481 if ( info.cdsc_trk == CDROM_LEADOUT ) {
482 status = CD_STOPPED;
483 } else {
484 status = CD_PAUSED;
485 }
486 break;
487 default:
488 status = CD_ERROR;
489 break;
490 }
491 }
492 if ( position ) {
493 if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
494 *position = MSF_TO_FRAMES(
495 info.cdsc_absaddr.msf.minute,
496 info.cdsc_absaddr.msf.second,
497 info.cdsc_absaddr.msf.frame);
498 } else {
499 *position = 0;
500 }
501 }
502 return(status);
503}
504
505/* Start play */
506static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
507{
508 struct cdrom_msf playtime;
509
510 FRAMES_TO_MSF(start,
511 &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0);
512 FRAMES_TO_MSF(start+length,
513 &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1);
514#ifdef DEBUG_CDROM
515 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
516 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
517 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
518#endif
519 return(SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime));
520}
521
522/* Pause play */
523static int SDL_SYS_CDPause(SDL_CD *cdrom)
524{
525 return(SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0));
526}
527
528/* Resume play */
529static int SDL_SYS_CDResume(SDL_CD *cdrom)
530{
531 return(SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0));
532}
533
534/* Stop play */
535static int SDL_SYS_CDStop(SDL_CD *cdrom)
536{
537 return(SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0));
538}
539
540/* Eject the CD-ROM */
541static int SDL_SYS_CDEject(SDL_CD *cdrom)
542{
543 return(SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0));
544}
545
546/* Close the CD-ROM handle */
547static void SDL_SYS_CDClose(SDL_CD *cdrom)
548{
549 close(cdrom->id);
550}
551
552void SDL_SYS_CDQuit(void)
553{
554 int i;
555
556 if ( SDL_numcds > 0 ) {
557 for ( i=0; i<SDL_numcds; ++i ) {
558 SDL_free(SDL_cdlist[i]);
559 }
560 SDL_numcds = 0;
561 }
562}
563
564#endif /* SDL_CDROM_LINUX */
diff --git a/apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom.c
deleted file mode 100644
index 10a202544e..0000000000
--- a/apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom.c
+++ /dev/null
@@ -1,525 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_MACOS
25
26/* MacOS functions for system-level CD-ROM audio control */
27
28#include <Devices.h>
29#include <Files.h>
30#include <LowMem.h> /* Use entry table macros, not functions in InterfaceLib */
31
32#include "SDL_cdrom.h"
33#include "../SDL_syscdrom.h"
34#include "SDL_syscdrom_c.h"
35
36/* Added by Matt Slot */
37#if !defined(LMGetUnitTableEntryCount)
38 #define LMGetUnitTableEntryCount() *(short *)0x01D2
39#endif
40
41/* The maximum number of CD-ROM drives we'll detect */
42#define MAX_DRIVES 26
43
44/* A list of available CD-ROM drives */
45static long SDL_cdversion = 0;
46static struct {
47 short dRefNum;
48 short driveNum;
49 long frames;
50 char name[256];
51 Boolean hasAudio;
52 } SDL_cdlist[MAX_DRIVES];
53static StringPtr gDriverName = "\p.AppleCD";
54
55/* The system-dependent CD control functions */
56static const char *SDL_SYS_CDName(int drive);
57static int SDL_SYS_CDOpen(int drive);
58static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
59static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
60static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
61static int SDL_SYS_CDPause(SDL_CD *cdrom);
62static int SDL_SYS_CDResume(SDL_CD *cdrom);
63static int SDL_SYS_CDStop(SDL_CD *cdrom);
64static int SDL_SYS_CDEject(SDL_CD *cdrom);
65static void SDL_SYS_CDClose(SDL_CD *cdrom);
66
67static short SDL_SYS_ShortToBCD(short value)
68{
69 return((value % 10) + (value / 10) * 0x10); /* Convert value to BCD */
70}
71
72static short SDL_SYS_BCDToShort(short value)
73{
74 return((value % 0x10) + (value / 0x10) * 10); /* Convert value from BCD */
75}
76
77int SDL_SYS_CDInit(void)
78{
79 SInt16 dRefNum = 0;
80 SInt16 first, last;
81
82 SDL_numcds = 0;
83
84 /* Check that the software is available */
85 if (Gestalt(kGestaltAudioCDSelector, &SDL_cdversion) ||
86 !SDL_cdversion) return(0);
87
88 /* Fill in our driver capabilities */
89 SDL_CDcaps.Name = SDL_SYS_CDName;
90 SDL_CDcaps.Open = SDL_SYS_CDOpen;
91 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
92 SDL_CDcaps.Status = SDL_SYS_CDStatus;
93 SDL_CDcaps.Play = SDL_SYS_CDPlay;
94 SDL_CDcaps.Pause = SDL_SYS_CDPause;
95 SDL_CDcaps.Resume = SDL_SYS_CDResume;
96 SDL_CDcaps.Stop = SDL_SYS_CDStop;
97 SDL_CDcaps.Eject = SDL_SYS_CDEject;
98 SDL_CDcaps.Close = SDL_SYS_CDClose;
99
100 /* Walk the list, count each AudioCD driver, and save the refnums */
101 first = -1;
102 last = 0 - LMGetUnitTableEntryCount();
103 for(dRefNum = first; dRefNum >= last; dRefNum--) {
104 Str255 driverName;
105 StringPtr namePtr;
106 DCtlHandle deviceEntry;
107
108 deviceEntry = GetDCtlEntry(dRefNum);
109 if (! deviceEntry) continue;
110
111 /* Is this an .AppleCD ? */
112 namePtr = (*deviceEntry)->dCtlFlags & (1L << dRAMBased) ?
113 ((StringPtr) ((DCtlPtr) deviceEntry)->dCtlDriver + 18) :
114 ((StringPtr) (*deviceEntry)->dCtlDriver + 18);
115 BlockMoveData(namePtr, driverName, namePtr[0]+1);
116 if (driverName[0] > gDriverName[0]) driverName[0] = gDriverName[0];
117 if (! EqualString(driverName, gDriverName, false, false)) continue;
118
119 /* Record the basic info for each drive */
120 SDL_cdlist[SDL_numcds].dRefNum = dRefNum;
121 BlockMoveData(namePtr + 1, SDL_cdlist[SDL_numcds].name, namePtr[0]);
122 SDL_cdlist[SDL_numcds].name[namePtr[0]] = 0;
123 SDL_cdlist[SDL_numcds].hasAudio = false;
124 SDL_numcds++;
125 }
126 return(0);
127}
128
129static const char *SDL_SYS_CDName(int drive)
130{
131 return(SDL_cdlist[drive].name);
132}
133
134static int get_drivenum(int drive)
135{
136 QHdr *driveQ = GetDrvQHdr();
137 DrvQEl *driveElem;
138
139 /* Update the drive number */
140 SDL_cdlist[drive].driveNum = 0;
141 if ( driveQ->qTail ) {
142 driveQ->qTail->qLink = 0;
143 }
144 for ( driveElem=(DrvQEl *)driveQ->qHead; driveElem;
145 driveElem = (DrvQEl *)driveElem->qLink ) {
146 if ( driveElem->dQRefNum == SDL_cdlist[drive].dRefNum ) {
147 SDL_cdlist[drive].driveNum = driveElem->dQDrive;
148 break;
149 }
150 }
151 return(SDL_cdlist[drive].driveNum);
152}
153
154static int SDL_SYS_CDOpen(int drive)
155{
156 return(drive);
157}
158
159static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
160{
161 CDCntrlParam cdpb;
162 CDTrackData tracks[SDL_MAX_TRACKS];
163 long i, leadout;
164
165 /* Get the number of tracks on the CD by examining the TOC */
166 SDL_memset(&cdpb, 0, sizeof(cdpb));
167 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
168 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
169 cdpb.csCode = kReadTOC;
170 cdpb.csParam.words[0] = kGetTrackRange;
171 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
172 SDL_SetError("PBControlSync() failed");
173 return(-1);
174 }
175
176 cdrom->numtracks =
177 SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) -
178 SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1;
179 if ( cdrom->numtracks > SDL_MAX_TRACKS )
180 cdrom->numtracks = SDL_MAX_TRACKS;
181 cdrom->status = CD_STOPPED;
182 cdrom->cur_track = 0; /* Apparently these are set elsewhere */
183 cdrom->cur_frame = 0; /* Apparently these are set elsewhere */
184
185
186 /* Get the lead out area of the CD by examining the TOC */
187 SDL_memset(&cdpb, 0, sizeof(cdpb));
188 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
189 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
190 cdpb.csCode = kReadTOC;
191 cdpb.csParam.words[0] = kGetLeadOutArea;
192 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
193 SDL_SetError("PBControlSync() failed");
194 return(-1);
195 }
196
197 leadout = MSF_TO_FRAMES(
198 SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]),
199 SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]),
200 SDL_SYS_BCDToShort(cdpb.csParam.bytes[2]));
201
202 /* Get an array of track locations by examining the TOC */
203 SDL_memset(tracks, 0, sizeof(tracks));
204 SDL_memset(&cdpb, 0, sizeof(cdpb));
205 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
206 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
207 cdpb.csCode = kReadTOC;
208 cdpb.csParam.words[0] = kGetTrackEntries; /* Type of Query */
209 * ((long *) (cdpb.csParam.words+1)) = (long) tracks;
210 cdpb.csParam.words[3] = cdrom->numtracks * sizeof(tracks[0]);
211 * ((char *) (cdpb.csParam.words+4)) = 1; /* First track */
212 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
213 SDL_SetError("PBControlSync() failed");
214 return(-1);
215 }
216
217 /* Read all the track TOC entries */
218 SDL_cdlist[cdrom->id].hasAudio = false;
219 for ( i=0; i<cdrom->numtracks; ++i )
220 {
221 cdrom->track[i].id = i+1;
222 if (tracks[i].entry.control & kDataTrackMask)
223 cdrom->track[i].type = SDL_DATA_TRACK;
224 else
225 {
226 cdrom->track[i].type = SDL_AUDIO_TRACK;
227 SDL_cdlist[SDL_numcds].hasAudio = true;
228 }
229
230 cdrom->track[i].offset = MSF_TO_FRAMES(
231 SDL_SYS_BCDToShort(tracks[i].entry.min),
232 SDL_SYS_BCDToShort(tracks[i].entry.min),
233 SDL_SYS_BCDToShort(tracks[i].entry.frame));
234 cdrom->track[i].length = MSF_TO_FRAMES(
235 SDL_SYS_BCDToShort(tracks[i+1].entry.min),
236 SDL_SYS_BCDToShort(tracks[i+1].entry.min),
237 SDL_SYS_BCDToShort(tracks[i+1].entry.frame)) -
238 cdrom->track[i].offset;
239 }
240
241 /* Apparently SDL wants a fake last entry */
242 cdrom->track[i].offset = leadout;
243 cdrom->track[i].length = 0;
244
245 return(0);
246}
247
248/* Get CD-ROM status */
249static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
250{
251 CDCntrlParam cdpb;
252 CDstatus status = CD_ERROR;
253 Boolean spinning = false;
254
255 if (position) *position = 0;
256
257 /* Get the number of tracks on the CD by examining the TOC */
258 if ( ! get_drivenum(cdrom->id) ) {
259 return(CD_TRAYEMPTY);
260 }
261 SDL_memset(&cdpb, 0, sizeof(cdpb));
262 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
263 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
264 cdpb.csCode = kReadTOC;
265 cdpb.csParam.words[0] = kGetTrackRange;
266 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
267 SDL_SetError("PBControlSync() failed");
268 return(CD_ERROR);
269 }
270
271 cdrom->numtracks =
272 SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) -
273 SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1;
274 if ( cdrom->numtracks > SDL_MAX_TRACKS )
275 cdrom->numtracks = SDL_MAX_TRACKS;
276 cdrom->cur_track = 0; /* Apparently these are set elsewhere */
277 cdrom->cur_frame = 0; /* Apparently these are set elsewhere */
278
279
280 if (1 || SDL_cdlist[cdrom->id].hasAudio) {
281 /* Get the current playback status */
282 SDL_memset(&cdpb, 0, sizeof(cdpb));
283 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
284 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
285 cdpb.csCode = kAudioStatus;
286 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
287 SDL_SetError("PBControlSync() failed");
288 return(-1);
289 }
290
291 switch(cdpb.csParam.cd.status) {
292 case kStatusPlaying:
293 status = CD_PLAYING;
294 spinning = true;
295 break;
296 case kStatusPaused:
297 status = CD_PAUSED;
298 spinning = true;
299 break;
300 case kStatusMuted:
301 status = CD_PLAYING; /* What should I do here? */
302 spinning = true;
303 break;
304 case kStatusDone:
305 status = CD_STOPPED;
306 spinning = true;
307 break;
308 case kStatusStopped:
309 status = CD_STOPPED;
310 spinning = false;
311 break;
312 case kStatusError:
313 default:
314 status = CD_ERROR;
315 spinning = false;
316 break;
317 }
318
319 if (spinning && position) *position = MSF_TO_FRAMES(
320 SDL_SYS_BCDToShort(cdpb.csParam.cd.minute),
321 SDL_SYS_BCDToShort(cdpb.csParam.cd.second),
322 SDL_SYS_BCDToShort(cdpb.csParam.cd.frame));
323 }
324 else
325 status = CD_ERROR; /* What should I do here? */
326
327 return(status);
328}
329
330/* Start play */
331static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
332{
333 CDCntrlParam cdpb;
334
335 /* Pause the current audio playback to avoid audible artifacts */
336 if ( SDL_SYS_CDPause(cdrom) < 0 ) {
337 return(-1);
338 }
339
340 /* Specify the AudioCD playback mode */
341 SDL_memset(&cdpb, 0, sizeof(cdpb));
342 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
343 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
344 cdpb.csCode = kSetPlayMode;
345 cdpb.csParam.bytes[0] = false; /* Repeat? */
346 cdpb.csParam.bytes[1] = kPlayModeSequential; /* Play mode */
347 /* ¥¥¥ÊTreat as soft error, NEC Drive doesnt support this call ¥¥¥ */
348 PBControlSync((ParmBlkPtr) &cdpb);
349
350#if 1
351 /* Specify the end of audio playback */
352 SDL_memset(&cdpb, 0, sizeof(cdpb));
353 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
354 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
355 cdpb.csCode = kAudioStop;
356 cdpb.csParam.words[0] = kBlockPosition; /* Position Mode */
357 *(long *) (cdpb.csParam.words + 1) = start+length-1; /* Search Address */
358 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
359 SDL_SetError("PBControlSync() failed");
360 return(-1);
361 }
362
363 /* Specify the start of audio playback, and start it */
364 SDL_memset(&cdpb, 0, sizeof(cdpb));
365 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
366 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
367 cdpb.csCode = kAudioPlay;
368 cdpb.csParam.words[0] = kBlockPosition; /* Position Mode */
369 *(long *) (cdpb.csParam.words + 1) = start+1; /* Search Address */
370 cdpb.csParam.words[3] = false; /* Stop address? */
371 cdpb.csParam.words[4] = kStereoPlayMode; /* Audio Play Mode */
372 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
373 SDL_SetError("PBControlSync() failed");
374 return(-1);
375 }
376#else
377 /* Specify the end of audio playback */
378 FRAMES_TO_MSF(start+length, &m, &s, &f);
379 SDL_memset(&cdpb, 0, sizeof(cdpb));
380 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
381 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
382 cdpb.csCode = kAudioStop;
383 cdpb.csParam.words[0] = kTrackPosition; /* Position Mode */
384 cdpb.csParam.words[1] = 0; /* Search Address (hiword)*/
385 cdpb.csParam.words[2] = /* Search Address (loword)*/
386 SDL_SYS_ShortToBCD(cdrom->numtracks);
387 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
388 SDL_SetError("PBControlSync() failed");
389 return(-1);
390 }
391
392 /* Specify the start of audio playback, and start it */
393 FRAMES_TO_MSF(start, &m, &s, &f);
394 SDL_memset(&cdpb, 0, sizeof(cdpb));
395 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
396 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
397 cdpb.csCode = kAudioPlay;
398 cdpb.csParam.words[0] = kTrackPosition; /* Position Mode */
399 cdpb.csParam.words[1] = 0; /* Search Address (hiword)*/
400 cdpb.csParam.words[2] = SDL_SYS_ShortToBCD(1); /* Search Address (loword)*/
401 cdpb.csParam.words[3] = false; /* Stop address? */
402 cdpb.csParam.words[4] = kStereoPlayMode; /* Audio Play Mode */
403 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
404 SDL_SetError("PBControlSync() failed");
405 return(-1);
406 }
407#endif
408
409 return(0);
410}
411
412/* Pause play */
413static int SDL_SYS_CDPause(SDL_CD *cdrom)
414{
415 CDCntrlParam cdpb;
416
417 SDL_memset(&cdpb, 0, sizeof(cdpb));
418 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
419 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
420 cdpb.csCode = kAudioPause;
421 cdpb.csParam.words[0] = 0; /* Pause/Continue Flag (hiword) */
422 cdpb.csParam.words[1] = 1; /* Pause/Continue Flag (loword) */
423 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
424 SDL_SetError("PBControlSync() failed");
425 return(-1);
426 }
427 return(0);
428}
429
430/* Resume play */
431static int SDL_SYS_CDResume(SDL_CD *cdrom)
432{
433 CDCntrlParam cdpb;
434
435 SDL_memset(&cdpb, 0, sizeof(cdpb));
436 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
437 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
438 cdpb.csCode = kAudioPause;
439 cdpb.csParam.words[0] = 0; /* Pause/Continue Flag (hiword) */
440 cdpb.csParam.words[1] = 0; /* Pause/Continue Flag (loword) */
441 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
442 SDL_SetError("PBControlSync() failed");
443 return(-1);
444 }
445 return(0);
446}
447
448/* Stop play */
449static int SDL_SYS_CDStop(SDL_CD *cdrom)
450{
451 CDCntrlParam cdpb;
452
453 SDL_memset(&cdpb, 0, sizeof(cdpb));
454 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
455 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
456 cdpb.csCode = kAudioStop;
457 cdpb.csParam.words[0] = 0; /* Position Mode */
458 cdpb.csParam.words[1] = 0; /* Search Address (hiword) */
459 cdpb.csParam.words[2] = 0; /* Search Address (loword) */
460 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
461 SDL_SetError("PBControlSync() failed");
462 return(-1);
463 }
464 return(0);
465}
466
467/* Eject the CD-ROM */
468static int SDL_SYS_CDEject(SDL_CD *cdrom)
469{
470 Boolean disk = false;
471 QHdr *driveQ = GetDrvQHdr();
472 DrvQEl *driveElem;
473 HParamBlockRec hpb;
474 ParamBlockRec cpb;
475
476 for ( driveElem = (DrvQEl *) driveQ->qHead; driveElem; driveElem =
477 (driveElem) ? ((DrvQEl *) driveElem->qLink) :
478 ((DrvQEl *) driveQ->qHead) ) {
479 if ( driveQ->qTail ) {
480 driveQ->qTail->qLink = 0;
481 }
482 if ( driveElem->dQRefNum != SDL_cdlist[cdrom->id].dRefNum ) {
483 continue;
484 }
485
486 /* Does drive contain mounted volume? If not, skip */
487 SDL_memset(&hpb, 0, sizeof(hpb));
488 hpb.volumeParam.ioVRefNum = driveElem->dQDrive;
489 if ( PBHGetVInfoSync(&hpb) != noErr ) {
490 continue;
491 }
492 if ( (UnmountVol(0, driveElem->dQDrive) == noErr) &&
493 (Eject(0, driveElem->dQDrive) == noErr) ) {
494 driveElem = 0; /* Clear pointer to reset our loop */
495 disk = true;
496 }
497 }
498
499 /* If no disk is present, just eject the tray */
500 if (! disk) {
501 SDL_memset(&cpb, 0, sizeof(cpb));
502 cpb.cntrlParam.ioVRefNum = 0; /* No Drive */
503 cpb.cntrlParam.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
504 cpb.cntrlParam.csCode = kEjectTheDisc;
505 if ( PBControlSync((ParmBlkPtr)&cpb) != noErr ) {
506 SDL_SetError("PBControlSync() failed");
507 return(-1);
508 }
509 }
510 return(0);
511}
512
513/* Close the CD-ROM handle */
514static void SDL_SYS_CDClose(SDL_CD *cdrom)
515{
516 return;
517}
518
519void SDL_SYS_CDQuit(void)
520{
521 while(SDL_numcds--)
522 SDL_memset(SDL_cdlist + SDL_numcds, 0, sizeof(SDL_cdlist[0]));
523}
524
525#endif /* SDL_CDROM_MACOS */
diff --git a/apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom_c.h b/apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom_c.h
deleted file mode 100644
index e715a256d1..0000000000
--- a/apps/plugins/sdl/src/cdrom/macos/SDL_syscdrom_c.h
+++ /dev/null
@@ -1,140 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/* This is the MacOS specific header for the SDL CD-ROM API
25 Contributed by Matt Slot
26 */
27
28/* AppleCD Control calls */
29#define kVerifyTheDisc 5 /* Returns noErr if there is disc inserted */
30#define kEjectTheDisc 7 /* Eject disc from drive */
31#define kUserEject 80 /* Enable/disable the CD-ROM eject button */
32#define kReadTOC 100 /* Extract various TOC information from the disc */
33#define kReadQ 101 /* Extract Q subcode info for the current track */
34#define kAudioTrackSearch 103 /* Start playback from the indicated position */
35#define kAudioPlay 104 /* Start playback from the indicated position */
36#define kAudioPause 105 /* Pause/continue the playback */
37#define kAudioStop 106 /* Stop playback at the indicated position */
38#define kAudioStatus 107 /* Return audio play status */
39#define kAudioControl 109 /* Set the output volume for the audio channels */
40#define kReadAudioVolume 112 /* Get the output volume for the audio channels */
41#define kSetTrackList 122 /* Set the track program for the audio CD to play */
42#define kGetTrackList 123 /* Get the track program the audio CD is playing */
43#define kGetTrackIndex 124 /* Get the track index the audio CD is playing */
44#define kSetPlayMode 125 /* Set the audio tracks play mode */
45#define kGetPlayMode 126 /* Get the audio tracks play mode */
46
47/* AppleCD Status calls */
48#define kGetDriveType 96 /* Get the type of the physical CD-ROM drive */
49#define kWhoIsThere 97 /* Get a bitmap of SCSI IDs the driver controls */
50#define kGetBlockSize 98 /* Get current block size of the CD-ROM drive */
51
52/* AppleCD other constants */
53#define kBlockPosition 0 /* Position at the specified logical block number */
54#define kAbsMSFPosition 1 /* Position at the specified Min/Sec/Frame (in BCD) */
55#define kTrackPosition 2 /* Position at the specified track number (in BCD) */
56#define kIndexPosition 3 /* Position at the nth track in program (in BCD) */
57
58#define kMutedPlayMode 0 /* Play the audio track with no output */
59#define kStereoPlayMode 9 /* Play the audio track in normal stereo */
60
61#define kControlFieldMask 0x0D /* Bits 3,2,0 in the nibble */
62#define kDataTrackMask 0x04 /* Indicates Data Track */
63
64#define kGetTrackRange 1 /* Query TOC for track numbers */
65#define kGetLeadOutArea 2 /* Query TOC for "Lead Out" end of audio data */
66#define kGetTrackEntries 3 /* Query TOC for track starts and data types */
67
68#define kStatusPlaying 0 /* Audio Play operation in progress */
69#define kStatusPaused 1 /* CD-ROM device in Hold Track ("Pause") state */
70#define kStatusMuted 2 /* MUTING-ON operation in progress */
71#define kStatusDone 3 /* Audio Play completed */
72#define kStatusError 4 /* Error occurred during audio play operation */
73#define kStatusStopped 5 /* Audio play operation not requested */
74
75#define kPlayModeSequential 0 /* Play tracks in order */
76#define kPlayModeShuffled 1 /* Play tracks randomly */
77#define kPlayModeProgrammed 2 /* Use custom playlist */
78
79/* AppleCD Gestalt selectors */
80#define kGestaltAudioCDSelector 'aucd'
81#define kDriverVersion52 0x00000520
82#define kDriverVersion51 0x00000510
83#define kDriverVersion50 0x00000500
84
85/* Drive type constants */
86#define kDriveAppleCD_SC 1
87#define kDriveAppleCD_SCPlus_or_150 2
88#define kDriveAppleCD_300_or_300Plus 3
89
90/* Misc constants */
91#define kFirstSCSIDevice -33
92#define kLastSCSIDevice -40
93
94#if PRAGMA_STRUCT_ALIGN
95 #pragma options align=mac68k
96#endif
97
98/* AppleCD driver parameter block */
99typedef struct CDCntrlParam {
100 QElemPtr qLink;
101 short qType;
102 short ioTrap;
103 Ptr ioCmdAddr;
104 IOCompletionUPP ioCompletion;
105 OSErr ioResult;
106 StringPtr ioNamePtr;
107 short ioVRefNum;
108 short ioCRefNum;
109 short csCode;
110
111 union {
112 long longs[6];
113 short words[11];
114 unsigned char bytes[22];
115 struct {
116 unsigned char status;
117 unsigned char play;
118 unsigned char control;
119 unsigned char minute;
120 unsigned char second;
121 unsigned char frame;
122 } cd;
123 } csParam;
124
125 } CDCntrlParam, *CDCntrlParamPtr;
126
127typedef union CDTrackData {
128 long value; /* Treat as a longword value */
129 struct {
130 unsigned char reserved : 4; /* Unused by AppleCD driver */
131 unsigned char control : 4; /* Track flags (data track?) */
132 unsigned char min; /* Start of track (BCD) */
133 unsigned char sec; /* Start of track (BCD) */
134 unsigned char frame; /* Start of track (BCD) */
135 } entry; /* Broken into fields */
136 } CDTrackData, *CDTrackPtr;
137
138#if PRAGMA_STRUCT_ALIGN
139 #pragma options align=reset
140#endif
diff --git a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c b/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c
deleted file mode 100644
index 97cb9b2874..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.c
+++ /dev/null
@@ -1,360 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21
22 This file based on Apple sample code. We haven't changed the file name,
23 so if you want to see the original search for it on apple.com/developer
24*/
25#include "SDL_config.h"
26#include "SDL_endian.h"
27
28/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
29 AudioFilePlayer.cpp
30*/
31#include "AudioFilePlayer.h"
32
33/*
34void ThrowResult (OSStatus result, const char* str)
35{
36 SDL_SetError ("Error: %s %d", str, result);
37 throw result;
38}
39*/
40
41#if DEBUG
42static void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
43{
44 if (!inDesc) {
45 printf ("Can't print a NULL desc!\n");
46 return;
47 }
48
49 printf ("- - - - - - - - - - - - - - - - - - - -\n");
50 printf (" Sample Rate:%f\n", inDesc->mSampleRate);
51 printf (" Format ID:%s\n", (char*)&inDesc->mFormatID);
52 printf (" Format Flags:%lX\n", inDesc->mFormatFlags);
53 printf (" Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
54 printf (" Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
55 printf (" Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
56 printf (" Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
57 printf (" Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
58 printf ("- - - - - - - - - - - - - - - - - - - -\n");
59}
60#endif
61
62
63static int AudioFilePlayer_SetDestination (AudioFilePlayer *afp, AudioUnit *inDestUnit)
64{
65 /*if (afp->mConnected) throw static_cast<OSStatus>(-1);*/ /* can't set dest if already engaged */
66 if (afp->mConnected)
67 return 0 ;
68
69 SDL_memcpy(&afp->mPlayUnit, inDestUnit, sizeof (afp->mPlayUnit));
70
71 OSStatus result = noErr;
72
73
74 /* we can "down" cast a component instance to a component */
75 ComponentDescription desc;
76 result = GetComponentInfo ((Component)*inDestUnit, &desc, 0, 0, 0);
77 if (result) return 0; /*THROW_RESULT("GetComponentInfo")*/
78
79 /* we're going to use this to know which convert routine to call
80 a v1 audio unit will have a type of 'aunt'
81 a v2 audio unit will have one of several different types. */
82 if (desc.componentType != kAudioUnitType_Output) {
83 result = badComponentInstance;
84 /*THROW_RESULT("BAD COMPONENT")*/
85 if (result) return 0;
86 }
87
88 /* Set the input format of the audio unit. */
89 result = AudioUnitSetProperty (*inDestUnit,
90 kAudioUnitProperty_StreamFormat,
91 kAudioUnitScope_Input,
92 0,
93 &afp->mFileDescription,
94 sizeof (afp->mFileDescription));
95 /*THROW_RESULT("AudioUnitSetProperty")*/
96 if (result) return 0;
97 return 1;
98}
99
100static void AudioFilePlayer_SetNotifier(AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon)
101{
102 afp->mNotifier = inNotifier;
103 afp->mRefCon = inRefCon;
104}
105
106static int AudioFilePlayer_IsConnected(AudioFilePlayer *afp)
107{
108 return afp->mConnected;
109}
110
111static AudioUnit AudioFilePlayer_GetDestUnit(AudioFilePlayer *afp)
112{
113 return afp->mPlayUnit;
114}
115
116static void AudioFilePlayer_Print(AudioFilePlayer *afp)
117{
118#if DEBUG
119 printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false"));
120 printf ("- - - - - - - - - - - - - - \n");
121#endif
122}
123
124static void AudioFilePlayer_SetStartFrame (AudioFilePlayer *afp, int frame)
125{
126 SInt64 position = frame * 2352;
127
128 afp->mStartFrame = frame;
129 afp->mAudioFileManager->SetPosition (afp->mAudioFileManager, position);
130}
131
132
133static int AudioFilePlayer_GetCurrentFrame (AudioFilePlayer *afp)
134{
135 return afp->mStartFrame + (afp->mAudioFileManager->GetByteCounter(afp->mAudioFileManager) / 2352);
136}
137
138static void AudioFilePlayer_SetStopFrame (AudioFilePlayer *afp, int frame)
139{
140 SInt64 position = frame * 2352;
141
142 afp->mAudioFileManager->SetEndOfFile (afp->mAudioFileManager, position);
143}
144
145void delete_AudioFilePlayer(AudioFilePlayer *afp)
146{
147 if (afp != NULL)
148 {
149 afp->Disconnect(afp);
150
151 if (afp->mAudioFileManager) {
152 delete_AudioFileManager(afp->mAudioFileManager);
153 afp->mAudioFileManager = 0;
154 }
155
156 if (afp->mForkRefNum) {
157 FSCloseFork (afp->mForkRefNum);
158 afp->mForkRefNum = 0;
159 }
160 SDL_free(afp);
161 }
162}
163
164static int AudioFilePlayer_Connect(AudioFilePlayer *afp)
165{
166#if DEBUG
167 printf ("Connect:%x, engaged=%d\n", (int)afp->mPlayUnit, (afp->mConnected ? 1 : 0));
168#endif
169 if (!afp->mConnected)
170 {
171 if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager))
172 return 0;
173
174 /* set the render callback for the file data to be supplied to the sound converter AU */
175 afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc;
176 afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager;
177
178 OSStatus result = AudioUnitSetProperty (afp->mPlayUnit,
179 kAudioUnitProperty_SetRenderCallback,
180 kAudioUnitScope_Input,
181 0,
182 &afp->mInputCallback,
183 sizeof(afp->mInputCallback));
184 if (result) return 0; /*THROW_RESULT("AudioUnitSetProperty")*/
185 afp->mConnected = 1;
186 }
187
188 return 1;
189}
190
191/* warning noted, now please go away ;-) */
192/* #warning This should redirect the calling of notification code to some other thread */
193static void AudioFilePlayer_DoNotification (AudioFilePlayer *afp, OSStatus inStatus)
194{
195 if (afp->mNotifier) {
196 (*afp->mNotifier) (afp->mRefCon, inStatus);
197 } else {
198 SDL_SetError ("Notification posted with no notifier in place");
199
200 if (inStatus == kAudioFilePlay_FileIsFinished)
201 afp->Disconnect(afp);
202 else if (inStatus != kAudioFilePlayErr_FilePlayUnderrun)
203 afp->Disconnect(afp);
204 }
205}
206
207static void AudioFilePlayer_Disconnect (AudioFilePlayer *afp)
208{
209#if DEBUG
210 printf ("Disconnect:%x,%ld, engaged=%d\n", (int)afp->mPlayUnit, 0, (afp->mConnected ? 1 : 0));
211#endif
212 if (afp->mConnected)
213 {
214 afp->mConnected = 0;
215
216 afp->mInputCallback.inputProc = 0;
217 afp->mInputCallback.inputProcRefCon = 0;
218 OSStatus result = AudioUnitSetProperty (afp->mPlayUnit,
219 kAudioUnitProperty_SetRenderCallback,
220 kAudioUnitScope_Input,
221 0,
222 &afp->mInputCallback,
223 sizeof(afp->mInputCallback));
224 if (result)
225 SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result);
226
227 afp->mAudioFileManager->Disconnect(afp->mAudioFileManager);
228 }
229}
230
231typedef struct {
232 UInt32 offset;
233 UInt32 blockSize;
234} SSNDData;
235
236static int AudioFilePlayer_OpenFile (AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileDataSize)
237{
238 ContainerChunk chunkHeader;
239 ChunkHeader chunk;
240 SSNDData ssndData;
241
242 OSErr result;
243 HFSUniStr255 dfName;
244 ByteCount actual;
245 SInt64 offset;
246
247 /* Open the data fork of the input file */
248 result = FSGetDataForkName(&dfName);
249 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")*/
250
251 result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &afp->mForkRefNum);
252 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")*/
253
254 /* Read the file header, and check if it's indeed an AIFC file */
255 result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual);
256 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/
257
258 if (SDL_SwapBE32(chunkHeader.ckID) != 'FORM') {
259 result = -1;
260 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");*/
261 }
262
263 if (SDL_SwapBE32(chunkHeader.formType) != 'AIFC') {
264 result = -1;
265 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");*/
266 }
267
268 /* Search for the SSND chunk. We ignore all compression etc. information
269 in other chunks. Of course that is kind of evil, but for now we are lazy
270 and rely on the cdfs to always give us the same fixed format.
271 TODO: Parse the COMM chunk we currently skip to fill in mFileDescription.
272 */
273 offset = 0;
274 do {
275 result = FSReadFork(afp->mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual);
276 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/
277
278 chunk.ckID = SDL_SwapBE32(chunk.ckID);
279 chunk.ckSize = SDL_SwapBE32(chunk.ckSize);
280
281 /* Skip the chunk data */
282 offset = chunk.ckSize;
283 } while (chunk.ckID != 'SSND');
284
285 /* Read the header of the SSND chunk. After this, we are positioned right
286 at the start of the audio data. */
287 result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual);
288 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")*/
289
290 ssndData.offset = SDL_SwapBE32(ssndData.offset);
291
292 result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset);
293 if (result) return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")*/
294
295 /* Data size */
296 *outFileDataSize = chunk.ckSize - ssndData.offset - 8;
297
298 /* File format */
299 afp->mFileDescription.mSampleRate = 44100;
300 afp->mFileDescription.mFormatID = kAudioFormatLinearPCM;
301 afp->mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
302 afp->mFileDescription.mBytesPerPacket = 4;
303 afp->mFileDescription.mFramesPerPacket = 1;
304 afp->mFileDescription.mBytesPerFrame = 4;
305 afp->mFileDescription.mChannelsPerFrame = 2;
306 afp->mFileDescription.mBitsPerChannel = 16;
307
308 return 1;
309}
310
311AudioFilePlayer *new_AudioFilePlayer (const FSRef *inFileRef)
312{
313 SInt64 fileDataSize = 0;
314
315 AudioFilePlayer *afp = (AudioFilePlayer *) SDL_malloc(sizeof (AudioFilePlayer));
316 if (afp == NULL)
317 return NULL;
318 SDL_memset(afp, '\0', sizeof (*afp));
319
320 #define SET_AUDIOFILEPLAYER_METHOD(m) afp->m = AudioFilePlayer_##m
321 SET_AUDIOFILEPLAYER_METHOD(SetDestination);
322 SET_AUDIOFILEPLAYER_METHOD(SetNotifier);
323 SET_AUDIOFILEPLAYER_METHOD(SetStartFrame);
324 SET_AUDIOFILEPLAYER_METHOD(GetCurrentFrame);
325 SET_AUDIOFILEPLAYER_METHOD(SetStopFrame);
326 SET_AUDIOFILEPLAYER_METHOD(Connect);
327 SET_AUDIOFILEPLAYER_METHOD(Disconnect);
328 SET_AUDIOFILEPLAYER_METHOD(DoNotification);
329 SET_AUDIOFILEPLAYER_METHOD(IsConnected);
330 SET_AUDIOFILEPLAYER_METHOD(GetDestUnit);
331 SET_AUDIOFILEPLAYER_METHOD(Print);
332 SET_AUDIOFILEPLAYER_METHOD(OpenFile);
333 #undef SET_AUDIOFILEPLAYER_METHOD
334
335 if (!afp->OpenFile (afp, inFileRef, &fileDataSize))
336 {
337 SDL_free(afp);
338 return NULL;
339 }
340
341 /* we want about 4 seconds worth of data for the buffer */
342 int bytesPerSecond = (UInt32) (4 * afp->mFileDescription.mSampleRate * afp->mFileDescription.mBytesPerFrame);
343
344#if DEBUG
345 printf("File format:\n");
346 PrintStreamDesc (&afp->mFileDescription);
347#endif
348
349 afp->mAudioFileManager = new_AudioFileManager(afp, afp->mForkRefNum,
350 fileDataSize,
351 bytesPerSecond);
352 if (afp->mAudioFileManager == NULL)
353 {
354 delete_AudioFilePlayer(afp);
355 return NULL;
356 }
357
358 return afp;
359}
360
diff --git a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h b/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h
deleted file mode 100644
index 886d017a59..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/AudioFilePlayer.h
+++ /dev/null
@@ -1,178 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21
22 This file based on Apple sample code. We haven't changed the file name,
23 so if you want to see the original search for it on apple.com/developer
24*/
25#include "SDL_config.h"
26
27/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 AudioFilePlayer.h
29*/
30#ifndef __AudioFilePlayer_H__
31#define __AudioFilePlayer_H__
32
33#include <CoreServices/CoreServices.h>
34
35#include <AudioUnit/AudioUnit.h>
36#if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050
37#include <AudioUnit/AUNTComponent.h>
38#endif
39
40#if (MAC_OS_X_VERSION_MAX_ALLOWED < 1050)
41typedef SInt16 FSIORefNum;
42#endif
43
44#include "SDL_error.h"
45
46const char* AudioFilePlayerErrorStr (OSStatus error);
47
48/*
49void ThrowResult (OSStatus result, const char *str);
50
51#define THROW_RESULT(str) \
52 if (result) { \
53 ThrowResult (result, str); \
54 }
55*/
56
57typedef void (*AudioFilePlayNotifier)(void *inRefCon,
58 OSStatus inStatus);
59
60enum {
61 kAudioFilePlayErr_FilePlayUnderrun = -10000,
62 kAudioFilePlay_FileIsFinished = -10001,
63 kAudioFilePlay_PlayerIsUninitialized = -10002
64};
65
66
67struct S_AudioFileManager;
68
69#pragma mark __________ AudioFilePlayer
70typedef struct S_AudioFilePlayer
71{
72/*public:*/
73 int (*SetDestination)(struct S_AudioFilePlayer *afp, AudioUnit *inDestUnit);
74 void (*SetNotifier)(struct S_AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon);
75 void (*SetStartFrame)(struct S_AudioFilePlayer *afp, int frame); /* seek in the file */
76 int (*GetCurrentFrame)(struct S_AudioFilePlayer *afp); /* get the current frame position */
77 void (*SetStopFrame)(struct S_AudioFilePlayer *afp, int frame); /* set limit in the file */
78 int (*Connect)(struct S_AudioFilePlayer *afp);
79 void (*Disconnect)(struct S_AudioFilePlayer *afp);
80 void (*DoNotification)(struct S_AudioFilePlayer *afp, OSStatus inError);
81 int (*IsConnected)(struct S_AudioFilePlayer *afp);
82 AudioUnit (*GetDestUnit)(struct S_AudioFilePlayer *afp);
83 void (*Print)(struct S_AudioFilePlayer *afp);
84
85/*private:*/
86 AudioUnit mPlayUnit;
87 FSIORefNum mForkRefNum;
88
89 AURenderCallbackStruct mInputCallback;
90
91 AudioStreamBasicDescription mFileDescription;
92
93 int mConnected;
94
95 struct S_AudioFileManager* mAudioFileManager;
96
97 AudioFilePlayNotifier mNotifier;
98 void* mRefCon;
99
100 int mStartFrame;
101
102#pragma mark __________ Private_Methods
103
104 int (*OpenFile)(struct S_AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileSize);
105} AudioFilePlayer;
106
107
108AudioFilePlayer *new_AudioFilePlayer(const FSRef *inFileRef);
109void delete_AudioFilePlayer(AudioFilePlayer *afp);
110
111
112
113#pragma mark __________ AudioFileManager
114typedef struct S_AudioFileManager
115{
116/*public:*/
117 /* this method should NOT be called by an object of this class
118 as it is called by the parent's Disconnect() method */
119 void (*Disconnect)(struct S_AudioFileManager *afm);
120 int (*DoConnect)(struct S_AudioFileManager *afm);
121 OSStatus (*Read)(struct S_AudioFileManager *afm, char *buffer, ByteCount *len);
122 const char* (*GetFileBuffer)(struct S_AudioFileManager *afm);
123 const AudioFilePlayer *(*GetParent)(struct S_AudioFileManager *afm);
124 void (*SetPosition)(struct S_AudioFileManager *afm, SInt64 pos); /* seek/rewind in the file */
125 int (*GetByteCounter)(struct S_AudioFileManager *afm); /* return actual bytes streamed to audio hardware */
126 void (*SetEndOfFile)(struct S_AudioFileManager *afm, SInt64 pos); /* set the "EOF" (will behave just like it reached eof) */
127
128/*protected:*/
129 AudioFilePlayer* mParent;
130 SInt16 mForkRefNum;
131 SInt64 mAudioDataOffset;
132
133 char* mFileBuffer;
134
135 int mByteCounter;
136
137 int mReadFromFirstBuffer;
138 int mLockUnsuccessful;
139 int mIsEngaged;
140
141 int mNumTimesAskedSinceFinished;
142
143
144 void* mTmpBuffer;
145 UInt32 mBufferSize;
146 UInt32 mBufferOffset;
147/*public:*/
148 UInt32 mChunkSize;
149 SInt64 mFileLength;
150 SInt64 mReadFilePosition;
151 int mWriteToFirstBuffer;
152 int mFinishedReadingData;
153
154/*protected:*/
155 OSStatus (*Render)(struct S_AudioFileManager *afm, AudioBufferList *ioData);
156 OSStatus (*GetFileData)(struct S_AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize);
157 void (*AfterRender)(struct S_AudioFileManager *afm);
158
159/*public:*/
160 /*static*/
161 OSStatus (*FileInputProc)(void *inRefCon,
162 AudioUnitRenderActionFlags *ioActionFlags,
163 const AudioTimeStamp *inTimeStamp,
164 UInt32 inBusNumber,
165 UInt32 inNumberFrames,
166 AudioBufferList *ioData);
167} AudioFileManager;
168
169
170AudioFileManager *new_AudioFileManager (AudioFilePlayer *inParent,
171 SInt16 inForkRefNum,
172 SInt64 inFileLength,
173 UInt32 inChunkSize);
174
175void delete_AudioFileManager(AudioFileManager *afm);
176
177#endif
178
diff --git a/apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c b/apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c
deleted file mode 100644
index 0007c07f61..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/AudioFileReaderThread.c
+++ /dev/null
@@ -1,610 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21
22 This file based on Apple sample code. We haven't changed the file name,
23 so if you want to see the original search for it on apple.com/developer
24*/
25#include "SDL_config.h"
26
27/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28 AudioFileManager.cpp
29*/
30#include "AudioFilePlayer.h"
31#include <mach/mach.h> /* used for setting policy of thread */
32#include "SDLOSXCAGuard.h"
33#include <pthread.h>
34
35/*#include <list>*/
36
37/*typedef void *FileData;*/
38typedef struct S_FileData
39{
40 AudioFileManager *obj;
41 struct S_FileData *next;
42} FileData;
43
44
45typedef struct S_FileReaderThread {
46/*public:*/
47 SDLOSXCAGuard* (*GetGuard)(struct S_FileReaderThread *frt);
48 void (*AddReader)(struct S_FileReaderThread *frt);
49 void (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
50 int (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
51
52 int mThreadShouldDie;
53
54/*private:*/
55 /*typedef std::list<AudioFileManager*> FileData;*/
56
57 SDLOSXCAGuard *mGuard;
58 UInt32 mThreadPriority;
59
60 int mNumReaders;
61 FileData *mFileData;
62
63
64 void (*ReadNextChunk)(struct S_FileReaderThread *frt);
65 int (*StartFixedPriorityThread)(struct S_FileReaderThread *frt);
66 /*static*/
67 UInt32 (*GetThreadBasePriority)(pthread_t inThread);
68 /*static*/
69 void* (*DiskReaderEntry)(void *inRefCon);
70} FileReaderThread;
71
72
73static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt)
74{
75 return frt->mGuard;
76}
77
78/* returns 1 if succeeded */
79static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem)
80{
81 int didLock = 0;
82 int succeeded = 0;
83 if (frt->mGuard->Try(frt->mGuard, &didLock))
84 {
85 /*frt->mFileData.push_back (inItem);*/
86 /* !!! FIXME: this could be faster with a "tail" member. --ryan. */
87 FileData *i = frt->mFileData;
88 FileData *prev = NULL;
89
90 FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData));
91 newfd->obj = inItem;
92 newfd->next = NULL;
93
94 while (i != NULL) { prev = i; i = i->next; }
95 if (prev == NULL)
96 frt->mFileData = newfd;
97 else
98 prev->next = newfd;
99
100 frt->mGuard->Notify(frt->mGuard);
101 succeeded = 1;
102
103 if (didLock)
104 frt->mGuard->Unlock(frt->mGuard);
105 }
106
107 return succeeded;
108}
109
110static void FileReaderThread_AddReader(FileReaderThread *frt)
111{
112 if (frt->mNumReaders == 0)
113 {
114 frt->mThreadShouldDie = 0;
115 frt->StartFixedPriorityThread (frt);
116 }
117 frt->mNumReaders++;
118}
119
120static void FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileManager* inItem)
121{
122 if (frt->mNumReaders > 0)
123 {
124 int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
125
126 /*frt->mFileData.remove (inItem);*/
127 FileData *i = frt->mFileData;
128 FileData *prev = NULL;
129 while (i != NULL)
130 {
131 FileData *next = i->next;
132 if (i->obj != inItem)
133 prev = i;
134 else
135 {
136 if (prev == NULL)
137 frt->mFileData = next;
138 else
139 prev->next = next;
140 SDL_free(i);
141 }
142 i = next;
143 }
144
145 if (--frt->mNumReaders == 0) {
146 frt->mThreadShouldDie = 1;
147 frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */
148 frt->mGuard->Wait(frt->mGuard); /* wait for thread to die */
149 }
150
151 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
152 }
153}
154
155static int FileReaderThread_StartFixedPriorityThread (FileReaderThread *frt)
156{
157 pthread_attr_t theThreadAttrs;
158 pthread_t pThread;
159
160 OSStatus result = pthread_attr_init(&theThreadAttrs);
161 if (result) return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")*/
162
163 result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
164 if (result) return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")*/
165
166 result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
167 if (result) return 0; /*THROW_RESULT("pthread_create - Create and start the thread.")*/
168
169 pthread_attr_destroy(&theThreadAttrs);
170
171 /* we've now created the thread and started it
172 we'll now set the priority of the thread to the nominated priority
173 and we'll also make the thread fixed */
174 thread_extended_policy_data_t theFixedPolicy;
175 thread_precedence_policy_data_t thePrecedencePolicy;
176 SInt32 relativePriority;
177
178 /* make thread fixed */
179 theFixedPolicy.timeshare = 0; /* set to 1 for a non-fixed thread */
180 result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
181 if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")*/
182 /* set priority */
183 /* precedency policy's "importance" value is relative to spawning thread's priority */
184 relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
185
186 thePrecedencePolicy.importance = relativePriority;
187 result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
188 if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.")*/
189
190 return 1;
191}
192
193static UInt32 FileReaderThread_GetThreadBasePriority (pthread_t inThread)
194{
195 thread_basic_info_data_t threadInfo;
196 policy_info_data_t thePolicyInfo;
197 unsigned int count;
198
199 /* get basic info */
200 count = THREAD_BASIC_INFO_COUNT;
201 thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
202
203 switch (threadInfo.policy) {
204 case POLICY_TIMESHARE:
205 count = POLICY_TIMESHARE_INFO_COUNT;
206 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
207 return thePolicyInfo.ts.base_priority;
208 break;
209
210 case POLICY_FIFO:
211 count = POLICY_FIFO_INFO_COUNT;
212 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
213 if (thePolicyInfo.fifo.depressed) {
214 return thePolicyInfo.fifo.depress_priority;
215 } else {
216 return thePolicyInfo.fifo.base_priority;
217 }
218 break;
219
220 case POLICY_RR:
221 count = POLICY_RR_INFO_COUNT;
222 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
223 if (thePolicyInfo.rr.depressed) {
224 return thePolicyInfo.rr.depress_priority;
225 } else {
226 return thePolicyInfo.rr.base_priority;
227 }
228 break;
229 }
230
231 return 0;
232}
233
234static void *FileReaderThread_DiskReaderEntry (void *inRefCon)
235{
236 FileReaderThread *frt = (FileReaderThread *)inRefCon;
237 frt->ReadNextChunk(frt);
238 #if DEBUG
239 printf ("finished with reading file\n");
240 #endif
241
242 return 0;
243}
244
245static void FileReaderThread_ReadNextChunk (FileReaderThread *frt)
246{
247 OSStatus result;
248 ByteCount dataChunkSize;
249 AudioFileManager* theItem = 0;
250
251 for (;;)
252 {
253 { /* this is a scoped based lock */
254 int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
255
256 if (frt->mThreadShouldDie) {
257 frt->mGuard->Notify(frt->mGuard);
258 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
259 return;
260 }
261
262 /*if (frt->mFileData.empty())*/
263 if (frt->mFileData == NULL)
264 {
265 frt->mGuard->Wait(frt->mGuard);
266 }
267
268 /* kill thread */
269 if (frt->mThreadShouldDie) {
270
271 frt->mGuard->Notify(frt->mGuard);
272 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
273 return;
274 }
275
276 /*theItem = frt->mFileData.front();*/
277 /*frt->mFileData.pop_front();*/
278 theItem = NULL;
279 if (frt->mFileData != NULL)
280 {
281 FileData *next = frt->mFileData->next;
282 theItem = frt->mFileData->obj;
283 SDL_free(frt->mFileData);
284 frt->mFileData = next;
285 }
286
287 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
288 }
289
290 if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
291 dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
292 else
293 dataChunkSize = theItem->mChunkSize;
294
295 /* this is the exit condition for the thread */
296 if (dataChunkSize <= 0) {
297 theItem->mFinishedReadingData = 1;
298 continue;
299 }
300 /* construct pointer */
301 char* writePtr = (char *) (theItem->GetFileBuffer(theItem) +
302 (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
303
304 /* read data */
305 result = theItem->Read(theItem, writePtr, &dataChunkSize);
306 if (result != noErr && result != eofErr) {
307 AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem);
308 afp->DoNotification(afp, result);
309 continue;
310 }
311
312 if (dataChunkSize != theItem->mChunkSize)
313 {
314 writePtr += dataChunkSize;
315
316 /* can't exit yet.. we still have to pass the partial buffer back */
317 SDL_memset(writePtr, 0, (theItem->mChunkSize - dataChunkSize));
318 }
319
320 theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; /* switch buffers */
321
322 if (result == eofErr)
323 theItem->mReadFilePosition = theItem->mFileLength;
324 else
325 theItem->mReadFilePosition += dataChunkSize; /* increment count */
326 }
327}
328
329void delete_FileReaderThread(FileReaderThread *frt)
330{
331 if (frt != NULL)
332 {
333 delete_SDLOSXCAGuard(frt->mGuard);
334 SDL_free(frt);
335 }
336}
337
338FileReaderThread *new_FileReaderThread ()
339{
340 FileReaderThread *frt = (FileReaderThread *) SDL_malloc(sizeof (FileReaderThread));
341 if (frt == NULL)
342 return NULL;
343 SDL_memset(frt, '\0', sizeof (*frt));
344
345 frt->mGuard = new_SDLOSXCAGuard();
346 if (frt->mGuard == NULL)
347 {
348 SDL_free(frt);
349 return NULL;
350 }
351
352 #define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m
353 SET_FILEREADERTHREAD_METHOD(GetGuard);
354 SET_FILEREADERTHREAD_METHOD(AddReader);
355 SET_FILEREADERTHREAD_METHOD(RemoveReader);
356 SET_FILEREADERTHREAD_METHOD(TryNextRead);
357 SET_FILEREADERTHREAD_METHOD(ReadNextChunk);
358 SET_FILEREADERTHREAD_METHOD(StartFixedPriorityThread);
359 SET_FILEREADERTHREAD_METHOD(GetThreadBasePriority);
360 SET_FILEREADERTHREAD_METHOD(DiskReaderEntry);
361 #undef SET_FILEREADERTHREAD_METHOD
362
363 frt->mThreadPriority = 62;
364 return frt;
365}
366
367
368static FileReaderThread *sReaderThread;
369
370
371static int AudioFileManager_DoConnect (AudioFileManager *afm)
372{
373 if (!afm->mIsEngaged)
374 {
375 OSStatus result;
376
377 /*afm->mReadFilePosition = 0;*/
378 afm->mFinishedReadingData = 0;
379
380 afm->mNumTimesAskedSinceFinished = 0;
381 afm->mLockUnsuccessful = 0;
382
383 ByteCount dataChunkSize;
384
385 if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize)
386 dataChunkSize = afm->mFileLength - afm->mReadFilePosition;
387 else
388 dataChunkSize = afm->mChunkSize;
389
390 result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize);
391 if (result) return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read")*/
392
393 afm->mReadFilePosition += dataChunkSize;
394
395 afm->mWriteToFirstBuffer = 0;
396 afm->mReadFromFirstBuffer = 1;
397
398 sReaderThread->AddReader(sReaderThread);
399
400 afm->mIsEngaged = 1;
401 }
402 /*
403 else
404 throw static_cast<OSStatus>(-1); */ /* thread has already been started */
405
406 return 1;
407}
408
409static void AudioFileManager_Disconnect (AudioFileManager *afm)
410{
411 if (afm->mIsEngaged)
412 {
413 sReaderThread->RemoveReader (sReaderThread, afm);
414 afm->mIsEngaged = 0;
415 }
416}
417
418static OSStatus AudioFileManager_Read(AudioFileManager *afm, char *buffer, ByteCount *len)
419{
420 return FSReadFork (afm->mForkRefNum,
421 fsFromStart,
422 afm->mReadFilePosition + afm->mAudioDataOffset,
423 *len,
424 buffer,
425 len);
426}
427
428static OSStatus AudioFileManager_GetFileData (AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize)
429{
430 if (afm->mFinishedReadingData)
431 {
432 ++afm->mNumTimesAskedSinceFinished;
433 *inOutDataSize = 0;
434 *inOutData = 0;
435 return noErr;
436 }
437
438 if (afm->mReadFromFirstBuffer == afm->mWriteToFirstBuffer) {
439 #if DEBUG
440 printf ("* * * * * * * Can't keep up with reading file\n");
441 #endif
442
443 afm->mParent->DoNotification (afm->mParent, kAudioFilePlayErr_FilePlayUnderrun);
444 *inOutDataSize = 0;
445 *inOutData = 0;
446 } else {
447 *inOutDataSize = afm->mChunkSize;
448 *inOutData = afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->mFileBuffer + afm->mChunkSize);
449 }
450
451 afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
452
453 afm->mReadFromFirstBuffer = !afm->mReadFromFirstBuffer;
454
455 return noErr;
456}
457
458static void AudioFileManager_AfterRender (AudioFileManager *afm)
459{
460 if (afm->mNumTimesAskedSinceFinished > 0)
461 {
462 int didLock = 0;
463 SDLOSXCAGuard *guard = sReaderThread->GetGuard(sReaderThread);
464 if (guard->Try(guard, &didLock)) {
465 afm->mParent->DoNotification (afm->mParent, kAudioFilePlay_FileIsFinished);
466 if (didLock)
467 guard->Unlock(guard);
468 }
469 }
470
471 if (afm->mLockUnsuccessful)
472 afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
473}
474
475static void AudioFileManager_SetPosition (AudioFileManager *afm, SInt64 pos)
476{
477 if (pos < 0 || pos >= afm->mFileLength) {
478 SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n",
479 (unsigned int)pos, (unsigned int)afm->mFileLength);
480 pos = 0;
481 }
482
483 afm->mReadFilePosition = pos;
484}
485
486static void AudioFileManager_SetEndOfFile (AudioFileManager *afm, SInt64 pos)
487{
488 if (pos <= 0 || pos > afm->mFileLength) {
489 SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
490 pos = afm->mFileLength;
491 }
492
493 afm->mFileLength = pos;
494}
495
496static const char *AudioFileManager_GetFileBuffer(AudioFileManager *afm)
497{
498 return afm->mFileBuffer;
499}
500
501const AudioFilePlayer *AudioFileManager_GetParent(AudioFileManager *afm)
502{
503 return afm->mParent;
504}
505
506static int AudioFileManager_GetByteCounter(AudioFileManager *afm)
507{
508 return afm->mByteCounter;
509}
510
511static OSStatus AudioFileManager_FileInputProc (void *inRefCon,
512 AudioUnitRenderActionFlags *ioActionFlags,
513 const AudioTimeStamp *inTimeStamp,
514 UInt32 inBusNumber,
515 UInt32 inNumberFrames,
516 AudioBufferList *ioData)
517{
518 AudioFileManager* afm = (AudioFileManager*)inRefCon;
519 return afm->Render(afm, ioData);
520}
521
522static OSStatus AudioFileManager_Render (AudioFileManager *afm, AudioBufferList *ioData)
523{
524 OSStatus result = noErr;
525 AudioBuffer *abuf;
526 UInt32 i;
527
528 for (i = 0; i < ioData->mNumberBuffers; i++) {
529 abuf = &ioData->mBuffers[i];
530 if (afm->mBufferOffset >= afm->mBufferSize) {
531 result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize);
532 if (result) {
533 SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
534 afm->mParent->DoNotification(afm->mParent, result);
535 return result;
536 }
537
538 afm->mBufferOffset = 0;
539 }
540
541 if (abuf->mDataByteSize > afm->mBufferSize - afm->mBufferOffset)
542 abuf->mDataByteSize = afm->mBufferSize - afm->mBufferOffset;
543 abuf->mData = (char *)afm->mTmpBuffer + afm->mBufferOffset;
544 afm->mBufferOffset += abuf->mDataByteSize;
545
546 afm->mByteCounter += abuf->mDataByteSize;
547 afm->AfterRender(afm);
548 }
549 return result;
550}
551
552
553void delete_AudioFileManager (AudioFileManager *afm)
554{
555 if (afm != NULL) {
556 if (afm->mFileBuffer) {
557 free(afm->mFileBuffer);
558 }
559
560 SDL_free(afm);
561 }
562}
563
564
565AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent,
566 SInt16 inForkRefNum,
567 SInt64 inFileLength,
568 UInt32 inChunkSize)
569{
570 AudioFileManager *afm;
571
572 if (sReaderThread == NULL)
573 {
574 sReaderThread = new_FileReaderThread();
575 if (sReaderThread == NULL)
576 return NULL;
577 }
578
579 afm = (AudioFileManager *) SDL_malloc(sizeof (AudioFileManager));
580 if (afm == NULL)
581 return NULL;
582 SDL_memset(afm, '\0', sizeof (*afm));
583
584 #define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m
585 SET_AUDIOFILEMANAGER_METHOD(Disconnect);
586 SET_AUDIOFILEMANAGER_METHOD(DoConnect);
587 SET_AUDIOFILEMANAGER_METHOD(Read);
588 SET_AUDIOFILEMANAGER_METHOD(GetFileBuffer);
589 SET_AUDIOFILEMANAGER_METHOD(GetParent);
590 SET_AUDIOFILEMANAGER_METHOD(SetPosition);
591 SET_AUDIOFILEMANAGER_METHOD(GetByteCounter);
592 SET_AUDIOFILEMANAGER_METHOD(SetEndOfFile);
593 SET_AUDIOFILEMANAGER_METHOD(Render);
594 SET_AUDIOFILEMANAGER_METHOD(GetFileData);
595 SET_AUDIOFILEMANAGER_METHOD(AfterRender);
596 SET_AUDIOFILEMANAGER_METHOD(FileInputProc);
597 #undef SET_AUDIOFILEMANAGER_METHOD
598
599 afm->mParent = inParent;
600 afm->mForkRefNum = inForkRefNum;
601 afm->mBufferSize = inChunkSize;
602 afm->mBufferOffset = inChunkSize;
603 afm->mChunkSize = inChunkSize;
604 afm->mFileLength = inFileLength;
605 afm->mFileBuffer = (char*) SDL_malloc(afm->mChunkSize * 2);
606 FSGetForkPosition(afm->mForkRefNum, &afm->mAudioDataOffset);
607 assert (afm->mFileBuffer != NULL);
608 return afm;
609}
610
diff --git a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c b/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c
deleted file mode 100644
index beb87cd85b..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.c
+++ /dev/null
@@ -1,636 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#include "CDPlayer.h"
25#include "AudioFilePlayer.h"
26#include "SDLOSXCAGuard.h"
27
28/* we're exporting these functions into C land for SDL_syscdrom.c */
29/*extern "C" {*/
30
31/*///////////////////////////////////////////////////////////////////////////
32 Constants
33 //////////////////////////////////////////////////////////////////////////*/
34
35#define kAudioCDFilesystemID (UInt16)(('J' << 8) | 'H') /* 'JH'; this avoids compiler warning */
36
37/* XML PList keys */
38#define kRawTOCDataString "Format 0x02 TOC Data"
39#define kSessionsString "Sessions"
40#define kSessionTypeString "Session Type"
41#define kTrackArrayString "Track Array"
42#define kFirstTrackInSessionString "First Track"
43#define kLastTrackInSessionString "Last Track"
44#define kLeadoutBlockString "Leadout Block"
45#define kDataKeyString "Data"
46#define kPointKeyString "Point"
47#define kSessionNumberKeyString "Session Number"
48#define kStartBlockKeyString "Start Block"
49
50/*///////////////////////////////////////////////////////////////////////////
51 Globals
52 //////////////////////////////////////////////////////////////////////////*/
53
54#pragma mark -- Globals --
55
56static int playBackWasInit = 0;
57static AudioUnit theUnit;
58static AudioFilePlayer* thePlayer = NULL;
59static CDPlayerCompletionProc completionProc = NULL;
60static SDL_mutex *apiMutex = NULL;
61static SDL_sem *callbackSem;
62static SDL_CD* theCDROM;
63
64/*///////////////////////////////////////////////////////////////////////////
65 Prototypes
66 //////////////////////////////////////////////////////////////////////////*/
67
68#pragma mark -- Prototypes --
69
70static OSStatus CheckInit ();
71
72static void FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus);
73
74static int RunCallBackThread (void* inRefCon);
75
76
77#pragma mark -- Public Functions --
78
79void Lock ()
80{
81 if (!apiMutex) {
82 apiMutex = SDL_CreateMutex();
83 }
84 SDL_mutexP(apiMutex);
85}
86
87void Unlock ()
88{
89 SDL_mutexV(apiMutex);
90}
91
92int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes)
93{
94 int volumeIndex;
95 int cdVolumeCount = 0;
96 OSStatus result = noErr;
97
98 for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++)
99 {
100 FSVolumeRefNum actualVolume;
101 FSVolumeInfo volumeInfo;
102
103 memset (&volumeInfo, 0, sizeof(volumeInfo));
104
105 result = FSGetVolumeInfo (kFSInvalidVolumeRefNum,
106 volumeIndex,
107 &actualVolume,
108 kFSVolInfoFSInfo,
109 &volumeInfo,
110 NULL,
111 NULL);
112
113 if (result == noErr)
114 {
115 if (volumeInfo.filesystemID == kAudioCDFilesystemID) /* It's an audio CD */
116 {
117 if (volumes != NULL && cdVolumeCount < numVolumes)
118 volumes[cdVolumeCount] = actualVolume;
119
120 cdVolumeCount++;
121 }
122 }
123 else
124 {
125 /* I'm commenting this out because it seems to be harmless */
126 /*SDL_SetError ("DetectAudioCDVolumes: FSGetVolumeInfo returned %d", result);*/
127 }
128 }
129
130 return cdVolumeCount;
131}
132
133int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD)
134{
135 HFSUniStr255 dataForkName;
136 OSStatus theErr;
137 FSIORefNum forkRefNum;
138 SInt64 forkSize;
139 Ptr forkData = 0;
140 ByteCount actualRead;
141 CFDataRef dataRef = 0;
142 CFPropertyListRef propertyListRef = 0;
143 FSRefParam fsRefPB;
144 FSRef tocPlistFSRef;
145 FSRef rootRef;
146 const char* error = "Unspecified Error";
147 const UniChar uniName[] = { '.','T','O','C','.','p','l','i','s','t' };
148
149 theErr = FSGetVolumeInfo(theVolume, 0, 0, kFSVolInfoNone, 0, 0, &rootRef);
150 if(theErr != noErr) {
151 error = "FSGetVolumeInfo";
152 goto bail;
153 }
154
155 SDL_memset(&fsRefPB, '\0', sizeof (fsRefPB));
156
157 /* get stuff from .TOC.plist */
158 fsRefPB.ref = &rootRef;
159 fsRefPB.newRef = &tocPlistFSRef;
160 fsRefPB.nameLength = sizeof (uniName) / sizeof (uniName[0]);
161 fsRefPB.name = uniName;
162 fsRefPB.textEncodingHint = kTextEncodingUnknown;
163
164 theErr = PBMakeFSRefUnicodeSync (&fsRefPB);
165 if(theErr != noErr) {
166 error = "PBMakeFSRefUnicodeSync";
167 goto bail;
168 }
169
170 /* Load and parse the TOC XML data */
171
172 theErr = FSGetDataForkName (&dataForkName);
173 if (theErr != noErr) {
174 error = "FSGetDataForkName";
175 goto bail;
176 }
177
178 theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum);
179 if (theErr != noErr) {
180 error = "FSOpenFork";
181 goto bail;
182 }
183
184 theErr = FSGetForkSize (forkRefNum, &forkSize);
185 if (theErr != noErr) {
186 error = "FSGetForkSize";
187 goto bail;
188 }
189
190 /* Allocate some memory for the XML data */
191 forkData = NewPtr (forkSize);
192 if(forkData == NULL) {
193 error = "NewPtr";
194 goto bail;
195 }
196
197 theErr = FSReadFork (forkRefNum, fsFromStart, 0 /* offset location */, forkSize, forkData, &actualRead);
198 if(theErr != noErr) {
199 error = "FSReadFork";
200 goto bail;
201 }
202
203 dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize);
204 if(dataRef == 0) {
205 error = "CFDataCreate";
206 goto bail;
207 }
208
209 propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault,
210 dataRef,
211 kCFPropertyListImmutable,
212 NULL);
213 if (propertyListRef == NULL) {
214 error = "CFPropertyListCreateFromXMLData";
215 goto bail;
216 }
217
218 /* Now we got the Property List in memory. Parse it. */
219
220 /* First, make sure the root item is a CFDictionary. If not, release and bail. */
221 if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID())
222 {
223 CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef;
224
225 CFDataRef theRawTOCDataRef;
226 CFArrayRef theSessionArrayRef;
227 CFIndex numSessions;
228 CFIndex index;
229
230 /* This is how we get the Raw TOC Data */
231 theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString));
232
233 /* Get the session array info. */
234 theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString));
235
236 /* Find out how many sessions there are. */
237 numSessions = CFArrayGetCount (theSessionArrayRef);
238
239 /* Initialize the total number of tracks to 0 */
240 theCD->numtracks = 0;
241
242 /* Iterate over all sessions, collecting the track data */
243 for(index = 0; index < numSessions; index++)
244 {
245 CFDictionaryRef theSessionDict;
246 CFNumberRef leadoutBlock;
247 CFArrayRef trackArray;
248 CFIndex numTracks;
249 CFIndex trackIndex;
250 UInt32 value = 0;
251
252 theSessionDict = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index);
253 leadoutBlock = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString));
254
255 trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString));
256
257 numTracks = CFArrayGetCount (trackArray);
258
259 for(trackIndex = 0; trackIndex < numTracks; trackIndex++) {
260
261 CFDictionaryRef theTrackDict;
262 CFNumberRef trackNumber;
263 CFNumberRef sessionNumber;
264 CFNumberRef startBlock;
265 CFBooleanRef isDataTrack;
266 UInt32 value;
267
268 theTrackDict = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex);
269
270 trackNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString));
271 sessionNumber = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString));
272 startBlock = (CFNumberRef) CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString));
273 isDataTrack = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString));
274
275 /* Fill in the SDL_CD struct */
276 int idx = theCD->numtracks++;
277
278 CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value);
279 theCD->track[idx].id = value;
280
281 CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value);
282 theCD->track[idx].offset = value;
283
284 theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK;
285
286 /* Since the track lengths are not stored in .TOC.plist we compute them. */
287 if (trackIndex > 0) {
288 theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset;
289 }
290 }
291
292 /* Compute the length of the last track */
293 CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value);
294
295 theCD->track[theCD->numtracks-1].length =
296 value - theCD->track[theCD->numtracks-1].offset;
297
298 /* Set offset to leadout track */
299 theCD->track[theCD->numtracks].offset = value;
300 }
301
302 }
303
304 theErr = 0;
305 goto cleanup;
306bail:
307 SDL_SetError ("ReadTOCData: %s returned %d", error, theErr);
308 theErr = -1;
309cleanup:
310
311 if (propertyListRef != NULL)
312 CFRelease(propertyListRef);
313 if (dataRef != NULL)
314 CFRelease(dataRef);
315 if (forkData != NULL)
316 DisposePtr(forkData);
317
318 FSCloseFork (forkRefNum);
319
320 return theErr;
321}
322
323int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks)
324{
325 OSStatus result = -1;
326 FSIterator iterator;
327 ItemCount actualObjects;
328 FSRef rootDirectory;
329 FSRef ref;
330 HFSUniStr255 nameStr;
331
332 result = FSGetVolumeInfo (theVolume,
333 0,
334 NULL,
335 kFSVolInfoFSInfo,
336 NULL,
337 NULL,
338 &rootDirectory);
339
340 if (result != noErr) {
341 SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result);
342 return result;
343 }
344
345 result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator);
346 if (result == noErr) {
347 do
348 {
349 result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects,
350 NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr);
351 if (result == noErr) {
352
353 CFStringRef name;
354 name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length);
355
356 /* Look for .aiff extension */
357 if (CFStringHasSuffix (name, CFSTR(".aiff")) ||
358 CFStringHasSuffix (name, CFSTR(".cdda"))) {
359
360 /* Extract the track id from the filename */
361 int trackID = 0, i = 0;
362 while (i < nameStr.length && !isdigit(nameStr.unicode[i])) {
363 ++i;
364 }
365 while (i < nameStr.length && isdigit(nameStr.unicode[i])) {
366 trackID = 10 * trackID +(nameStr.unicode[i] - '0');
367 ++i;
368 }
369
370 #if DEBUG_CDROM
371 printf("Found AIFF for track %d: '%s'\n", trackID,
372 CFStringGetCStringPtr (name, CFStringGetSystemEncoding()));
373 #endif
374
375 /* Track ID's start at 1, but we want to start at 0 */
376 trackID--;
377
378 assert(0 <= trackID && trackID <= SDL_MAX_TRACKS);
379
380 if (trackID < numTracks)
381 memcpy (&trackFiles[trackID], &ref, sizeof(FSRef));
382 }
383 CFRelease (name);
384 }
385 } while(noErr == result);
386 FSCloseIterator (iterator);
387 }
388
389 return 0;
390}
391
392int LoadFile (const FSRef *ref, int startFrame, int stopFrame)
393{
394 int error = -1;
395
396 if (CheckInit () < 0)
397 goto bail;
398
399 /* release any currently playing file */
400 if (ReleaseFile () < 0)
401 goto bail;
402
403 #if DEBUG_CDROM
404 printf ("LoadFile: %d %d\n", startFrame, stopFrame);
405 #endif
406
407 /*try {*/
408
409 /* create a new player, and attach to the audio unit */
410
411 thePlayer = new_AudioFilePlayer(ref);
412 if (thePlayer == NULL) {
413 SDL_SetError ("LoadFile: Could not create player");
414 return -3; /*throw (-3);*/
415 }
416
417 if (!thePlayer->SetDestination(thePlayer, &theUnit))
418 goto bail;
419
420 if (startFrame >= 0)
421 thePlayer->SetStartFrame (thePlayer, startFrame);
422
423 if (stopFrame >= 0 && stopFrame > startFrame)
424 thePlayer->SetStopFrame (thePlayer, stopFrame);
425
426 /* we set the notifier later */
427 /*thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL);*/
428
429 if (!thePlayer->Connect(thePlayer))
430 goto bail;
431
432 #if DEBUG_CDROM
433 thePlayer->Print(thePlayer);
434 fflush (stdout);
435 #endif
436 /*}
437 catch (...)
438 {
439 goto bail;
440 }*/
441
442 error = 0;
443
444 bail:
445 return error;
446}
447
448int ReleaseFile ()
449{
450 int error = -1;
451
452 /* (Don't see any way that the original C++ code could throw here.) --ryan. */
453 /*try {*/
454 if (thePlayer != NULL) {
455
456 thePlayer->Disconnect(thePlayer);
457
458 delete_AudioFilePlayer(thePlayer);
459
460 thePlayer = NULL;
461 }
462 /*}
463 catch (...)
464 {
465 goto bail;
466 }*/
467
468 error = 0;
469
470/* bail: */
471 return error;
472}
473
474int PlayFile ()
475{
476 OSStatus result = -1;
477
478 if (CheckInit () < 0)
479 goto bail;
480
481 /*try {*/
482
483 // start processing of the audio unit
484 result = AudioOutputUnitStart (theUnit);
485 if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart")
486
487 /*}
488 catch (...)
489 {
490 goto bail;
491 }*/
492
493 result = 0;
494
495bail:
496 return result;
497}
498
499int PauseFile ()
500{
501 OSStatus result = -1;
502
503 if (CheckInit () < 0)
504 goto bail;
505
506 /*try {*/
507
508 /* stop processing the audio unit */
509 result = AudioOutputUnitStop (theUnit);
510 if (result) goto bail; /*THROW_RESULT("PauseFile: AudioOutputUnitStop")*/
511 /*}
512 catch (...)
513 {
514 goto bail;
515 }*/
516
517 result = 0;
518bail:
519 return result;
520}
521
522void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom)
523{
524 assert(thePlayer != NULL);
525
526 theCDROM = cdrom;
527 completionProc = proc;
528 thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom);
529}
530
531int GetCurrentFrame ()
532{
533 int frame;
534
535 if (thePlayer == NULL)
536 frame = 0;
537 else
538 frame = thePlayer->GetCurrentFrame (thePlayer);
539
540 return frame;
541}
542
543
544#pragma mark -- Private Functions --
545
546static OSStatus CheckInit ()
547{
548 if (playBackWasInit)
549 return 0;
550
551 OSStatus result = noErr;
552
553 /* Create the callback semaphore */
554 callbackSem = SDL_CreateSemaphore(0);
555
556 /* Start callback thread */
557 SDL_CreateThread(RunCallBackThread, NULL);
558
559 { /*try {*/
560 ComponentDescription desc;
561
562 desc.componentType = kAudioUnitType_Output;
563 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
564 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
565 desc.componentFlags = 0;
566 desc.componentFlagsMask = 0;
567
568 Component comp = FindNextComponent (NULL, &desc);
569 if (comp == NULL) {
570 SDL_SetError ("CheckInit: FindNextComponent returned NULL");
571 if (result) return -1; //throw(internalComponentErr);
572 }
573
574 result = OpenAComponent (comp, &theUnit);
575 if (result) return -1; //THROW_RESULT("CheckInit: OpenAComponent")
576
577 // you need to initialize the output unit before you set it as a destination
578 result = AudioUnitInitialize (theUnit);
579 if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize")
580
581
582 playBackWasInit = true;
583 }
584 /*catch (...)
585 {
586 return -1;
587 }*/
588
589 return 0;
590}
591
592static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus)
593{
594 if (inStatus == kAudioFilePlay_FileIsFinished) {
595
596 /* notify non-CA thread to perform the callback */
597 SDL_SemPost(callbackSem);
598
599 } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) {
600
601 SDL_SetError ("CDPlayer Notification: buffer underrun");
602 } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) {
603
604 SDL_SetError ("CDPlayer Notification: player is uninitialized");
605 } else {
606
607 SDL_SetError ("CDPlayer Notification: unknown error %ld", inStatus);
608 }
609}
610
611static int RunCallBackThread (void *param)
612{
613 for (;;) {
614
615 SDL_SemWait(callbackSem);
616
617 if (completionProc && theCDROM) {
618 #if DEBUG_CDROM
619 printf ("callback!\n");
620 #endif
621 (*completionProc)(theCDROM);
622 } else {
623 #if DEBUG_CDROM
624 printf ("callback?\n");
625 #endif
626 }
627 }
628
629 #if DEBUG_CDROM
630 printf ("thread dying now...\n");
631 #endif
632
633 return 0;
634}
635
636/*}; // extern "C" */
diff --git a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h b/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h
deleted file mode 100644
index be1ac1826a..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/CDPlayer.h
+++ /dev/null
@@ -1,69 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifndef __CDPlayer__H__
25#define __CDPlayer__H__ 1
26
27#include <string.h>
28
29#include <Carbon/Carbon.h>
30#include <CoreFoundation/CoreFoundation.h>
31#include <AudioUnit/AudioUnit.h>
32
33#include "SDL.h"
34#include "SDL_thread.h"
35#include "SDL_mutex.h"
36
37#ifdef __cplusplus
38extern "C" {
39#endif
40
41typedef void (*CDPlayerCompletionProc)(SDL_CD *cdrom) ;
42
43void Lock ();
44
45void Unlock();
46
47int LoadFile (const FSRef *ref, int startFrame, int endFrame); /* pass -1 to do nothing */
48
49int ReleaseFile ();
50
51int PlayFile ();
52
53int PauseFile ();
54
55void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom);
56
57int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD);
58
59int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks);
60
61int DetectAudioCDVolumes (FSVolumeRefNum *volumes, int numVolumes);
62
63int GetCurrentFrame ();
64
65#ifdef __cplusplus
66};
67#endif
68
69#endif /* __CD_Player__H__ */
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c b/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c
deleted file mode 100644
index e8caf1bf10..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.c
+++ /dev/null
@@ -1,199 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/*
25 Note: This file hasn't been modified so technically we have to keep the disclaimer :-(
26
27 Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
28
29 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
30 ("Apple") in consideration of your agreement to the following terms, and your
31 use, installation, modification or redistribution of this Apple software
32 constitutes acceptance of these terms. If you do not agree with these terms,
33 please do not use, install, modify or redistribute this Apple software.
34
35 In consideration of your agreement to abide by the following terms, and subject
36 to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
37 copyrights in this original Apple software (the "Apple Software"), to use,
38 reproduce, modify and redistribute the Apple Software, with or without
39 modifications, in source and/or binary forms; provided that if you redistribute
40 the Apple Software in its entirety and without modifications, you must retain
41 this notice and the following text and disclaimers in all such redistributions of
42 the Apple Software. Neither the name, trademarks, service marks or logos of
43 Apple Computer, Inc. may be used to endorse or promote products derived from the
44 Apple Software without specific prior written permission from Apple. Except as
45 expressly stated in this notice, no other rights or licenses, express or implied,
46 are granted by Apple herein, including but not limited to any patent rights that
47 may be infringed by your derivative works or by other works in which the Apple
48 Software may be incorporated.
49
50 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
51 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
52 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
54 COMBINATION WITH YOUR PRODUCTS.
55
56 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
57 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
58 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
60 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
61 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
62 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63*/
64/*=============================================================================
65 CAGuard.cp
66
67=============================================================================*/
68
69/*=============================================================================
70 Includes
71 =============================================================================*/
72
73/*
74#include <stdio.h>
75#include <stdlib.h>
76#include <string.h>
77*/
78#include "SDL_stdinc.h"
79
80/*#define NDEBUG 1*/
81/*
82#include <assert.h>
83*/
84#define assert(X)
85
86
87#include "SDLOSXCAGuard.h"
88
89/*#warning Need a try-based Locker too*/
90/*=============================================================================
91 SDLOSXCAGuard
92 =============================================================================*/
93
94static int SDLOSXCAGuard_Lock(SDLOSXCAGuard *cag)
95{
96 int theAnswer = 0;
97
98 if(pthread_self() != cag->mOwner)
99 {
100 OSStatus theError = pthread_mutex_lock(&cag->mMutex);
101 (void)theError;
102 assert(theError == 0);
103 cag->mOwner = pthread_self();
104 theAnswer = 1;
105 }
106
107 return theAnswer;
108}
109
110static void SDLOSXCAGuard_Unlock(SDLOSXCAGuard *cag)
111{
112 OSStatus theError;
113 assert(pthread_self() == cag->mOwner);
114
115 cag->mOwner = 0;
116 theError = pthread_mutex_unlock(&cag->mMutex);
117 (void)theError;
118 assert(theError == 0);
119}
120
121static int SDLOSXCAGuard_Try (SDLOSXCAGuard *cag, int *outWasLocked)
122{
123 int theAnswer = 0;
124 *outWasLocked = 0;
125
126 if (pthread_self() == cag->mOwner) {
127 theAnswer = 1;
128 *outWasLocked = 0;
129 } else {
130 OSStatus theError = pthread_mutex_trylock(&cag->mMutex);
131 if (theError == 0) {
132 cag->mOwner = pthread_self();
133 theAnswer = 1;
134 *outWasLocked = 1;
135 }
136 }
137
138 return theAnswer;
139}
140
141static void SDLOSXCAGuard_Wait(SDLOSXCAGuard *cag)
142{
143 OSStatus theError;
144 assert(pthread_self() == cag->mOwner);
145
146 cag->mOwner = 0;
147
148 theError = pthread_cond_wait(&cag->mCondVar, &cag->mMutex);
149 (void)theError;
150 assert(theError == 0);
151 cag->mOwner = pthread_self();
152}
153
154static void SDLOSXCAGuard_Notify(SDLOSXCAGuard *cag)
155{
156 OSStatus theError = pthread_cond_signal(&cag->mCondVar);
157 (void)theError;
158 assert(theError == 0);
159}
160
161
162SDLOSXCAGuard *new_SDLOSXCAGuard(void)
163{
164 OSStatus theError;
165 SDLOSXCAGuard *cag = (SDLOSXCAGuard *) SDL_malloc(sizeof (SDLOSXCAGuard));
166 if (cag == NULL)
167 return NULL;
168 SDL_memset(cag, '\0', sizeof (*cag));
169
170 #define SET_SDLOSXCAGUARD_METHOD(m) cag->m = SDLOSXCAGuard_##m
171 SET_SDLOSXCAGUARD_METHOD(Lock);
172 SET_SDLOSXCAGUARD_METHOD(Unlock);
173 SET_SDLOSXCAGUARD_METHOD(Try);
174 SET_SDLOSXCAGUARD_METHOD(Wait);
175 SET_SDLOSXCAGUARD_METHOD(Notify);
176 #undef SET_SDLOSXCAGUARD_METHOD
177
178 theError = pthread_mutex_init(&cag->mMutex, NULL);
179 (void)theError;
180 assert(theError == 0);
181
182 theError = pthread_cond_init(&cag->mCondVar, NULL);
183 (void)theError;
184 assert(theError == 0);
185
186 cag->mOwner = 0;
187 return cag;
188}
189
190void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag)
191{
192 if (cag != NULL)
193 {
194 pthread_mutex_destroy(&cag->mMutex);
195 pthread_cond_destroy(&cag->mCondVar);
196 SDL_free(cag);
197 }
198}
199
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h b/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h
deleted file mode 100644
index f22c6956fe..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/SDLOSXCAGuard.h
+++ /dev/null
@@ -1,116 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/*
25 Note: This file hasn't been modified so technically we have to keep the disclaimer :-(
26
27
28 Copyright: © Copyright 2002 Apple Computer, Inc. All rights reserved.
29
30 Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc.
31 ("Apple") in consideration of your agreement to the following terms, and your
32 use, installation, modification or redistribution of this Apple software
33 constitutes acceptance of these terms. If you do not agree with these terms,
34 please do not use, install, modify or redistribute this Apple software.
35
36 In consideration of your agreement to abide by the following terms, and subject
37 to these terms, Apple grants you a personal, non-exclusive license, under AppleÕs
38 copyrights in this original Apple software (the "Apple Software"), to use,
39 reproduce, modify and redistribute the Apple Software, with or without
40 modifications, in source and/or binary forms; provided that if you redistribute
41 the Apple Software in its entirety and without modifications, you must retain
42 this notice and the following text and disclaimers in all such redistributions of
43 the Apple Software. Neither the name, trademarks, service marks or logos of
44 Apple Computer, Inc. may be used to endorse or promote products derived from the
45 Apple Software without specific prior written permission from Apple. Except as
46 expressly stated in this notice, no other rights or licenses, express or implied,
47 are granted by Apple herein, including but not limited to any patent rights that
48 may be infringed by your derivative works or by other works in which the Apple
49 Software may be incorporated.
50
51 The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO
52 WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
53 WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
54 PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
55 COMBINATION WITH YOUR PRODUCTS.
56
57 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
58 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
59 GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
61 OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
62 (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
63 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64*/
65/*=============================================================================
66 CAGuard.h
67
68=============================================================================*/
69#if !defined(__CAGuard_h__)
70#define __CAGuard_h__
71
72/*=============================================================================
73 Includes
74 =============================================================================*/
75
76#include <CoreAudio/CoreAudioTypes.h>
77#include <pthread.h>
78
79
80/*=============================================================================
81 CAGuard
82
83 This is your typical mutex with signalling implemented via pthreads.
84 Lock() will return true if and only if the guard is locked on that call.
85 A thread that already has the guard will receive 'false' if it locks it
86 again. Use of the stack-based CAGuard::Locker class is highly recommended
87 to properly manage the recursive nesting. The Wait calls with timeouts
88 will return true if and only if the timeout period expired. They will
89 return false if they receive notification any other way.
90 =============================================================================*/
91
92typedef struct S_SDLOSXCAGuard
93{
94
95/* Construction/Destruction */
96/*public:*/
97/* Actions */
98/*public:*/
99 int (*Lock)(struct S_SDLOSXCAGuard *cag);
100 void (*Unlock)(struct S_SDLOSXCAGuard *cag);
101 int (*Try)(struct S_SDLOSXCAGuard *cag, int *outWasLocked); /* returns true if lock is free, false if not */
102 void (*Wait)(struct S_SDLOSXCAGuard *cag);
103 void (*Notify)(struct S_SDLOSXCAGuard *cag);
104
105/* Implementation */
106/*protected:*/
107 pthread_mutex_t mMutex;
108 pthread_cond_t mCondVar;
109 pthread_t mOwner;
110} SDLOSXCAGuard;
111
112SDLOSXCAGuard *new_SDLOSXCAGuard(void);
113void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag);
114
115#endif
116
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c
deleted file mode 100644
index 5018750222..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom.c
+++ /dev/null
@@ -1,514 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_MACOSX
25
26#include "SDL_syscdrom_c.h"
27
28#pragma mark -- Globals --
29
30static FSRef** tracks;
31static FSVolumeRefNum* volumes;
32static CDstatus status;
33static int nextTrackFrame;
34static int nextTrackFramesRemaining;
35static int fakeCD;
36static int currentTrack;
37static int didReadTOC;
38static int cacheTOCNumTracks;
39static int currentDrive; /* Only allow 1 drive in use at a time */
40
41#pragma mark -- Prototypes --
42
43static const char *SDL_SYS_CDName (int drive);
44static int SDL_SYS_CDOpen (int drive);
45static int SDL_SYS_CDGetTOC (SDL_CD *cdrom);
46static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position);
47static int SDL_SYS_CDPlay (SDL_CD *cdrom, int start, int length);
48static int SDL_SYS_CDPause (SDL_CD *cdrom);
49static int SDL_SYS_CDResume (SDL_CD *cdrom);
50static int SDL_SYS_CDStop (SDL_CD *cdrom);
51static int SDL_SYS_CDEject (SDL_CD *cdrom);
52static void SDL_SYS_CDClose (SDL_CD *cdrom);
53
54#pragma mark -- Helper Functions --
55
56/* Read a list of tracks from the volume */
57static int LoadTracks (SDL_CD *cdrom)
58{
59 /* Check if tracks are already loaded */
60 if ( tracks[cdrom->id] != NULL )
61 return 0;
62
63 /* Allocate memory for tracks */
64 tracks[cdrom->id] = (FSRef*) SDL_calloc (1, sizeof(**tracks) * cdrom->numtracks);
65 if (tracks[cdrom->id] == NULL) {
66 SDL_OutOfMemory ();
67 return -1;
68 }
69
70 /* Load tracks */
71 if (ListTrackFiles (volumes[cdrom->id], tracks[cdrom->id], cdrom->numtracks) < 0)
72 return -1;
73
74 return 0;
75}
76
77/* Find a file for a given start frame and length */
78static FSRef* GetFileForOffset (SDL_CD *cdrom, int start, int length, int *outStartFrame, int *outStopFrame)
79{
80 int i;
81
82 for (i = 0; i < cdrom->numtracks; i++) {
83
84 if (cdrom->track[i].offset <= start &&
85 start < (cdrom->track[i].offset + cdrom->track[i].length))
86 break;
87 }
88
89 if (i == cdrom->numtracks)
90 return NULL;
91
92 currentTrack = i;
93
94 *outStartFrame = start - cdrom->track[i].offset;
95
96 if ((*outStartFrame + length) < cdrom->track[i].length) {
97 *outStopFrame = *outStartFrame + length;
98 length = 0;
99 nextTrackFrame = -1;
100 nextTrackFramesRemaining = -1;
101 }
102 else {
103 *outStopFrame = -1;
104 length -= cdrom->track[i].length - *outStartFrame;
105 nextTrackFrame = cdrom->track[i+1].offset;
106 nextTrackFramesRemaining = length;
107 }
108
109 return &tracks[cdrom->id][i];
110}
111
112/* Setup another file for playback, or stop playback (called from another thread) */
113static void CompletionProc (SDL_CD *cdrom)
114{
115
116 Lock ();
117
118 if (nextTrackFrame > 0 && nextTrackFramesRemaining > 0) {
119
120 /* Load the next file to play */
121 int startFrame, stopFrame;
122 FSRef *file;
123
124 PauseFile ();
125 ReleaseFile ();
126
127 file = GetFileForOffset (cdrom, nextTrackFrame,
128 nextTrackFramesRemaining, &startFrame, &stopFrame);
129
130 if (file == NULL) {
131 status = CD_STOPPED;
132 Unlock ();
133 return;
134 }
135
136 LoadFile (file, startFrame, stopFrame);
137
138 SetCompletionProc (CompletionProc, cdrom);
139
140 PlayFile ();
141 }
142 else {
143
144 /* Release the current file */
145 PauseFile ();
146 ReleaseFile ();
147 status = CD_STOPPED;
148 }
149
150 Unlock ();
151}
152
153
154#pragma mark -- Driver Functions --
155
156/* Initialize */
157int SDL_SYS_CDInit (void)
158{
159 /* Initialize globals */
160 volumes = NULL;
161 tracks = NULL;
162 status = CD_STOPPED;
163 nextTrackFrame = -1;
164 nextTrackFramesRemaining = -1;
165 fakeCD = SDL_FALSE;
166 currentTrack = -1;
167 didReadTOC = SDL_FALSE;
168 cacheTOCNumTracks = -1;
169 currentDrive = -1;
170
171 /* Fill in function pointers */
172 SDL_CDcaps.Name = SDL_SYS_CDName;
173 SDL_CDcaps.Open = SDL_SYS_CDOpen;
174 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
175 SDL_CDcaps.Status = SDL_SYS_CDStatus;
176 SDL_CDcaps.Play = SDL_SYS_CDPlay;
177 SDL_CDcaps.Pause = SDL_SYS_CDPause;
178 SDL_CDcaps.Resume = SDL_SYS_CDResume;
179 SDL_CDcaps.Stop = SDL_SYS_CDStop;
180 SDL_CDcaps.Eject = SDL_SYS_CDEject;
181 SDL_CDcaps.Close = SDL_SYS_CDClose;
182
183 /*
184 Read the list of "drives"
185
186 This is currently a hack that infers drives from
187 mounted audio CD volumes, rather than
188 actual CD-ROM devices - which means it may not
189 act as expected sometimes.
190 */
191
192 /* Find out how many cd volumes are mounted */
193 SDL_numcds = DetectAudioCDVolumes (NULL, 0);
194
195 /*
196 If there are no volumes, fake a cd device
197 so tray empty can be reported.
198 */
199 if (SDL_numcds == 0) {
200
201 fakeCD = SDL_TRUE;
202 SDL_numcds = 1;
203 status = CD_TRAYEMPTY;
204
205 return 0;
206 }
207
208 /* Allocate space for volumes */
209 volumes = (FSVolumeRefNum*) SDL_calloc (1, sizeof(*volumes) * SDL_numcds);
210 if (volumes == NULL) {
211 SDL_OutOfMemory ();
212 return -1;
213 }
214
215 /* Allocate space for tracks */
216 tracks = (FSRef**) SDL_calloc (1, sizeof(*tracks) * (SDL_numcds + 1));
217 if (tracks == NULL) {
218 SDL_OutOfMemory ();
219 return -1;
220 }
221
222 /* Mark the end of the tracks array */
223 tracks[ SDL_numcds ] = (FSRef*)-1;
224
225 /*
226 Redetect, now save all volumes for later
227 Update SDL_numcds just in case it changed
228 */
229 {
230 int numVolumes = SDL_numcds;
231
232 SDL_numcds = DetectAudioCDVolumes (volumes, numVolumes);
233
234 /* If more cds suddenly show up, ignore them */
235 if (SDL_numcds > numVolumes) {
236 SDL_SetError ("Some CD's were added but they will be ignored");
237 SDL_numcds = numVolumes;
238 }
239 }
240
241 return 0;
242}
243
244/* Shutdown and cleanup */
245void SDL_SYS_CDQuit(void)
246{
247 ReleaseFile();
248
249 if (volumes != NULL)
250 free (volumes);
251
252 if (tracks != NULL) {
253
254 FSRef **ptr;
255 for (ptr = tracks; *ptr != (FSRef*)-1; ptr++)
256 if (*ptr != NULL)
257 free (*ptr);
258
259 free (tracks);
260 }
261}
262
263/* Get the Unix disk name of the volume */
264static const char *SDL_SYS_CDName (int drive)
265{
266 /*
267 * !!! FIXME: PBHGetVolParmsSync() is gone in 10.6,
268 * !!! FIXME: replaced with FSGetVolumeParms(), which
269 * !!! FIXME: isn't available before 10.5. :/
270 */
271 return "Mac OS X CD-ROM Device";
272
273#if 0
274 OSStatus err = noErr;
275 HParamBlockRec pb;
276 GetVolParmsInfoBuffer volParmsInfo;
277
278 if (fakeCD)
279 return "Fake CD-ROM Device";
280
281 pb.ioParam.ioNamePtr = NULL;
282 pb.ioParam.ioVRefNum = volumes[drive];
283 pb.ioParam.ioBuffer = (Ptr)&volParmsInfo;
284 pb.ioParam.ioReqCount = (SInt32)sizeof(volParmsInfo);
285 err = PBHGetVolParmsSync(&pb);
286
287 if (err != noErr) {
288 SDL_SetError ("PBHGetVolParmsSync returned %d", err);
289 return NULL;
290 }
291
292 return volParmsInfo.vMDeviceID;
293#endif
294}
295
296/* Open the "device" */
297static int SDL_SYS_CDOpen (int drive)
298{
299 /* Only allow 1 device to be open */
300 if (currentDrive >= 0) {
301 SDL_SetError ("Only one cdrom is supported");
302 return -1;
303 }
304 else
305 currentDrive = drive;
306
307 return drive;
308}
309
310/* Get the table of contents */
311static int SDL_SYS_CDGetTOC (SDL_CD *cdrom)
312{
313 if (fakeCD) {
314 SDL_SetError (kErrorFakeDevice);
315 return -1;
316 }
317
318 if (didReadTOC) {
319 cdrom->numtracks = cacheTOCNumTracks;
320 return 0;
321 }
322
323
324 ReadTOCData (volumes[cdrom->id], cdrom);
325 didReadTOC = SDL_TRUE;
326 cacheTOCNumTracks = cdrom->numtracks;
327
328 return 0;
329}
330
331/* Get CD-ROM status */
332static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position)
333{
334 if (position) {
335 int trackFrame;
336
337 Lock ();
338 trackFrame = GetCurrentFrame ();
339 Unlock ();
340
341 *position = cdrom->track[currentTrack].offset + trackFrame;
342 }
343
344 return status;
345}
346
347/* Start playback */
348static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
349{
350 int startFrame, stopFrame;
351 FSRef *ref;
352
353 if (fakeCD) {
354 SDL_SetError (kErrorFakeDevice);
355 return -1;
356 }
357
358 Lock();
359
360 if (LoadTracks (cdrom) < 0)
361 return -2;
362
363 if (PauseFile () < 0)
364 return -3;
365
366 if (ReleaseFile () < 0)
367 return -4;
368
369 ref = GetFileForOffset (cdrom, start, length, &startFrame, &stopFrame);
370 if (ref == NULL) {
371 SDL_SetError ("SDL_SYS_CDPlay: No file for start=%d, length=%d", start, length);
372 return -5;
373 }
374
375 if (LoadFile (ref, startFrame, stopFrame) < 0)
376 return -6;
377
378 SetCompletionProc (CompletionProc, cdrom);
379
380 if (PlayFile () < 0)
381 return -7;
382
383 status = CD_PLAYING;
384
385 Unlock();
386
387 return 0;
388}
389
390/* Pause playback */
391static int SDL_SYS_CDPause(SDL_CD *cdrom)
392{
393 if (fakeCD) {
394 SDL_SetError (kErrorFakeDevice);
395 return -1;
396 }
397
398 Lock ();
399
400 if (PauseFile () < 0) {
401 Unlock ();
402 return -2;
403 }
404
405 status = CD_PAUSED;
406
407 Unlock ();
408
409 return 0;
410}
411
412/* Resume playback */
413static int SDL_SYS_CDResume(SDL_CD *cdrom)
414{
415 if (fakeCD) {
416 SDL_SetError (kErrorFakeDevice);
417 return -1;
418 }
419
420 Lock ();
421
422 if (PlayFile () < 0) {
423 Unlock ();
424 return -2;
425 }
426
427 status = CD_PLAYING;
428
429 Unlock ();
430
431 return 0;
432}
433
434/* Stop playback */
435static int SDL_SYS_CDStop(SDL_CD *cdrom)
436{
437 if (fakeCD) {
438 SDL_SetError (kErrorFakeDevice);
439 return -1;
440 }
441
442 Lock ();
443
444 if (PauseFile () < 0) {
445 Unlock ();
446 return -2;
447 }
448
449 if (ReleaseFile () < 0) {
450 Unlock ();
451 return -3;
452 }
453
454 status = CD_STOPPED;
455
456 Unlock ();
457
458 return 0;
459}
460
461/* Eject the CD-ROM (Unmount the volume) */
462static int SDL_SYS_CDEject(SDL_CD *cdrom)
463{
464 OSStatus err;
465 pid_t dissenter;
466
467 if (fakeCD) {
468 SDL_SetError (kErrorFakeDevice);
469 return -1;
470 }
471
472 Lock ();
473
474 if (PauseFile () < 0) {
475 Unlock ();
476 return -2;
477 }
478
479 if (ReleaseFile () < 0) {
480 Unlock ();
481 return -3;
482 }
483
484 status = CD_STOPPED;
485
486 /* Eject the volume */
487 err = FSEjectVolumeSync(volumes[cdrom->id], kNilOptions, &dissenter);
488
489 if (err != noErr) {
490 Unlock ();
491 SDL_SetError ("PBUnmountVol returned %d", err);
492 return -4;
493 }
494
495 status = CD_TRAYEMPTY;
496
497 /* Invalidate volume and track info */
498 volumes[cdrom->id] = 0;
499 free (tracks[cdrom->id]);
500 tracks[cdrom->id] = NULL;
501
502 Unlock ();
503
504 return 0;
505}
506
507/* Close the CD-ROM */
508static void SDL_SYS_CDClose(SDL_CD *cdrom)
509{
510 currentDrive = -1;
511 return;
512}
513
514#endif /* SDL_CDROM_MACOSX */
diff --git a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h b/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h
deleted file mode 100644
index 589c5897e6..0000000000
--- a/apps/plugins/sdl/src/cdrom/macosx/SDL_syscdrom_c.h
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24/* This is the Mac OS X / CoreAudio specific header for the SDL CD-ROM API
25 Contributed by Darrell Walisser and Max Horn
26 */
27
28/***********************************************************************************
29 Implementation Notes
30 *********************
31
32 This code has several limitations currently (all of which are proabaly fixable):
33
34 1. A CD-ROM device is inferred from a mounted cdfs volume, so device 0 is
35 not necessarily the first CD-ROM device on the system. (Somewhat easy to fix
36 by useing the device name from the volume id's to reorder the volumes)
37
38 2. You can only open and control 1 CD-ROM device at a time. (Challenging to fix,
39 due to extensive code restructuring)
40
41 3. The status reported by SDL_CDStatus only changes to from CD_PLAYING to CD_STOPPED in
42 1-second intervals (because the audio is buffered in 1-second chunks) If
43 the audio data is less than 1 second, the remainder is filled with silence.
44
45 If you need to play sequences back-to-back that are less that 1 second long,
46 use the frame position to determine when to play the next sequence, instead
47 of SDL_CDStatus.
48
49 This may be possible to fix with a clever usage of the AudioUnit API.
50
51 4. When new volumes are inserted, our volume information is not updated. The only way
52 to refresh this information is to reinit the CD-ROM subsystem of SDL. To fix this,
53 one would probably have to fix point 1 above first, then figure out how to register
54 for a notification when new media is mounted in order to perform an automatic
55 rescan for cdfs volumes.
56
57
58
59 So, here comes a description of how this all works.
60
61 < Initializing >
62
63 To get things rolling, we have to locate mounted volumes that contain
64 audio (since nearly all Macs don't have analog audio-in on the sound card).
65 That's easy, since these volumes have a flag that indicates this special
66 filesystem. See DetectAudioCDVolumes() in CDPlayer.cpp for this code.
67
68 Next, we parse the invisible .TOC.plist in the root of the volume, which gets us
69 the track information (number, offset, length, leadout, etc). See ReadTOCData() in
70 CDPlayer.cpp for the skinny on this.
71
72
73 < The Playback Loop >
74
75 Now come the tricky parts. Let's start with basic audio playback. When a frame
76 range to play is requested, we must first find the .aiff files on the volume,
77 hopefully in the right order. Since these files all begin with a number "1 Audio Track",
78 etc, this is used to determine the correct track order.
79
80 Once all files are determined, we have to find what file corresponds to the start
81 and length parameter to SDL_SYS_CDPlay(). Again, this is quite simple by walking the
82 cdrom's track list. At this point, we also save the offset to the next track and frames
83 remaining, if we're going to have to play another file after the first one. See
84 GetFileForOffset() for this code.
85
86 At this point we have all info needed to start playback, so we hand off to the LoadFile()
87 function, which proceeds to do its magic and plays back the file.
88
89 When the file is finished playing, CompletionProc() is invoked, at which time we can
90 play the next file if the previously saved next track and frames remaining
91 indicates that we should.
92
93
94 < Magic >
95
96 OK, so it's not really magic, but since I don't fully understand all the hidden details it
97 seems like it to me ;-) The API's involved are the AudioUnit and AudioFile API's. These
98 appear to be an extension of CoreAudio for creating modular playback and f/x entities.
99 The important thing is that CPU usage is very low and reliability is very high. You'd
100 be hard-pressed to find a way to stutter the playback with other CPU-intensive tasks.
101
102 One part of this magic is that it uses multiple threads, which carries the usual potential
103 for disaster if not handled carefully. Playback currently requires 4 additional threads:
104 1. The coreaudio runloop thread
105 2. The coreaudio device i/o thread
106 3. The file streaming thread
107 4. The notification/callback thread
108
109 The first 2 threads are necessary evil - CoreAudio creates this no matter what the situation
110 is (even the SDL sound implementation creates theses suckers). The last two are are created
111 by us.
112
113 The file is streamed from disk using a threaded double-buffer approach.
114 This way, the high latency operation of reading from disk can be performed without interrupting
115 the real-time device thread (which amounts to avoiding dropouts). The device thread grabs the
116 buffer that isn't being read and sends it to the CoreAudio mixer where it eventually gets
117 to the sound card.
118
119 The device thread posts a notification when the file streaming thread is out of data. This
120 notification must be handled in a separate thread to avoid potential deadlock in the
121 device thread. That's where the notification thread comes in. This thread is signaled
122 whenever a notification needs to be processed, so another file can be played back if need be.
123
124 The API in CDPlayer.cpp contains synchronization because otherwise both the notification thread
125 and main thread (or another other thread using the SDL CD api) can potentially call it at the same time.
126
127************************************************************************************/
128
129
130#include "SDL_cdrom.h"
131#include "../SDL_syscdrom.h"
132
133#include "CDPlayer.h"
134
135#define kErrorFakeDevice "Error: Cannot proceed since we're faking a CD-ROM device. Reinit the CD-ROM subsystem to scan for new volumes."
136
diff --git a/apps/plugins/sdl/src/cdrom/mint/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/mint/SDL_syscdrom.c
deleted file mode 100644
index 0bc10edb72..0000000000
--- a/apps/plugins/sdl/src/cdrom/mint/SDL_syscdrom.c
+++ /dev/null
@@ -1,317 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_MINT
25
26/*
27 Atari MetaDOS CD-ROM functions
28
29 Patrice Mandin
30*/
31
32#include <errno.h>
33
34#include <mint/cdromio.h>
35#include <mint/metados.h>
36
37#include "SDL_cdrom.h"
38#include "../SDL_syscdrom.h"
39
40/* Some ioctl() errno values which occur when the tray is empty */
41#ifndef ENOMEDIUM
42#define ENOMEDIUM ENOENT
43#endif
44#define ERRNO_TRAYEMPTY(errno) \
45 ((errno == EIO) || (errno == ENOENT) || \
46 (errno == EINVAL) || (errno == ENOMEDIUM))
47
48/* The maximum number of CD-ROM drives we'll detect */
49#define MAX_DRIVES 32
50
51typedef struct {
52 char device[3]; /* Physical device letter + ':' + '\0' */
53 metaopen_t metaopen; /* Infos on opened drive */
54} metados_drive_t;
55
56static metados_drive_t metados_drives[MAX_DRIVES];
57
58/* The system-dependent CD control functions */
59static const char *SDL_SYS_CDName(int drive);
60static int SDL_SYS_CDOpen(int drive);
61static void SDL_SYS_CDClose(SDL_CD *cdrom);
62static int SDL_SYS_CDioctl(int id, int command, void *arg);
63static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
64static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
65static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
66static int SDL_SYS_CDPause(SDL_CD *cdrom);
67static int SDL_SYS_CDResume(SDL_CD *cdrom);
68static int SDL_SYS_CDStop(SDL_CD *cdrom);
69static int SDL_SYS_CDEject(SDL_CD *cdrom);
70
71int SDL_SYS_CDInit(void)
72{
73 metainit_t metainit={0,0,0,0};
74 metaopen_t metaopen;
75 int i, handle;
76 struct cdrom_subchnl info;
77
78 Metainit(&metainit);
79 if (metainit.version == NULL) {
80#ifdef DEBUG_CDROM
81 fprintf(stderr, "MetaDOS not installed\n");
82#endif
83 return -1;
84 }
85
86 if (metainit.drives_map == 0) {
87#ifdef DEBUG_CDROM
88 fprintf(stderr, "No MetaDOS devices present\n");
89#endif
90 return -1;
91 }
92
93 SDL_numcds = 0;
94
95 for (i='A'; i<='Z'; i++) {
96 metados_drives[SDL_numcds].device[0] = 0;
97 metados_drives[SDL_numcds].device[1] = ':';
98 metados_drives[SDL_numcds].device[2] = 0;
99
100 if (metainit.drives_map & (1<<(i-'A'))) {
101 handle = Metaopen(i, &metaopen);
102 if (handle == 0) {
103
104 info.cdsc_format = CDROM_MSF;
105 if ( (Metaioctl(i, METADOS_IOCTL_MAGIC, CDROMSUBCHNL, &info) == 0) || ERRNO_TRAYEMPTY(errno) ) {
106 metados_drives[SDL_numcds].device[0] = i;
107 ++SDL_numcds;
108 }
109
110 Metaclose(i);
111 }
112 }
113 }
114
115 /* Fill in our driver capabilities */
116 SDL_CDcaps.Name = SDL_SYS_CDName;
117 SDL_CDcaps.Open = SDL_SYS_CDOpen;
118 SDL_CDcaps.Close = SDL_SYS_CDClose;
119
120 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
121 SDL_CDcaps.Status = SDL_SYS_CDStatus;
122 SDL_CDcaps.Play = SDL_SYS_CDPlay;
123 SDL_CDcaps.Pause = SDL_SYS_CDPause;
124 SDL_CDcaps.Resume = SDL_SYS_CDResume;
125 SDL_CDcaps.Stop = SDL_SYS_CDStop;
126 SDL_CDcaps.Eject = SDL_SYS_CDEject;
127
128 return 0;
129}
130
131void SDL_SYS_CDQuit(void)
132{
133 SDL_numcds = 0;
134}
135
136static const char *SDL_SYS_CDName(int drive)
137{
138 return(metados_drives[drive].device);
139}
140
141static int SDL_SYS_CDOpen(int drive)
142{
143 int handle;
144
145 handle = Metaopen(metados_drives[drive].device[0], &(metados_drives[drive].metaopen));
146 if (handle == 0) {
147 return drive;
148 }
149
150 return -1;
151}
152
153static void SDL_SYS_CDClose(SDL_CD *cdrom)
154{
155 Metaclose(metados_drives[cdrom->id].device[0]);
156}
157
158static int SDL_SYS_CDioctl(int id, int command, void *arg)
159{
160 int retval;
161
162 retval = Metaioctl(metados_drives[id].device[0], METADOS_IOCTL_MAGIC, command, arg);
163 if ( retval < 0 ) {
164 SDL_SetError("ioctl() error: %s", strerror(errno));
165 }
166 return(retval);
167}
168
169static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
170{
171 int i,okay;
172 struct cdrom_tochdr toc;
173 struct cdrom_tocentry entry;
174
175 /* Use standard ioctl() */
176 if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)<0) {
177 return -1;
178 }
179
180 cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1;
181 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
182 cdrom->numtracks = SDL_MAX_TRACKS;
183 }
184
185 /* Read all the track TOC entries */
186 okay=1;
187 for ( i=0; i<=cdrom->numtracks; ++i ) {
188 if ( i == cdrom->numtracks ) {
189 cdrom->track[i].id = CDROM_LEADOUT;
190 } else {
191 cdrom->track[i].id = toc.cdth_trk0+i;
192 }
193 entry.cdte_track = cdrom->track[i].id;
194 entry.cdte_format = CDROM_MSF;
195 if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY, &entry) < 0 ) {
196 okay=0;
197 break;
198 } else {
199 if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) {
200 cdrom->track[i].type = SDL_DATA_TRACK;
201 } else {
202 cdrom->track[i].type = SDL_AUDIO_TRACK;
203 }
204 cdrom->track[i].offset = MSF_TO_FRAMES(
205 entry.cdte_addr.msf.minute,
206 entry.cdte_addr.msf.second,
207 entry.cdte_addr.msf.frame);
208 cdrom->track[i].length = 0;
209 if ( i > 0 ) {
210 cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset;
211 }
212 }
213 }
214
215 return(okay ? 0 : -1);
216}
217
218/* Get CD-ROM status */
219static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
220{
221 CDstatus status;
222 struct cdrom_tochdr toc;
223 struct cdrom_subchnl info;
224
225 info.cdsc_format = CDROM_MSF;
226 if ( SDL_SYS_CDioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) {
227 if ( ERRNO_TRAYEMPTY(errno) ) {
228 status = CD_TRAYEMPTY;
229 } else {
230 status = CD_ERROR;
231 }
232 } else {
233 switch (info.cdsc_audiostatus) {
234 case CDROM_AUDIO_INVALID:
235 case CDROM_AUDIO_NO_STATUS:
236 /* Try to determine if there's a CD available */
237 if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) {
238 status = CD_STOPPED;
239 } else {
240 status = CD_TRAYEMPTY;
241 }
242 break;
243 case CDROM_AUDIO_COMPLETED:
244 status = CD_STOPPED;
245 break;
246 case CDROM_AUDIO_PLAY:
247 status = CD_PLAYING;
248 break;
249 case CDROM_AUDIO_PAUSED:
250 /* Workaround buggy CD-ROM drive */
251 if ( info.cdsc_trk == CDROM_LEADOUT ) {
252 status = CD_STOPPED;
253 } else {
254 status = CD_PAUSED;
255 }
256 break;
257 default:
258 status = CD_ERROR;
259 break;
260 }
261 }
262 if ( position ) {
263 if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
264 *position = MSF_TO_FRAMES(
265 info.cdsc_absaddr.msf.minute,
266 info.cdsc_absaddr.msf.second,
267 info.cdsc_absaddr.msf.frame);
268 } else {
269 *position = 0;
270 }
271 }
272 return(status);
273}
274
275/* Start play */
276static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
277{
278 struct cdrom_msf playtime;
279
280 FRAMES_TO_MSF(start,
281 &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0);
282 FRAMES_TO_MSF(start+length,
283 &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1);
284#ifdef DEBUG_CDROM
285 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
286 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
287 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
288#endif
289
290 return SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime);
291}
292
293/* Pause play */
294static int SDL_SYS_CDPause(SDL_CD *cdrom)
295{
296 return SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0);
297}
298
299/* Resume play */
300static int SDL_SYS_CDResume(SDL_CD *cdrom)
301{
302 return SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0);
303}
304
305/* Stop play */
306static int SDL_SYS_CDStop(SDL_CD *cdrom)
307{
308 return SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0);
309}
310
311/* Eject the CD-ROM */
312static int SDL_SYS_CDEject(SDL_CD *cdrom)
313{
314 return SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0);
315}
316
317#endif /* SDL_CDROM_MINT */
diff --git a/apps/plugins/sdl/src/cdrom/openbsd/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/openbsd/SDL_syscdrom.c
deleted file mode 100644
index e4d03a6a37..0000000000
--- a/apps/plugins/sdl/src/cdrom/openbsd/SDL_syscdrom.c
+++ /dev/null
@@ -1,416 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_OPENBSD
25
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>
34#include <sys/ioctl.h>
35#include <sys/cdio.h>
36
37#include "SDL_cdrom.h"
38#include "../SDL_syscdrom.h"
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 */
45static char *SDL_cdlist[MAX_DRIVES];
46static dev_t SDL_cdmode[MAX_DRIVES];
47
48/* The system-dependent CD control functions */
49static const char *SDL_SYS_CDName(int drive);
50static int SDL_SYS_CDOpen(int drive);
51static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
52static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
53static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
54static int SDL_SYS_CDPause(SDL_CD *cdrom);
55static int SDL_SYS_CDResume(SDL_CD *cdrom);
56static int SDL_SYS_CDStop(SDL_CD *cdrom);
57static int SDL_SYS_CDEject(SDL_CD *cdrom);
58static 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) \
62 ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL) || \
63 (errno == ENODEV))
64
65/* Check a drive to see if it is a CD-ROM */
66static 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 }
95 else if (ERRNO_TRAYEMPTY(errno))
96 is_cd = 1;
97 }
98 return(is_cd);
99}
100
101/* Add a CD-ROM drive to our list of valid drives */
102static 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;
121 SDL_cdlist[i] = SDL_strdup(drive);
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
134int SDL_SYS_CDInit(void)
135{
136 static char *checklist[] = {
137#if defined(__OPENBSD__)
138 "?0 cd?c", "cdrom", NULL
139#elif defined(__NETBSD__)
140 "?0 cd?d", "?0 cd?c", "cdrom", NULL
141#else
142 "?0 cd?c", "?0 acd?c", "cdrom", NULL
143#endif
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 */
163 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
164 if ( SDLcdrom != NULL ) {
165 char *cdpath, *delim;
166 size_t len = SDL_strlen(SDLcdrom)+1;
167 cdpath = SDL_stack_alloc(char, len);
168 if ( cdpath != NULL ) {
169 SDL_strlcpy(cdpath, SDLcdrom, len);
170 SDLcdrom = cdpath;
171 do {
172 delim = SDL_strchr(SDLcdrom, ':');
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 );
185 SDL_stack_free(cdpath);
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 ) {
200 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]);
201 insert = SDL_strchr(drive, '?');
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 {
220 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
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 */
230static 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
241static const char *SDL_SYS_CDName(int drive)
242{
243 return(SDL_cdlist[drive]);
244}
245
246static int SDL_SYS_CDOpen(int drive)
247{
248 return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0));
249}
250
251static 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 */
300static 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 */
356static 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 */
374static int SDL_SYS_CDPause(SDL_CD *cdrom)
375{
376 return(SDL_SYS_CDioctl(cdrom->id, CDIOCPAUSE, 0));
377}
378
379/* Resume play */
380static int SDL_SYS_CDResume(SDL_CD *cdrom)
381{
382 return(SDL_SYS_CDioctl(cdrom->id, CDIOCRESUME, 0));
383}
384
385/* Stop play */
386static int SDL_SYS_CDStop(SDL_CD *cdrom)
387{
388 return(SDL_SYS_CDioctl(cdrom->id, CDIOCSTOP, 0));
389}
390
391/* Eject the CD-ROM */
392static int SDL_SYS_CDEject(SDL_CD *cdrom)
393{
394 SDL_SYS_CDioctl(cdrom->id, CDIOCALLOW, 0);
395 return(SDL_SYS_CDioctl(cdrom->id, CDIOCEJECT, 0));
396}
397
398/* Close the CD-ROM handle */
399static void SDL_SYS_CDClose(SDL_CD *cdrom)
400{
401 close(cdrom->id);
402}
403
404void SDL_SYS_CDQuit(void)
405{
406 int i;
407
408 if ( SDL_numcds > 0 ) {
409 for ( i=0; i<SDL_numcds; ++i ) {
410 SDL_free(SDL_cdlist[i]);
411 }
412 SDL_numcds = 0;
413 }
414}
415
416#endif /* SDL_CDROM_OPENBSD */
diff --git a/apps/plugins/sdl/src/cdrom/os2/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/os2/SDL_syscdrom.c
deleted file mode 100644
index 6ed9c658fb..0000000000
--- a/apps/plugins/sdl/src/cdrom/os2/SDL_syscdrom.c
+++ /dev/null
@@ -1,393 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_OS2
25
26/* Functions for system-level CD-ROM audio control */
27
28#define INCL_MCIOS2
29#include <os2.h>
30#include <os2me.h>
31
32#include "SDL_cdrom.h"
33#include "../SDL_syscdrom.h"
34
35/* Size of MCI result buffer (in bytes) */
36#define MCI_CMDRETBUFSIZE 128
37
38/* The maximum number of CD-ROM drives we'll detect */
39#define MAX_DRIVES 16
40
41/* A list of available CD-ROM drives */
42static char *SDL_cdlist[MAX_DRIVES];
43//static dev_t SDL_cdmode[MAX_DRIVES];
44
45/* The system-dependent CD control functions */
46static const char *SDL_SYS_CDName(int drive);
47static int SDL_SYS_CDOpen(int drive);
48static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
49static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
50static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
51static int SDL_SYS_CDPause(SDL_CD *cdrom);
52static int SDL_SYS_CDResume(SDL_CD *cdrom);
53static int SDL_SYS_CDStop(SDL_CD *cdrom);
54static int SDL_SYS_CDEject(SDL_CD *cdrom);
55static void SDL_SYS_CDClose(SDL_CD *cdrom);
56
57/* MCI Timing Functions */
58#define MCI_MMTIMEPERSECOND 3000
59#define FRAMESFROMMM(mmtime) (((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND)
60
61
62/* Ready for MCI CDAudio Devices */
63int SDL_SYS_CDInit(void)
64{
65int i; /* generig counter */
66MCI_SYSINFO_PARMS msp; /* Structure to MCI SysInfo parameters */
67CHAR SysInfoRet[MCI_CMDRETBUFSIZE]; /* Buffer for MCI Command result */
68
69/* Fill in our driver capabilities */
70SDL_CDcaps.Name = SDL_SYS_CDName;
71SDL_CDcaps.Open = SDL_SYS_CDOpen;
72SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
73SDL_CDcaps.Status = SDL_SYS_CDStatus;
74SDL_CDcaps.Play = SDL_SYS_CDPlay;
75SDL_CDcaps.Pause = SDL_SYS_CDPause;
76SDL_CDcaps.Resume = SDL_SYS_CDResume;
77SDL_CDcaps.Stop = SDL_SYS_CDStop;
78SDL_CDcaps.Eject = SDL_SYS_CDEject;
79SDL_CDcaps.Close = SDL_SYS_CDClose;
80
81/* Get the number of CD ROMs in the System */
82/* Clean SysInfo structure */
83SDL_memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));
84/* Prepare structure to Ask Numer of Audio CDs */
85msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
86msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
87msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
88if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
89SDL_numcds = atoi(SysInfoRet);
90if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */
91
92/* Get and Add their system name to the SDL_cdlist */
93msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
94msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
95msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
96for (i=0; i<SDL_numcds; i++)
97 {
98 msp.ulNumber = i+1;
99 mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0);
100 SDL_cdlist[i] = SDL_strdup(SysInfoRet);
101 if ( SDL_cdlist[i] == NULL )
102 {
103 SDL_OutOfMemory();
104 return(-1);
105 }
106 }
107return(0);
108}
109
110/* Return CDAudio System Dependent Device Name - Ready for MCI*/
111static const char *SDL_SYS_CDName(int drive)
112{
113return(SDL_cdlist[drive]);
114}
115
116/* Open CDAudio Device - Ready for MCI */
117static int SDL_SYS_CDOpen(int drive)
118{
119MCI_OPEN_PARMS mop;
120MCI_SET_PARMS msp;
121MCI_GENERIC_PARMS mgp;
122
123/* Open the device */
124mop.hwndCallback = (HWND)NULL; // None
125mop.usDeviceID = (USHORT)NULL; // Will be returned.
126mop.pszDeviceType = (PSZ)SDL_cdlist[drive]; // CDAudio Device
127if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
128/* Set time format */
129msp.hwndCallback = (HWND)NULL; // None
130msp.ulTimeFormat = MCI_FORMAT_MSF; // Minute : Second : Frame structure
131msp.ulSpeedFormat = (ULONG)NULL; // No change
132msp.ulAudio = (ULONG)NULL; // No Channel
133msp.ulLevel = (ULONG)NULL; // No Volume
134msp.ulOver = (ULONG)NULL; // No Delay
135msp.ulItem = (ULONG)NULL; // No item
136msp.ulValue = (ULONG)NULL; // No value for item flag
137if (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID);
138/* Error setting time format? - Close opened device */
139mgp.hwndCallback = (HWND)NULL; // None
140mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);
141return(CD_ERROR);
142}
143
144/* Get CD Table Of Contents - Ready for MCI */
145static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
146{
147MCI_TOC_PARMS mtp;
148MCI_STATUS_PARMS msp;
149MCI_TOC_REC * mtr;
150INT i;
151
152/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */
153if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;
154
155/* Get Number of Tracks */
156msp.hwndCallback = (HWND)NULL; /* None */
157msp.ulReturn = (ULONG)NULL; /* We want this information */
158msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;
159msp.ulValue = (ULONG)NULL; /* No additional information */
160if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
161cdrom->numtracks = msp.ulReturn;
162if ( cdrom->numtracks > SDL_MAX_TRACKS )
163 {
164 cdrom->numtracks = SDL_MAX_TRACKS;
165 }
166/* Alocate space for TOC data */
167mtr = (MCI_TOC_REC *)SDL_malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));
168if ( mtr == NULL )
169 {
170 SDL_OutOfMemory();
171 return(-1);
172 }
173/* Get TOC from CD */
174mtp.pBuf = mtr;
175mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);
176if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS)
177 {
178 SDL_OutOfMemory();
179 SDL_free(mtr);
180 return(CD_ERROR);
181 }
182/* Fill SDL Tracks Structure */
183for (i=0; i<cdrom->numtracks; i++)
184 {
185 /* Set Track ID */
186 cdrom->track[i].id = (mtr+i)->TrackNum;
187 /* Set Track Type */
188 msp.hwndCallback = (HWND)NULL; /* None */
189 msp.ulReturn = (ULONG)NULL; /* We want this information */
190 msp.ulItem = MCI_CD_STATUS_TRACK_TYPE;
191 msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */
192 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS)
193 {
194 SDL_free(mtr);
195 return (CD_ERROR);
196 }
197 if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK;
198 else cdrom->track[i].type = SDL_DATA_TRACK;
199 /* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */
200 cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr);
201 /* Set Track Offset */
202 cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr);
203 }
204SDL_free(mtr);
205return(0);
206}
207
208
209/* Get CD-ROM status - Ready for MCI */
210static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
211{
212CDstatus status;
213MCI_STATUS_PARMS msp;
214
215/* Get Status from MCI */
216msp.hwndCallback = (HWND)NULL; /* None */
217msp.ulReturn = (ULONG)NULL; /* We want this information */
218msp.ulItem = MCI_STATUS_MODE;
219msp.ulValue = (ULONG)NULL; /* No additional information */
220if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;
221else
222 {
223 switch(msp.ulReturn)
224 {
225 case MCI_MODE_NOT_READY:
226 status = CD_TRAYEMPTY;
227 break;
228 case MCI_MODE_PAUSE:
229 status = CD_PAUSED;
230 break;
231 case MCI_MODE_PLAY:
232 status = CD_PLAYING;
233 break;
234 case MCI_MODE_STOP:
235 status = CD_STOPPED;
236 break;
237 /* These cases should not occour */
238 case MCI_MODE_RECORD:
239 case MCI_MODE_SEEK:
240 default:
241 status = CD_ERROR;
242 break;
243 }
244 }
245
246/* Determine position */
247if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */
248 {
249 if ((status == CD_PLAYING) || (status == CD_PAUSED))
250 {
251 /* Get Position */
252 msp.hwndCallback = (HWND)NULL; /* None */
253 msp.ulReturn = (ULONG)NULL; /* We want this information */
254 msp.ulItem = MCI_STATUS_POSITION;
255 msp.ulValue = (ULONG)NULL; /* No additiona info */
256 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR);
257 /* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */
258 *position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn));
259 }
260 else *position = 0;
261 }
262return(status);
263}
264
265/* Start play - Ready for MCI */
266static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
267{
268MCI_GENERIC_PARMS mgp;
269MCI_STATUS_PARMS msp;
270MCI_PLAY_PARMS mpp;
271ULONG min,sec,frm;
272
273/* Start MSF */
274FRAMES_TO_MSF(start, &min, &sec, &frm);
275MSF_MINUTE(mpp.ulFrom) = min;
276MSF_SECOND(mpp.ulFrom) = sec;
277MSF_FRAME(mpp.ulFrom) = frm;
278/* End MSF */
279FRAMES_TO_MSF(start+length, &min, &sec, &frm);
280MSF_MINUTE(mpp.ulTo) = min;
281MSF_SECOND(mpp.ulTo) = sec;
282MSF_FRAME(mpp.ulTo) = frm;
283#ifdef DEBUG_CDROM
284 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
285 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
286 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
287#endif
288/* Verifies if it is paused first... and if it is, unpause before stopping it. */
289msp.hwndCallback = (HWND)NULL; /* None */
290msp.ulReturn = (ULONG)NULL; /* We want this information */
291msp.ulItem = MCI_STATUS_MODE;
292msp.ulValue = (ULONG)NULL; /* No additional information */
293if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
294 {
295 if (msp.ulReturn == MCI_MODE_PAUSE)
296 {
297 mgp.hwndCallback = (HWND)NULL; // None
298 mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0);
299 }
300 }
301/* Now play it. */
302mpp.hwndCallback = (HWND)NULL; // We do not want the info. temp
303if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;
304return (CD_ERROR);
305}
306
307/* Pause play - Ready for MCI */
308static int SDL_SYS_CDPause(SDL_CD *cdrom)
309{
310MCI_GENERIC_PARMS mgp;
311
312mgp.hwndCallback = (HWND)NULL; // None
313if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
314return(CD_ERROR);
315}
316
317/* Resume play - Ready for MCI */
318static int SDL_SYS_CDResume(SDL_CD *cdrom)
319{
320MCI_GENERIC_PARMS mgp;
321
322mgp.hwndCallback = (HWND)NULL; // None
323if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
324return(CD_ERROR);
325}
326
327/* Stop play - Ready for MCI */
328static int SDL_SYS_CDStop(SDL_CD *cdrom)
329{
330MCI_GENERIC_PARMS mgp;
331MCI_STATUS_PARMS msp;
332
333/* Verifies if it is paused first... and if it is, unpause before stopping it. */
334msp.hwndCallback = (HWND)NULL; /* None */
335msp.ulReturn = (ULONG)NULL; /* We want this information */
336msp.ulItem = MCI_STATUS_MODE;
337msp.ulValue = (ULONG)NULL; /* No additional information */
338if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
339 {
340 if (msp.ulReturn == MCI_MODE_PAUSE)
341 {
342 mgp.hwndCallback = (HWND)NULL; // None
343 mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0);
344 }
345 }
346/* Now stops the media */
347mgp.hwndCallback = (HWND)NULL; // None
348if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
349return(CD_ERROR);
350}
351
352/* Eject the CD-ROM - Ready for MCI */
353static int SDL_SYS_CDEject(SDL_CD *cdrom)
354{
355MCI_SET_PARMS msp;
356
357msp.hwndCallback = (HWND)NULL; // None
358msp.ulTimeFormat = (ULONG)NULL; // No change
359msp.ulSpeedFormat = (ULONG)NULL; // No change
360msp.ulAudio = (ULONG)NULL; // No Channel
361msp.ulLevel = (ULONG)NULL; // No Volume
362msp.ulOver = (ULONG)NULL; // No Delay
363msp.ulItem = (ULONG)NULL; // No item
364msp.ulValue = (ULONG)NULL; // No value for item flag
365if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;
366return(CD_ERROR);
367}
368
369/* Close the CD-ROM handle - Ready for MCI */
370static void SDL_SYS_CDClose(SDL_CD *cdrom)
371{
372MCI_GENERIC_PARMS mgp;
373
374mgp.hwndCallback = (HWND)NULL; // None
375mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);
376}
377
378/* Finalize CDROM Subsystem - Ready for MCI */
379void SDL_SYS_CDQuit(void)
380{
381int i;
382
383if ( SDL_numcds > 0 )
384 {
385 for ( i=0; i<SDL_numcds; ++i )
386 {
387 SDL_free(SDL_cdlist[i]);
388 }
389 SDL_numcds = 0;
390 }
391}
392
393#endif /* SDL_CDROM_OS2 */
diff --git a/apps/plugins/sdl/src/cdrom/osf/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/osf/SDL_syscdrom.c
deleted file mode 100644
index 8478a7b4cf..0000000000
--- a/apps/plugins/sdl/src/cdrom/osf/SDL_syscdrom.c
+++ /dev/null
@@ -1,444 +0,0 @@
1/*
2 Tru64 audio module for SDL (Simple DirectMedia Layer)
3 Copyright (C) 2003
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
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
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19
20*/
21#include "SDL_config.h"
22
23#ifdef SDL_CDROM_OSF
24
25/* Functions for system-level CD-ROM audio control */
26
27/* #define DEBUG_CDROM 1 */
28
29#include <sys/types.h>
30#include <dirent.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <io/cam/cdrom.h>
34#include <io/cam/rzdisk.h>
35#include <io/common/devgetinfo.h>
36
37#include "SDL_cdrom.h"
38#include "../SDL_syscdrom.h"
39
40/* The maximum number of CD-ROM drives we'll detect */
41#define MAX_DRIVES 16
42
43/* A list of available CD-ROM drives */
44static char *SDL_cdlist[MAX_DRIVES];
45static dev_t SDL_cdmode[MAX_DRIVES];
46
47/* The system-dependent CD control functions */
48static const char *SDL_SYS_CDName(int drive);
49static int SDL_SYS_CDOpen(int drive);
50static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
51static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
52static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
53static int SDL_SYS_CDPause(SDL_CD *cdrom);
54static int SDL_SYS_CDResume(SDL_CD *cdrom);
55static int SDL_SYS_CDStop(SDL_CD *cdrom);
56static int SDL_SYS_CDEject(SDL_CD *cdrom);
57static void SDL_SYS_CDClose(SDL_CD *cdrom);
58
59/* Check a drive to see if it is a CD-ROM */
60/* Caution!! Not tested. */
61static int CheckDrive(char *drive, struct stat *stbuf)
62{
63 int cdfd, is_cd = 0;
64 struct mode_sel_sns_params msp;
65 struct inquiry_info inq;
66
67#ifdef DEBUG_CDROM
68 char *devtype[] = {"Disk", "Tape", "Printer", "Processor", "WORM",
69 "CD-ROM", "Scanner", "Optical", "Changer", "Comm", "Unknown"};
70#endif
71
72 bzero(&msp, sizeof(msp));
73 bzero(&inq, sizeof(inq));
74
75 /* If it doesn't exist, return -1 */
76 if ( stat(drive, stbuf) < 0 ) {
77 return(-1);
78 }
79
80 if ( (cdfd = open(drive, (O_RDWR|O_NDELAY), 0)) >= 0 ) {
81 msp.msp_addr = (caddr_t) &inq;
82 msp.msp_pgcode = 0;
83 msp.msp_pgctrl = 0;
84 msp.msp_length = sizeof(inq);
85 msp.msp_setps = 0;
86
87 if ( ioctl(cdfd, SCSI_GET_INQUIRY_DATA, &msp) )
88 return (0);
89
90#ifdef DEBUG_CDROM
91 fprintf(stderr, "Device Type: %s\n", devtype[inq.perfdt]);
92 fprintf(stderr, "Vendor: %.8s\n", inq.vndrid);
93 fprintf(stderr, "Product: %.8s\n", inq.prodid);
94 fprintf(stderr, "Revision: %.8s\n", inq.revlvl);
95#endif
96 if ( inq.perfdt == DTYPE_RODIRECT )
97 is_cd = 1;
98 }
99
100 return(is_cd);
101}
102
103/* Add a CD-ROM drive to our list of valid drives */
104static void AddDrive(char *drive, struct stat *stbuf)
105{
106 int i;
107
108 if ( SDL_numcds < MAX_DRIVES ) {
109 /* Check to make sure it's not already in our list.
110 * This can happen when we see a drive via symbolic link.
111 *
112 */
113 for ( i=0; i<SDL_numcds; ++i ) {
114 if ( stbuf->st_rdev == SDL_cdmode[i] ) {
115#ifdef DEBUG_CDROM
116 fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
117#endif
118 return;
119 }
120 }
121
122 /* Add this drive to our list */
123 i = SDL_numcds;
124 SDL_cdlist[i] = SDL_strdup(drive);
125 if ( SDL_cdlist[i] == NULL ) {
126 SDL_OutOfMemory();
127 return;
128 }
129 SDL_cdmode[i] = stbuf->st_rdev;
130 ++SDL_numcds;
131#ifdef DEBUG_CDROM
132 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
133#endif
134 }
135}
136
137int SDL_SYS_CDInit(void)
138{
139 /* checklist:
140 *
141 * Tru64 5.X (/dev/rdisk/cdrom?c)
142 * dir: /dev/rdisk, name: cdrom
143 *
144 * Digital UNIX 4.0X (/dev/rrz?c)
145 * dir: /dev, name: rrz
146 *
147 */
148 struct {
149 char *dir;
150 char *name;
151 } checklist[] = {
152 {"/dev/rdisk", "cdrom"},
153 {"/dev", "rrz"},
154 {NULL, NULL}};
155 char drive[32];
156 char *SDLcdrom;
157 int i, j, exists;
158 struct stat stbuf;
159
160 /* Fill in our driver capabilities */
161 SDL_CDcaps.Name = SDL_SYS_CDName;
162 SDL_CDcaps.Open = SDL_SYS_CDOpen;
163 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
164 SDL_CDcaps.Status = SDL_SYS_CDStatus;
165 SDL_CDcaps.Play = SDL_SYS_CDPlay;
166 SDL_CDcaps.Pause = SDL_SYS_CDPause;
167 SDL_CDcaps.Resume = SDL_SYS_CDResume;
168 SDL_CDcaps.Stop = SDL_SYS_CDStop;
169 SDL_CDcaps.Eject = SDL_SYS_CDEject;
170 SDL_CDcaps.Close = SDL_SYS_CDClose;
171
172
173 /* Look in the environment for our CD-ROM drive list */
174 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
175 if ( SDLcdrom != NULL ) {
176 char *cdpath, *delim;
177 size_t len = SDL_strlen(SDLcdrom)+1;
178 cdpath = SDL_stack_alloc(char, len);
179 if ( cdpath != NULL ) {
180 SDL_strlcpy(cdpath, SDLcdrom, len);
181 SDLcdrom = cdpath;
182 do {
183 delim = SDL_strchr(SDLcdrom, ':');
184 if ( delim ) {
185 *delim++ = '\0';
186 }
187 if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
188 AddDrive(SDLcdrom, &stbuf);
189 }
190 if ( delim ) {
191 SDLcdrom = delim;
192 } else {
193 SDLcdrom = NULL;
194 }
195 } while ( SDLcdrom );
196 SDL_stack_free(cdpath);
197 }
198
199 /* If we found our drives, there's nothing left to do */
200 if ( SDL_numcds > 0 ) {
201 return(0);
202 }
203 }
204 /* Scan the system for CD-ROM drives */
205 for ( i = 0; checklist[i].dir; ++i) {
206 DIR *devdir;
207 struct dirent *devent;
208 int name_len;
209
210 devdir = opendir(checklist[i].dir);
211 if (devdir) {
212 name_len = SDL_strlen(checklist[i].name);
213 while (devent = readdir(devdir))
214 if (SDL_memcmp(checklist[i].name, devent->d_name, name_len) == 0)
215 if (devent->d_name[devent->d_namlen-1] == 'c') {
216 SDL_snprintf(drive, SDL_arraysize(drive), "%s/%s", checklist[i].dir, devent->d_name);
217#ifdef DEBUG_CDROM
218 fprintf(stderr, "Try to add drive: %s\n", drive);
219#endif
220 if ( CheckDrive(drive, &stbuf) > 0 )
221 AddDrive(drive, &stbuf);
222 }
223 closedir(devdir);
224 } else {
225#ifdef DEBUG_CDROM
226 fprintf(stderr, "cannot open dir: %s\n", checklist[i].dir);
227#endif
228 }
229 }
230 return (0);
231}
232
233static const char *SDL_SYS_CDName(int drive)
234{
235 return(SDL_cdlist[drive]);
236}
237
238static int SDL_SYS_CDOpen(int drive)
239{
240 /* O_RDWR: To use ioctl(fd, SCSI_STOP_UNIT) */
241 return(open(SDL_cdlist[drive], (O_RDWR|O_NDELAY), 0));
242}
243
244static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
245{
246 struct cd_toc toc;
247 struct cd_toc_header hdr;
248 struct cd_toc_entry *cdte;
249 int i;
250 int okay = 0;
251 if ( ioctl(cdrom->id, CDROM_TOC_HEADER, &hdr) ) {
252 fprintf(stderr,"ioctl error CDROM_TOC_HEADER\n");
253 return -1;
254 }
255 cdrom->numtracks = hdr.th_ending_track - hdr.th_starting_track + 1;
256 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
257 cdrom->numtracks = SDL_MAX_TRACKS;
258 }
259#ifdef DEBUG_CDROM
260 fprintf(stderr,"hdr.th_data_len1 = %d\n", hdr.th_data_len1);
261 fprintf(stderr,"hdr.th_data_len0 = %d\n", hdr.th_data_len0);
262 fprintf(stderr,"hdr.th_starting_track = %d\n", hdr.th_starting_track);
263 fprintf(stderr,"hdr.th_ending_track = %d\n", hdr.th_ending_track);
264 fprintf(stderr,"cdrom->numtracks = %d\n", cdrom->numtracks);
265#endif
266 toc.toc_address_format = CDROM_LBA_FORMAT;
267 toc.toc_starting_track = 0;
268 toc.toc_alloc_length = (hdr.th_data_len1 << 8) +
269 hdr.th_data_len0 + sizeof(hdr);
270 if ( (toc.toc_buffer = alloca(toc.toc_alloc_length)) == NULL) {
271 fprintf(stderr,"cannot allocate toc.toc_buffer\n");
272 return -1;
273 }
274
275 bzero (toc.toc_buffer, toc.toc_alloc_length);
276 if (ioctl(cdrom->id, CDROM_TOC_ENTRYS, &toc)) {
277 fprintf(stderr,"ioctl error CDROM_TOC_ENTRYS\n");
278 return -1;
279 }
280
281 cdte =(struct cd_toc_entry *) ((char *) toc.toc_buffer + sizeof(hdr));
282 for (i=0; i <= cdrom->numtracks; ++i) {
283 if (i == cdrom->numtracks ) {
284 cdrom->track[i].id = 0xAA;;
285 } else {
286 cdrom->track[i].id = hdr.th_starting_track + i;
287 }
288
289 cdrom->track[i].type =
290 cdte[i].te_control & CDROM_DATA_TRACK;
291 cdrom->track[i].offset =
292 cdte[i].te_absaddr.lba.addr3 << 24 |
293 cdte[i].te_absaddr.lba.addr2 << 16 |
294 cdte[i].te_absaddr.lba.addr1 << 8 |
295 cdte[i].te_absaddr.lba.addr0;
296 cdrom->track[i].length = 0;
297 if ( i > 0 ) {
298 cdrom->track[i - 1].length =
299 cdrom->track[i].offset -
300 cdrom->track[i - 1].offset;
301 }
302 }
303#ifdef DEBUG_CDROM
304 for (i = 0; i <= cdrom->numtracks; i++) {
305 fprintf(stderr,"toc_entry[%d].te_track_number = %d\n",
306 i,cdte[i].te_track_number);
307 fprintf(stderr,"cdrom->track[%d].id = %d\n", i,cdrom->track[i].id);
308 fprintf(stderr,"cdrom->track[%d].type = %x\n", i,cdrom->track[i].type);
309 fprintf(stderr,"cdrom->track[%d].offset = %d\n", i,cdrom->track[i].offset);
310 fprintf(stderr,"cdrom->track[%d].length = %d\n", i,cdrom->track[i].length);
311 }
312#endif
313 if ( i == (cdrom->numtracks+1) ) {
314 okay = 1;
315 }
316
317 return(okay ? 0 : -1);
318}
319
320/* Get CD-ROM status */
321static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
322{
323 CDstatus status;
324 struct cd_sub_channel sc;
325 struct cd_subc_channel_data scd;
326
327 sc.sch_address_format = CDROM_LBA_FORMAT;
328 sc.sch_data_format = CDROM_CURRENT_POSITION;
329 sc.sch_track_number = 0;
330 sc.sch_alloc_length = sizeof(scd);
331 sc.sch_buffer = (caddr_t)&scd;
332 if ( ioctl(cdrom->id, CDROM_READ_SUBCHANNEL, &sc) ) {
333 status = CD_ERROR;
334 fprintf(stderr,"ioctl error CDROM_READ_SUBCHANNEL \n");
335 } else {
336 switch (scd.scd_header.sh_audio_status) {
337 case AS_AUDIO_INVALID:
338 status = CD_STOPPED;
339 break;
340 case AS_PLAY_IN_PROGRESS:
341 status = CD_PLAYING;
342 break;
343 case AS_PLAY_PAUSED:
344 status = CD_PAUSED;
345 break;
346 case AS_PLAY_COMPLETED:
347 status = CD_STOPPED;
348 break;
349 case AS_PLAY_ERROR:
350 status = CD_ERROR;
351 break;
352 case AS_NO_STATUS:
353 status = CD_STOPPED;
354 break;
355 default:
356 status = CD_ERROR;
357 break;
358 }
359#ifdef DEBUG_CDROM
360 fprintf(stderr,"scd.scd_header.sh_audio_status = %x\n",
361 scd.scd_header.sh_audio_status);
362#endif
363 }
364 if (position) {
365 if (status == CD_PLAYING || (status == CD_PAUSED) ) {
366 *position =
367 scd.scd_position_data.scp_absaddr.lba.addr3 << 24 |
368 scd.scd_position_data.scp_absaddr.lba.addr2 << 16 |
369 scd.scd_position_data.scp_absaddr.lba.addr1 << 8 |
370 scd.scd_position_data.scp_absaddr.lba.addr0;
371 } else {
372 *position = 0;
373 }
374 }
375
376 return status;
377}
378
379/* Start play */
380static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
381{
382/*
383 * Play MSF
384 */
385 struct cd_play_audio_msf msf;
386 int end;
387
388 bzero(&msf, sizeof(msf));
389 end = start +length;
390 FRAMES_TO_MSF(start + 150, /* LBA = 4500*M + 75*S + F - 150 */
391 &msf.msf_starting_M_unit,
392 &msf.msf_starting_S_unit,
393 &msf.msf_starting_F_unit);
394 FRAMES_TO_MSF(end + 150, /* LBA = 4500*M + 75*S + F - 150 */
395 &msf.msf_ending_M_unit,
396 &msf.msf_ending_S_unit,
397 &msf.msf_ending_F_unit);
398
399 return(ioctl(cdrom->id, CDROM_PLAY_AUDIO_MSF, &msf));
400}
401
402/* Pause play */
403static int SDL_SYS_CDPause(SDL_CD *cdrom)
404{
405 return(ioctl(cdrom->id, CDROM_PAUSE_PLAY));
406}
407
408/* Resume play */
409static int SDL_SYS_CDResume(SDL_CD *cdrom)
410{
411 return(ioctl(cdrom->id, CDROM_RESUME_PLAY));
412}
413
414/* Stop play */
415static int SDL_SYS_CDStop(SDL_CD *cdrom)
416{
417 return(ioctl(cdrom->id, SCSI_STOP_UNIT));
418}
419
420/* Eject the CD-ROM */
421static int SDL_SYS_CDEject(SDL_CD *cdrom)
422{
423 return(ioctl(cdrom->id, CDROM_EJECT_CADDY));
424}
425
426/* Close the CD-ROM handle */
427static void SDL_SYS_CDClose(SDL_CD *cdrom)
428{
429 close(cdrom->id);
430}
431
432void SDL_SYS_CDQuit(void)
433{
434 int i;
435
436 if ( SDL_numcds > 0 ) {
437 for ( i=0; i<SDL_numcds; ++i ) {
438 SDL_free(SDL_cdlist[i]);
439 }
440 SDL_numcds = 0;
441 }
442}
443
444#endif /* SDL_CDROM_OSF */
diff --git a/apps/plugins/sdl/src/cdrom/qnx/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/qnx/SDL_syscdrom.c
deleted file mode 100644
index 0e38b7905e..0000000000
--- a/apps/plugins/sdl/src/cdrom/qnx/SDL_syscdrom.c
+++ /dev/null
@@ -1,551 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_QNX
25
26/* Functions for system-level CD-ROM audio control */
27
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <sys/ioctl.h>
31#include <fcntl.h>
32#include <errno.h>
33#include <unistd.h>
34#include <sys/cdrom.h>
35#include <sys/dcmd_cam.h>
36
37#include "SDL_timer.h"
38#include "SDL_cdrom.h"
39#include "../SDL_syscdrom.h"
40
41/* The maximum number of CD-ROM drives we'll detect */
42#define MAX_DRIVES 16
43
44#define QNX_CD_OPENMODE O_RDONLY | O_EXCL
45
46/* A list of available CD-ROM drives */
47static char *SDL_cdlist[MAX_DRIVES];
48static dev_t SDL_cdmode[MAX_DRIVES];
49static int SDL_cdopen[MAX_DRIVES];
50
51/* The system-dependent CD control functions */
52static const char *SDL_SYS_CDName(int drive);
53static int SDL_SYS_CDOpen(int drive);
54static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
55static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
56static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
57static int SDL_SYS_CDPause(SDL_CD *cdrom);
58static int SDL_SYS_CDResume(SDL_CD *cdrom);
59static int SDL_SYS_CDStop(SDL_CD *cdrom);
60static int SDL_SYS_CDEject(SDL_CD *cdrom);
61static void SDL_SYS_CDClose(SDL_CD *cdrom);
62
63/* Check a drive to see if it is a CD-ROM */
64static int CheckDrive(char *drive, struct stat *stbuf)
65{
66 int is_cd, cdfd;
67 cam_devinfo_t dinfo;
68 int devctlret=0;
69
70 int atapi;
71 int removable;
72 int cdb10;
73
74 /* If it doesn't exist, return -1 */
75 if (stat(drive, stbuf) < 0)
76 {
77 return(-1);
78 }
79
80 /* If it does exist, verify that it's an available CD-ROM */
81 is_cd = 0;
82
83 if (S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode))
84 {
85 cdfd = open(drive, QNX_CD_OPENMODE);
86 if ( cdfd >= 0 )
87 {
88 devctlret=devctl(cdfd, DCMD_CAM_DEVINFO, &dinfo, sizeof(cam_devinfo_t), NULL);
89
90 if (devctlret==EOK)
91 {
92 atapi=dinfo.flags & DEV_ATAPI;
93 removable=dinfo.flags & DEV_REMOVABLE;
94 cdb10=dinfo.flags & DEV_CDB_10; /* I'm not sure about that flag */
95
96 /* in the near future need to add more checks for splitting cdroms from other devices */
97 if ((atapi)&&(removable))
98 {
99 is_cd = 1;
100 }
101 }
102
103 close(cdfd);
104 }
105 }
106 return(is_cd);
107}
108
109/* Add a CD-ROM drive to our list of valid drives */
110static void AddDrive(char *drive, struct stat *stbuf)
111{
112 int i;
113
114 if (SDL_numcds < MAX_DRIVES)
115 {
116 /* Check to make sure it's not already in our list.
117 This can happen when we see a drive via symbolic link. */
118
119 for (i=0; i<SDL_numcds; ++i)
120 {
121 if (stbuf->st_rdev == SDL_cdmode[i])
122 {
123 return;
124 }
125 }
126
127 /* Add this drive to our list */
128
129 i = SDL_numcds;
130 SDL_cdlist[i] = SDL_strdup(drive);
131 if (SDL_cdlist[i] == NULL)
132 {
133 SDL_OutOfMemory();
134 return;
135 }
136 SDL_cdmode[i] = stbuf->st_rdev;
137 ++SDL_numcds;
138 }
139}
140
141int SDL_SYS_CDInit(void)
142{
143 /* checklist: /dev/cdrom, /dev/cd?, /dev/scd? */
144 static char *checklist[]={"cdrom", "?0 cd?", "?1 cd?", "?0 scd?", NULL};
145
146 char *SDLcdrom;
147 int i, j, exists;
148 char drive[32];
149 struct stat stbuf;
150
151 /* Fill in our driver capabilities */
152 SDL_CDcaps.Name = SDL_SYS_CDName;
153 SDL_CDcaps.Open = SDL_SYS_CDOpen;
154 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
155 SDL_CDcaps.Status = SDL_SYS_CDStatus;
156 SDL_CDcaps.Play = SDL_SYS_CDPlay;
157 SDL_CDcaps.Pause = SDL_SYS_CDPause;
158 SDL_CDcaps.Resume = SDL_SYS_CDResume;
159 SDL_CDcaps.Stop = SDL_SYS_CDStop;
160 SDL_CDcaps.Eject = SDL_SYS_CDEject;
161 SDL_CDcaps.Close = SDL_SYS_CDClose;
162
163 /* clearing device open status */
164 for (i=0; i<MAX_DRIVES; i++)
165 {
166 SDL_cdopen[i]=0;
167 }
168
169 /* Look in the environment for our CD-ROM drive list */
170 SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
171 if ( SDLcdrom != NULL )
172 {
173 char *cdpath, *delim;
174 size_t len = SDL_strlen(SDLcdrom)+1;
175 cdpath = SDL_stack_alloc(char, len);
176 if (cdpath != NULL)
177 {
178 SDL_strlcpy(cdpath, SDLcdrom, len);
179 SDLcdrom = cdpath;
180 do {
181 delim = SDL_strchr(SDLcdrom, ':');
182 if (delim)
183 {
184 *delim++ = '\0';
185 }
186 if (CheckDrive(SDLcdrom, &stbuf) > 0)
187 {
188 AddDrive(SDLcdrom, &stbuf);
189 }
190 if (delim)
191 {
192 SDLcdrom = delim;
193 }
194 else
195 {
196 SDLcdrom = NULL;
197 }
198 } while (SDLcdrom);
199 SDL_stack_free(cdpath);
200 }
201
202 /* If we found our drives, there's nothing left to do */
203 if (SDL_numcds > 0)
204 {
205 return(0);
206 }
207 }
208
209 /* Scan the system for CD-ROM drives */
210 for ( i=0; checklist[i]; ++i )
211 {
212 if (checklist[i][0] == '?')
213 {
214 char* insert;
215 exists = 1;
216
217 for ( j=checklist[i][1]; exists; ++j )
218 {
219 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", &checklist[i][3]);
220 insert = SDL_strchr(drive, '?');
221 if (insert != NULL)
222 {
223 *insert = j;
224 }
225 switch (CheckDrive(drive, &stbuf))
226 {
227 /* Drive exists and is a CD-ROM */
228 case 1:
229 AddDrive(drive, &stbuf);
230 break;
231 /* Drive exists, but isn't a CD-ROM */
232 case 0:
233 break;
234 /* Drive doesn't exist */
235 case -1:
236 exists = 0;
237 break;
238 }
239 }
240 }
241 else
242 {
243 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
244 if (CheckDrive(drive, &stbuf) > 0)
245 {
246 AddDrive(drive, &stbuf);
247 }
248 }
249 }
250 return(0);
251}
252
253static const char *SDL_SYS_CDName(int drive)
254{
255 return(SDL_cdlist[drive]);
256}
257
258static int SDL_SYS_CDOpen(int drive)
259{
260 int handle;
261
262 handle=open(SDL_cdlist[drive], QNX_CD_OPENMODE);
263
264 if (handle>0)
265 {
266 SDL_cdopen[drive]=handle;
267 }
268
269 return (handle);
270}
271
272static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
273{
274 cdrom_read_toc_t toc;
275 int i, okay;
276
277 okay = 0;
278 if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), NULL) == 0)
279 {
280 cdrom->numtracks = toc.last_track - toc.first_track + 1;
281 if (cdrom->numtracks > SDL_MAX_TRACKS)
282 {
283 cdrom->numtracks = SDL_MAX_TRACKS;
284 }
285 /* Read all the track TOC entries */
286 for (i=0; i<=cdrom->numtracks; ++i)
287 {
288 if (i == cdrom->numtracks)
289 {
290 cdrom->track[i].id = CDROM_LEADOUT;
291 }
292 else
293 {
294 cdrom->track[i].id = toc.first_track+i;
295 }
296
297 cdrom->track[i].type = toc.toc_entry[i].control_adr & 0x0F;
298 cdrom->track[i].offset = toc.toc_entry[i].addr.lba;
299 cdrom->track[i].length = 0;
300
301 if (i > 0)
302 {
303 cdrom->track[i-1].length = cdrom->track[i].offset-cdrom->track[i-1].offset;
304 }
305 }
306 if (i == (cdrom->numtracks+1))
307 {
308 okay = 1;
309 }
310 }
311 return (okay ? 0 : -1);
312}
313
314/* Get CD-ROM status */
315static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
316{
317 CDstatus status;
318
319 cdrom_read_toc_t toc;
320 cdrom_subch_data_t info;
321 cam_devinfo_t dinfo;
322
323 int devctlret=0;
324 int drive=-1;
325 int i;
326 int eagaincnt=0;
327
328 /* check media presence before read subchannel call, some cdroms can lockups */
329 /* if no media, while calling read subchannel functions. */
330 devctlret=devctl(cdrom->id, DCMD_CAM_DEVINFO, &dinfo, sizeof(cam_devinfo_t), NULL);
331
332 if (devctlret==EOK)
333 {
334 if ((dinfo.flags & DEV_NO_MEDIA)!=0)
335 {
336 status = CD_TRAYEMPTY;
337 if (position)
338 {
339 *position = 0;
340 }
341 return (status);
342 }
343 }
344
345 /* if media exists, then do other stuff */
346
347 SDL_memset(&info, 0x00, sizeof(info));
348 info.subch_command.data_format = CDROM_SUBCH_CURRENT_POSITION;
349
350 do {
351 devctlret=devctl(cdrom->id, DCMD_CAM_CDROMSUBCHNL, &info, sizeof(info), NULL);
352 if (devctlret==EIO)
353 {
354 /* big workaround for media change, handle is unusable after that,
355 that bug was found in QNX 6.2, 6.2.1 is not released yet. */
356
357 for (i=0; i<MAX_DRIVES; i++)
358 {
359 if (SDL_cdopen[i]==cdrom->id)
360 {
361 drive=i;
362 break;
363 }
364 }
365 if (drive==-1)
366 {
367 /* that cannot happen, but ... */
368 break;
369 }
370 close(cdrom->id);
371 cdrom->id=open(SDL_cdlist[drive], QNX_CD_OPENMODE);
372 devctlret=EAGAIN;
373 }
374 if (devctlret==EAGAIN)
375 {
376 eagaincnt++;
377 }
378 if (eagaincnt==2)
379 {
380 /* workaround for broken cdroms, which can return always EAGAIN when its not ready, */
381 /* that mean errornous media or just no media avail */
382 devctlret=ENXIO;
383 break;
384 }
385 } while ((devctlret==EAGAIN)||(devctlret==ESTALE));
386
387 if (devctlret != 0)
388 {
389 if (devctlret==ENXIO)
390 {
391 status = CD_TRAYEMPTY;
392 }
393 else
394 {
395 status = CD_ERROR;
396 }
397 }
398 else
399 {
400 switch (info.current_position.header.audio_status)
401 {
402 case CDROM_AUDIO_INVALID:
403 case CDROM_AUDIO_NO_STATUS:
404 /* Try to determine if there's a CD available */
405 if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), NULL)==0)
406 status = CD_STOPPED;
407 else
408 status = CD_TRAYEMPTY;
409 break;
410 case CDROM_AUDIO_COMPLETED:
411 status = CD_STOPPED;
412 break;
413 case CDROM_AUDIO_PLAY:
414 status = CD_PLAYING;
415 break;
416 case CDROM_AUDIO_PAUSED:
417 /* Workaround buggy CD-ROM drive */
418 if (info.current_position.data_format == CDROM_LEADOUT)
419 {
420 status = CD_STOPPED;
421 }
422 else
423 {
424 status = CD_PAUSED;
425 }
426 break;
427 default:
428 status = CD_ERROR;
429 break;
430 }
431 }
432
433 if (position)
434 {
435 if (status==CD_PLAYING || (status==CD_PAUSED))
436 {
437 *position = MSF_TO_FRAMES(info.current_position.addr.msf.minute,
438 info.current_position.addr.msf.second,
439 info.current_position.addr.msf.frame);
440 }
441 else
442 {
443 *position = 0;
444 }
445 }
446
447 return (status);
448}
449
450/* Start play */
451static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
452{
453 cdrom_playmsf_t playtime;
454
455 FRAMES_TO_MSF(start, &playtime.start_minute, &playtime.start_second, &playtime.start_frame);
456 FRAMES_TO_MSF(start+length, &playtime.end_minute, &playtime.end_second, &playtime.end_frame);
457
458 if (devctl(cdrom->id, DCMD_CAM_CDROMPLAYMSF, &playtime, sizeof(playtime), NULL) != 0)
459 {
460 return -1;
461 }
462 else
463 {
464 return 0;
465 }
466}
467
468/* Pause play */
469static int SDL_SYS_CDPause(SDL_CD *cdrom)
470{
471 if (devctl(cdrom->id, DCMD_CAM_CDROMPAUSE, NULL, 0, NULL)!=0)
472 {
473 return -1;
474 }
475 else
476 {
477 return 0;
478 }
479}
480
481/* Resume play */
482static int SDL_SYS_CDResume(SDL_CD *cdrom)
483{
484 if (devctl(cdrom->id, DCMD_CAM_CDROMRESUME, NULL, 0, NULL)!=0)
485 {
486 return -1;
487 }
488 else
489 {
490 return 0;
491 }
492}
493
494/* Stop play */
495static int SDL_SYS_CDStop(SDL_CD *cdrom)
496{
497 if (devctl(cdrom->id, DCMD_CAM_CDROMSTOP, NULL, 0, NULL)!=0)
498 {
499 return -1;
500 }
501 else
502 {
503 return 0;
504 }
505}
506
507/* Eject the CD-ROM */
508static int SDL_SYS_CDEject(SDL_CD *cdrom)
509{
510 if (devctl(cdrom->id, DCMD_CAM_EJECT_MEDIA, NULL, 0, NULL)!=0)
511 {
512 return -1;
513 }
514 else
515 {
516 return 0;
517 }
518}
519
520/* Close the CD-ROM handle */
521static void SDL_SYS_CDClose(SDL_CD *cdrom)
522{
523 int i;
524
525 for (i=0; i<MAX_DRIVES; i++)
526 {
527 if (SDL_cdopen[i]==cdrom->id)
528 {
529 SDL_cdopen[i]=0;
530 break;
531 }
532 }
533
534 close(cdrom->id);
535}
536
537void SDL_SYS_CDQuit(void)
538{
539 int i;
540
541 if (SDL_numcds > 0)
542 {
543 for (i=0; i<SDL_numcds; ++i)
544 {
545 SDL_free(SDL_cdlist[i]);
546 }
547 SDL_numcds = 0;
548 }
549}
550
551#endif /* SDL_CDROM_QNX */
diff --git a/apps/plugins/sdl/src/cdrom/win32/SDL_syscdrom.c b/apps/plugins/sdl/src/cdrom/win32/SDL_syscdrom.c
deleted file mode 100644
index cac9fd3b61..0000000000
--- a/apps/plugins/sdl/src/cdrom/win32/SDL_syscdrom.c
+++ /dev/null
@@ -1,386 +0,0 @@
1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2012 Sam Lantinga
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
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
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_WIN32
25
26/* Functions for system-level CD-ROM audio control */
27
28#define WIN32_LEAN_AND_MEAN
29#include <windows.h>
30#include <mmsystem.h>
31
32#include "SDL_cdrom.h"
33#include "../SDL_syscdrom.h"
34
35/* This really broken?? */
36#define BROKEN_MCI_PAUSE /* Pausing actually stops play -- Doh! */
37
38/* The maximum number of CD-ROM drives we'll detect (Don't change!) */
39#define MAX_DRIVES 26
40
41/* A list of available CD-ROM drives */
42static char *SDL_cdlist[MAX_DRIVES];
43static MCIDEVICEID SDL_mciID[MAX_DRIVES];
44#ifdef BROKEN_MCI_PAUSE
45static int SDL_paused[MAX_DRIVES];
46#endif
47static int SDL_CD_end_position;
48
49/* The system-dependent CD control functions */
50static const char *SDL_SYS_CDName(int drive);
51static int SDL_SYS_CDOpen(int drive);
52static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
53static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
54static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
55static int SDL_SYS_CDPause(SDL_CD *cdrom);
56static int SDL_SYS_CDResume(SDL_CD *cdrom);
57static int SDL_SYS_CDStop(SDL_CD *cdrom);
58static int SDL_SYS_CDEject(SDL_CD *cdrom);
59static void SDL_SYS_CDClose(SDL_CD *cdrom);
60
61
62/* Add a CD-ROM drive to our list of valid drives */
63static void AddDrive(char *drive)
64{
65 int i;
66
67 if ( SDL_numcds < MAX_DRIVES ) {
68 /* Add this drive to our list */
69 i = SDL_numcds;
70 SDL_cdlist[i] = SDL_strdup(drive);
71 if ( SDL_cdlist[i] == NULL ) {
72 SDL_OutOfMemory();
73 return;
74 }
75 ++SDL_numcds;
76#ifdef CDROM_DEBUG
77 fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
78#endif
79 }
80}
81
82int SDL_SYS_CDInit(void)
83{
84 /* checklist: Drive 'A' - 'Z' */
85 int i;
86 char drive[4];
87
88 /* Fill in our driver capabilities */
89 SDL_CDcaps.Name = SDL_SYS_CDName;
90 SDL_CDcaps.Open = SDL_SYS_CDOpen;
91 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
92 SDL_CDcaps.Status = SDL_SYS_CDStatus;
93 SDL_CDcaps.Play = SDL_SYS_CDPlay;
94 SDL_CDcaps.Pause = SDL_SYS_CDPause;
95 SDL_CDcaps.Resume = SDL_SYS_CDResume;
96 SDL_CDcaps.Stop = SDL_SYS_CDStop;
97 SDL_CDcaps.Eject = SDL_SYS_CDEject;
98 SDL_CDcaps.Close = SDL_SYS_CDClose;
99
100 /* Scan the system for CD-ROM drives */
101 for ( i='A'; i<='Z'; ++i ) {
102 SDL_snprintf(drive, SDL_arraysize(drive), "%c:\\", i);
103 if ( GetDriveType(drive) == DRIVE_CDROM ) {
104 AddDrive(drive);
105 }
106 }
107 SDL_memset(SDL_mciID, 0, sizeof(SDL_mciID));
108 return(0);
109}
110
111/* General ioctl() CD-ROM command function */
112static int SDL_SYS_CDioctl(int id, UINT msg, DWORD flags, void *arg)
113{
114 MCIERROR mci_error;
115
116 mci_error = mciSendCommand(SDL_mciID[id], msg, flags, (DWORD_PTR)arg);
117 if ( mci_error ) {
118 char error[256];
119
120 mciGetErrorString(mci_error, error, 256);
121 SDL_SetError("mciSendCommand() error: %s", error);
122 }
123 return(!mci_error ? 0 : -1);
124}
125
126static const char *SDL_SYS_CDName(int drive)
127{
128 return(SDL_cdlist[drive]);
129}
130
131static int SDL_SYS_CDOpen(int drive)
132{
133 MCI_OPEN_PARMS mci_open;
134 MCI_SET_PARMS mci_set;
135 char device[3];
136 DWORD flags;
137
138 /* Open the requested device */
139 mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
140 device[0] = *SDL_cdlist[drive];
141 device[1] = ':';
142 device[2] = '\0';
143 mci_open.lpstrElementName = device;
144 flags =
145 (MCI_OPEN_TYPE|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT);
146 if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) {
147 flags &= ~MCI_OPEN_SHAREABLE;
148 if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) {
149 return(-1);
150 }
151 }
152 SDL_mciID[drive] = mci_open.wDeviceID;
153
154 /* Set the minute-second-frame time format */
155 mci_set.dwTimeFormat = MCI_FORMAT_MSF;
156 SDL_SYS_CDioctl(drive, MCI_SET, MCI_SET_TIME_FORMAT, &mci_set);
157
158#ifdef BROKEN_MCI_PAUSE
159 SDL_paused[drive] = 0;
160#endif
161 return(drive);
162}
163
164static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
165{
166 MCI_STATUS_PARMS mci_status;
167 int i, okay;
168 DWORD flags;
169
170 okay = 0;
171 mci_status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
172 flags = MCI_STATUS_ITEM | MCI_WAIT;
173 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) {
174 cdrom->numtracks = mci_status.dwReturn;
175 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
176 cdrom->numtracks = SDL_MAX_TRACKS;
177 }
178 /* Read all the track TOC entries */
179 flags = MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT;
180 for ( i=0; i<cdrom->numtracks; ++i ) {
181 cdrom->track[i].id = i+1;
182 mci_status.dwTrack = cdrom->track[i].id;
183#ifdef MCI_CDA_STATUS_TYPE_TRACK
184 mci_status.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
185 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
186 &mci_status) < 0 ) {
187 break;
188 }
189 if ( mci_status.dwReturn == MCI_CDA_TRACK_AUDIO ) {
190 cdrom->track[i].type = SDL_AUDIO_TRACK;
191 } else {
192 cdrom->track[i].type = SDL_DATA_TRACK;
193 }
194#else
195 cdrom->track[i].type = SDL_AUDIO_TRACK;
196#endif
197 mci_status.dwItem = MCI_STATUS_POSITION;
198 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
199 &mci_status) < 0 ) {
200 break;
201 }
202 cdrom->track[i].offset = MSF_TO_FRAMES(
203 MCI_MSF_MINUTE(mci_status.dwReturn),
204 MCI_MSF_SECOND(mci_status.dwReturn),
205 MCI_MSF_FRAME(mci_status.dwReturn));
206 cdrom->track[i].length = 0;
207 if ( i > 0 ) {
208 cdrom->track[i-1].length =
209 cdrom->track[i].offset-
210 cdrom->track[i-1].offset;
211 }
212 }
213 if ( i == cdrom->numtracks ) {
214 mci_status.dwTrack = cdrom->track[i - 1].id;
215 mci_status.dwItem = MCI_STATUS_LENGTH;
216 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
217 &mci_status) == 0 ) {
218 cdrom->track[i - 1].length = MSF_TO_FRAMES(
219 MCI_MSF_MINUTE(mci_status.dwReturn),
220 MCI_MSF_SECOND(mci_status.dwReturn),
221 MCI_MSF_FRAME(mci_status.dwReturn));
222 /* compute lead-out offset */
223 cdrom->track[i].offset = cdrom->track[i - 1].offset +
224 cdrom->track[i - 1].length;
225 cdrom->track[i].length = 0;
226 okay = 1;
227 }
228 }
229 }
230 return(okay ? 0 : -1);
231}
232
233/* Get CD-ROM status */
234static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
235{
236 CDstatus status;
237 MCI_STATUS_PARMS mci_status;
238 DWORD flags;
239
240 flags = MCI_STATUS_ITEM | MCI_WAIT;
241 mci_status.dwItem = MCI_STATUS_MODE;
242 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) {
243 status = CD_ERROR;
244 } else {
245 switch (mci_status.dwReturn) {
246 case MCI_MODE_NOT_READY:
247 case MCI_MODE_OPEN:
248 status = CD_TRAYEMPTY;
249 break;
250 case MCI_MODE_STOP:
251#ifdef BROKEN_MCI_PAUSE
252 if ( SDL_paused[cdrom->id] ) {
253 status = CD_PAUSED;
254 } else {
255 status = CD_STOPPED;
256 }
257#else
258 status = CD_STOPPED;
259#endif /* BROKEN_MCI_PAUSE */
260 break;
261 case MCI_MODE_PLAY:
262#ifdef BROKEN_MCI_PAUSE
263 if ( SDL_paused[cdrom->id] ) {
264 status = CD_PAUSED;
265 } else {
266 status = CD_PLAYING;
267 }
268#else
269 status = CD_PLAYING;
270#endif /* BROKEN_MCI_PAUSE */
271 break;
272 case MCI_MODE_PAUSE:
273 status = CD_PAUSED;
274 break;
275 default:
276 status = CD_ERROR;
277 break;
278 }
279 }
280 if ( position ) {
281 if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
282 mci_status.dwItem = MCI_STATUS_POSITION;
283 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
284 &mci_status) == 0 ) {
285 *position = MSF_TO_FRAMES(
286 MCI_MSF_MINUTE(mci_status.dwReturn),
287 MCI_MSF_SECOND(mci_status.dwReturn),
288 MCI_MSF_FRAME(mci_status.dwReturn));
289 } else {
290 *position = 0;
291 }
292 } else {
293 *position = 0;
294 }
295 }
296 return(status);
297}
298
299/* Start play */
300static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
301{
302 MCI_PLAY_PARMS mci_play;
303 int m, s, f;
304 DWORD flags;
305
306 flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
307 mci_play.dwCallback = 0;
308 FRAMES_TO_MSF(start, &m, &s, &f);
309 mci_play.dwFrom = MCI_MAKE_MSF(m, s, f);
310 FRAMES_TO_MSF(start+length, &m, &s, &f);
311 mci_play.dwTo = MCI_MAKE_MSF(m, s, f);
312 SDL_CD_end_position = mci_play.dwTo;
313 return(SDL_SYS_CDioctl(cdrom->id, MCI_PLAY, flags, &mci_play));
314}
315
316/* Pause play */
317static int SDL_SYS_CDPause(SDL_CD *cdrom)
318{
319#ifdef BROKEN_MCI_PAUSE
320 SDL_paused[cdrom->id] = 1;
321#endif
322 return(SDL_SYS_CDioctl(cdrom->id, MCI_PAUSE, MCI_WAIT, NULL));
323}
324
325/* Resume play */
326static int SDL_SYS_CDResume(SDL_CD *cdrom)
327{
328#ifdef BROKEN_MCI_PAUSE
329 MCI_STATUS_PARMS mci_status;
330 int okay;
331 int flags;
332
333 okay = 0;
334 /* Play from the current play position to the end position set earlier */
335 flags = MCI_STATUS_ITEM | MCI_WAIT;
336 mci_status.dwItem = MCI_STATUS_POSITION;
337 if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) {
338 MCI_PLAY_PARMS mci_play;
339
340 flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
341 mci_play.dwCallback = 0;
342 mci_play.dwFrom = mci_status.dwReturn;
343 mci_play.dwTo = SDL_CD_end_position;
344 if (SDL_SYS_CDioctl(cdrom->id,MCI_PLAY,flags,&mci_play) == 0) {
345 okay = 1;
346 SDL_paused[cdrom->id] = 0;
347 }
348 }
349 return(okay ? 0 : -1);
350#else
351 return(SDL_SYS_CDioctl(cdrom->id, MCI_RESUME, MCI_WAIT, NULL));
352#endif /* BROKEN_MCI_PAUSE */
353}
354
355/* Stop play */
356static int SDL_SYS_CDStop(SDL_CD *cdrom)
357{
358 return(SDL_SYS_CDioctl(cdrom->id, MCI_STOP, MCI_WAIT, NULL));
359}
360
361/* Eject the CD-ROM */
362static int SDL_SYS_CDEject(SDL_CD *cdrom)
363{
364 return(SDL_SYS_CDioctl(cdrom->id, MCI_SET, MCI_SET_DOOR_OPEN, NULL));
365}
366
367/* Close the CD-ROM handle */
368static void SDL_SYS_CDClose(SDL_CD *cdrom)
369{
370 SDL_SYS_CDioctl(cdrom->id, MCI_CLOSE, MCI_WAIT, NULL);
371}
372
373void SDL_SYS_CDQuit(void)
374{
375 int i;
376
377 if ( SDL_numcds > 0 ) {
378 for ( i=0; i<SDL_numcds; ++i ) {
379 SDL_free(SDL_cdlist[i]);
380 SDL_cdlist[i] = NULL;
381 }
382 SDL_numcds = 0;
383 }
384}
385
386#endif /* SDL_CDROM_WIN32 */