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