From eda1583d7074093128a20c0f8560802b15b3127f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 22 Jul 2003 14:01:21 +0000 Subject: [PATCH] Added audio and CD-ROM support for OSF/Tru64 (thanks Hayashi!) --- configure.in | 14 +- include/SDL_types.h | 4 +- src/audio/Makefile.am | 24 +- src/audio/SDL_audio.c | 3 + src/audio/SDL_sysaudio.h | 3 + src/audio/mme/.cvsignore | 6 + src/audio/mme/Makefile.am | 9 + src/audio/mme/SDL_mmeaudio.c | 256 ++++++++++++++++++++ src/audio/mme/SDL_mmeaudio.h | 59 +++++ src/audio/riscos/.cvsignore | 6 + src/cdrom/Makefile.am | 25 +- src/cdrom/osf/.cvsignore | 6 + src/cdrom/osf/Makefile.am | 8 + src/cdrom/osf/SDL_syscdrom.c | 453 +++++++++++++++++++++++++++++++++++ 14 files changed, 856 insertions(+), 20 deletions(-) create mode 100644 src/audio/mme/.cvsignore create mode 100644 src/audio/mme/Makefile.am create mode 100644 src/audio/mme/SDL_mmeaudio.c create mode 100644 src/audio/mme/SDL_mmeaudio.h create mode 100644 src/audio/riscos/.cvsignore create mode 100644 src/cdrom/osf/.cvsignore create mode 100644 src/cdrom/osf/Makefile.am create mode 100644 src/cdrom/osf/SDL_syscdrom.c diff --git a/configure.in b/configure.in index 966aa2a4a..47a2eb77f 100644 --- a/configure.in +++ b/configure.in @@ -2170,13 +2170,15 @@ case "$target" in CheckAAlib CheckOpenGL CheckPTHREAD + SDL_LIBS="$SDL_LIBS -lrt" # Set up files for the main() stub COPY_ARCH_SRC(src/main, linux, SDL_main.c) # Set up files for the audio library if test x$enable_audio = xyes; then - CFLAGS="$CFLAGS -DSUNAUDIO_SUPPORT" - AUDIO_SUBDIRS="$AUDIO_SUBDIRS sun" - AUDIO_DRIVERS="$AUDIO_DRIVERS sun/libaudio_sun.la" + CFLAGS="$CFLAGS -I/usr/include/mme -DMMEAUDIO_SUPPORT" + SYSTEM_LIBS="$SYSTEM_LIBS -lmme" + AUDIO_SUBDIRS="$AUDIO_SUBDIRS mme" + AUDIO_DRIVERS="$AUDIO_DRIVERS mme/libaudio_mme.la" fi # Set up files for the joystick library # (No joystick support yet) @@ -2187,8 +2189,8 @@ case "$target" in # Set up files for the cdrom library # (No cdrom support yet) if test x$enable_cdrom = xyes; then - CDROM_SUBDIRS="$CDROM_SUBDIRS dummy" - CDROM_DRIVERS="$CDROM_DRIVERS dummy/libcdrom_dummy.la" + CDROM_SUBDIRS="$CDROM_SUBDIRS osf" + CDROM_DRIVERS="$CDROM_DRIVERS osf/libcdrom_osf.la" fi # Set up files for the thread library if test x$enable_threads = xyes; then @@ -2626,6 +2628,7 @@ src/audio/dsp/Makefile src/audio/esd/Makefile src/audio/macrom/Makefile src/audio/mint/Makefile +src/audio/mme/Makefile src/audio/nas/Makefile src/audio/nto/Makefile src/audio/openbsd/Makefile @@ -2695,6 +2698,7 @@ src/cdrom/linux/Makefile src/cdrom/macos/Makefile src/cdrom/macosx/Makefile src/cdrom/openbsd/Makefile +src/cdrom/osf/Makefile src/cdrom/qnx/Makefile src/cdrom/win32/Makefile src/thread/Makefile diff --git a/include/SDL_types.h b/include/SDL_types.h index 15547bcde..214e89e2b 100644 --- a/include/SDL_types.h +++ b/include/SDL_types.h @@ -47,7 +47,7 @@ typedef signed int Sint32; /* Figure out how to support 64-bit datatypes */ #if !defined(__STRICT_ANSI__) -#if defined(__GNUC__) || defined(__MWERKS__) || defined(__SUNPRO_C) +#if defined(__GNUC__) || defined(__MWERKS__) || defined(__DECC) #define SDL_HAS_64BIT_TYPE long long #elif defined(_MSC_VER) /* VC++ */ #define SDL_HAS_64BIT_TYPE __int64 @@ -61,7 +61,9 @@ typedef signed int Sint32; /* The 64-bit datatype isn't supported on all platforms */ #ifdef SDL_HAS_64BIT_TYPE +#ifndef H_MMBASIC typedef unsigned SDL_HAS_64BIT_TYPE Uint64; +#endif typedef SDL_HAS_64BIT_TYPE Sint64; #else /* This is really just a hack to prevent the compiler from complaining */ diff --git a/src/audio/Makefile.am b/src/audio/Makefile.am index 44485e13c..2dc1331bc 100644 --- a/src/audio/Makefile.am +++ b/src/audio/Makefile.am @@ -5,8 +5,28 @@ noinst_LTLIBRARIES = libaudio.la # Define which subdirectories need to be built SUBDIRS = @AUDIO_SUBDIRS@ -DIST_SUBDIRS = alsa arts baudio dma dmedia dsp esd macrom nas nto openbsd \ - paudio riscos sun ums windib windx5 disk mint dc +DIST_SUBDIRS = \ + alsa \ + arts \ + baudio \ + dc \ + disk \ + dma \ + dmedia \ + dsp \ + esd \ + macrom \ + mint \ + mme \ + nas \ + nto \ + openbsd \ + paudio \ + riscos \ + sun \ + ums \ + windib \ + windx5 DRIVERS = @AUDIO_DRIVERS@ diff --git a/src/audio/SDL_audio.c b/src/audio/SDL_audio.c index 23ebbdaa5..d18dbc135 100644 --- a/src/audio/SDL_audio.c +++ b/src/audio/SDL_audio.c @@ -83,6 +83,9 @@ static AudioBootStrap *bootstrap[] = { #ifdef ENABLE_AHI &AHI_bootstrap, #endif +#ifdef MMEAUDIO_SUPPORT + &MMEAUDIO_bootstrap, +#endif #ifdef MINTAUDIO_SUPPORT &MINTAUDIO_GSXB_bootstrap, &MINTAUDIO_MCSN_bootstrap, diff --git a/src/audio/SDL_sysaudio.h b/src/audio/SDL_sysaudio.h index 4a745dcc6..654ce81b8 100644 --- a/src/audio/SDL_sysaudio.h +++ b/src/audio/SDL_sysaudio.h @@ -163,6 +163,9 @@ extern AudioBootStrap DCAUD_bootstrap; #ifdef DRENDERER_SUPPORT extern AudioBootStrap DRENDERER_bootstrap; #endif +#ifdef MMEAUDIO_SUPPORT +extern AudioBootStrap MMEAUDIO_bootstrap; +#endif /* This is the current audio device */ extern SDL_AudioDevice *current_audio; diff --git a/src/audio/mme/.cvsignore b/src/audio/mme/.cvsignore new file mode 100644 index 000000000..899d53557 --- /dev/null +++ b/src/audio/mme/.cvsignore @@ -0,0 +1,6 @@ +Makefile.in +Makefile +.libs +*.o +*.lo +*.la diff --git a/src/audio/mme/Makefile.am b/src/audio/mme/Makefile.am new file mode 100644 index 000000000..b5ab2d6d0 --- /dev/null +++ b/src/audio/mme/Makefile.am @@ -0,0 +1,9 @@ + +## Makefile.am for SDL using the Tru64 MME sound driver + +noinst_LTLIBRARIES = libaudio_mme.la +libaudio_mme_la_SOURCES = $(SRCS) + +# The SDL audio driver sources +SRCS = SDL_mmeaudio.c \ + SDL_mmeaudio.h diff --git a/src/audio/mme/SDL_mmeaudio.c b/src/audio/mme/SDL_mmeaudio.c new file mode 100644 index 000000000..5ea8a6931 --- /dev/null +++ b/src/audio/mme/SDL_mmeaudio.c @@ -0,0 +1,256 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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 +*/ + +/* Tru64 UNIX MME support */ +#include "SDL_mmeaudio.h" + +static BOOL inUse[NUM_BUFFERS]; + +/* Audio driver functions */ +static int MME_OpenAudio(_THIS, SDL_AudioSpec *spec); +static void MME_WaitAudio(_THIS); +static Uint8 *MME_GetAudioBuf(_THIS); +static void MME_PlayAudio(_THIS); +static void MME_WaitDone(_THIS); +static void MME_CloseAudio(_THIS); + +/* Audio driver bootstrap functions */ +static int Audio_Available(void) +{ + return(1); +} + +static void Audio_DeleteDevice(SDL_AudioDevice *device) +{ + if ( device ) { + if ( device->hidden ) { + free(device->hidden); + device->hidden = NULL; + } + free(device); + device = NULL; + } +} + +static SDL_AudioDevice *Audio_CreateDevice(int devindex) +{ + SDL_AudioDevice *this; + +/* Initialize all variables that we clean on shutdown */ + this = malloc(sizeof(SDL_AudioDevice)); + if ( this ) { + memset(this, 0, (sizeof *this)); + this->hidden = malloc((sizeof *this->hidden)); + } + if ( (this == NULL) || (this->hidden == NULL) ) { + SDL_OutOfMemory(); + if ( this ) { + free(this); + } + return(0); + } + memset(this->hidden, 0, (sizeof *this->hidden)); + /* Set the function pointers */ + this->OpenAudio = MME_OpenAudio; + this->WaitAudio = MME_WaitAudio; + this->PlayAudio = MME_PlayAudio; + this->GetAudioBuf = MME_GetAudioBuf; + this->WaitDone = MME_WaitDone; + this->CloseAudio = MME_CloseAudio; + this->free = Audio_DeleteDevice; + + return this; +} + +AudioBootStrap MMEAUDIO_bootstrap = { + "waveout", "Tru64 MME WaveOut", + Audio_Available, Audio_CreateDevice +}; + +static void SetMMerror(char *function, MMRESULT code) +{ + int len; + char errbuf[MAXERRORLENGTH]; + + sprintf(errbuf, "%s: ", function); + len = strlen(errbuf); + waveOutGetErrorText(code, errbuf+len, MAXERRORLENGTH-len); + SDL_SetError("%s",errbuf); +} + +static void CALLBACK MME_CALLBACK(HWAVEOUT hwo, + UINT uMsg, + DWORD dwInstance, + LPARAM dwParam1, + LPARAM dwParam2) +{ + WAVEHDR *wp = (WAVEHDR *) dwParam1; + + if ( uMsg == WOM_DONE ) + inUse[wp->dwUser] = FALSE; +} + +static int MME_OpenAudio(_THIS, SDL_AudioSpec *spec) +{ + MMRESULT result; + int i; + + mixbuf = NULL; + + /* Set basic WAVE format parameters */ + shm = mmeAllocMem(sizeof(*shm)); + if ( shm == NULL ) { + SDL_SetError("Out of memory: shm"); + return(-1); + } + shm->sound = 0; + shm->wFmt.wf.wFormatTag = WAVE_FORMAT_PCM; + + /* Determine the audio parameters from the AudioSpec */ + switch ( spec->format & 0xFF ) { + case 8: + /* Unsigned 8 bit audio data */ + spec->format = AUDIO_U8; + shm->wFmt.wBitsPerSample = 8; + break; + case 16: + /* Signed 16 bit audio data */ + spec->format = AUDIO_S16; + shm->wFmt.wBitsPerSample = 16; + break; + default: + SDL_SetError("Unsupported audio format"); + return(-1); + } + + shm->wFmt.wf.nChannels = spec->channels; + shm->wFmt.wf.nSamplesPerSec = spec->freq; + shm->wFmt.wf.nBlockAlign = + shm->wFmt.wf.nChannels * shm->wFmt.wBitsPerSample / 8; + shm->wFmt.wf.nAvgBytesPerSec = + shm->wFmt.wf.nSamplesPerSec * shm->wFmt.wf.nBlockAlign; + + /* Check the buffer size -- minimum of 1/4 second (word aligned) */ + if ( spec->samples < (spec->freq/4) ) + spec->samples = ((spec->freq/4)+3)&~3; + + /* Update the fragment size as size in bytes */ + SDL_CalculateAudioSpec(spec); + + /* Open the audio device */ + result = waveOutOpen(&(shm->sound), + WAVE_MAPPER, + &(shm->wFmt.wf), + MME_CALLBACK, + NULL, + (CALLBACK_FUNCTION|WAVE_OPEN_SHAREABLE)); + if ( result != MMSYSERR_NOERROR ) { + SetMMerror("waveOutOpen()", result); + return(-1); + } + + /* Create the sound buffers */ + mixbuf = (Uint8 *)mmeAllocBuffer(NUM_BUFFERS * (spec->size)); + if ( mixbuf == NULL ) { + SDL_SetError("Out of memory: mixbuf"); + return(-1); + } + + for (i = 0; i < NUM_BUFFERS; i++) { + shm->wHdr[i].lpData = &mixbuf[i * (spec->size)]; + shm->wHdr[i].dwBufferLength = spec->size; + shm->wHdr[i].dwFlags = 0; + shm->wHdr[i].dwUser = i; + shm->wHdr[i].dwLoops = 0; /* loop control counter */ + shm->wHdr[i].lpNext = NULL; /* reserved for driver */ + shm->wHdr[i].reserved = 0; + inUse[i] = FALSE; + } + next_buffer = 0; + return 0; +} + +static void MME_WaitAudio(_THIS) +{ + mmeWaitForCallbacks (); + mmeProcessCallbacks (); +} + +static Uint8 *MME_GetAudioBuf(_THIS) +{ + Uint8 *retval; + + while ( inUse[next_buffer] ) + ; + + inUse[next_buffer] = TRUE; + retval = (Uint8 *)(shm->wHdr[next_buffer].lpData); + return retval; +} + +static void MME_PlayAudio(_THIS) +{ + /* Queue it up */ + waveOutWrite(shm->sound, &(shm->wHdr[next_buffer]), sizeof(WAVEHDR)); + next_buffer = (next_buffer+1)%NUM_BUFFERS; +} + +static void MME_WaitDone(_THIS) +{ + MMRESULT result; + int i; + + if ( shm->sound ) { + result = waveOutReset(shm->sound); + if ( result != MMSYSERR_NOERROR ) + SetMMerror("waveOutReset()", result); + else { + mmeWaitForCallbacks (); + mmeProcessCallbacks (); + } + } +} + +static void MME_CloseAudio(_THIS) +{ + MMRESULT result; + + if ( mixbuf ) { + result = mmeFreeBuffer(mixbuf); + if (result != MMSYSERR_NOERROR ) + SetMMerror("mmeFreeBuffer", result); + mixbuf = NULL; + } + + if ( shm ) { + if ( shm->sound ) { + result = waveOutClose(shm->sound); + if (result != MMSYSERR_NOERROR ) + SetMMerror("waveOutClose()", result); + } + result = mmeFreeMem(shm); + if (result != MMSYSERR_NOERROR ) + SetMMerror("mmeFreeMem()", result); + shm = NULL; + } +} + diff --git a/src/audio/mme/SDL_mmeaudio.h b/src/audio/mme/SDL_mmeaudio.h new file mode 100644 index 000000000..41d3c0470 --- /dev/null +++ b/src/audio/mme/SDL_mmeaudio.h @@ -0,0 +1,59 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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 +*/ + +/* Allow access to a raw mixing buffer */ + +#include +#include +#include +#include + +#include "SDL_audio.h" +#include "SDL_mutex.h" +#include "SDL_timer.h" +#include "SDL_audio_c.h" + +#ifndef _SDL_lowaudio_h +#define _SDL_lowaudio_h +#include "SDL_sysaudio.h" + +/* Hidden "this" pointer for the video functions */ +#define _THIS SDL_AudioDevice *this +#define NUM_BUFFERS 2 + +struct SharedMem { + HWAVEOUT sound; + WAVEHDR wHdr[NUM_BUFFERS]; + PCMWAVEFORMAT wFmt; +}; + +struct SDL_PrivateAudioData { + Uint8 *mixbuf; /* The raw allocated mixing buffer */ + struct SharedMem *shm; + int next_buffer; +}; + +#define shm (this->hidden->shm) +#define mixbuf (this->hidden->mixbuf) +#define next_buffer (this->hidden->next_buffer) +/* Old variable names */ +#endif /* _SDL_lowaudio_h */ diff --git a/src/audio/riscos/.cvsignore b/src/audio/riscos/.cvsignore new file mode 100644 index 000000000..899d53557 --- /dev/null +++ b/src/audio/riscos/.cvsignore @@ -0,0 +1,6 @@ +Makefile.in +Makefile +.libs +*.o +*.lo +*.la diff --git a/src/cdrom/Makefile.am b/src/cdrom/Makefile.am index 5dbd7bc8e..bec395430 100644 --- a/src/cdrom/Makefile.am +++ b/src/cdrom/Makefile.am @@ -5,18 +5,19 @@ noinst_LTLIBRARIES = libcdrom.la # Define which subdirectories need to be built SUBDIRS = @CDROM_SUBDIRS@ -DIST_SUBDIRS = \ - aix \ - beos \ - bsdi \ - dc \ - dummy \ - freebsd \ - linux \ - macos \ - macosx \ - openbsd \ - qnx \ +DIST_SUBDIRS = \ + aix \ + beos \ + bsdi \ + dc \ + dummy \ + freebsd \ + linux \ + macos \ + macosx \ + openbsd \ + osf \ + qnx \ win32 DRIVERS = @CDROM_DRIVERS@ diff --git a/src/cdrom/osf/.cvsignore b/src/cdrom/osf/.cvsignore new file mode 100644 index 000000000..899d53557 --- /dev/null +++ b/src/cdrom/osf/.cvsignore @@ -0,0 +1,6 @@ +Makefile.in +Makefile +.libs +*.o +*.lo +*.la diff --git a/src/cdrom/osf/Makefile.am b/src/cdrom/osf/Makefile.am new file mode 100644 index 000000000..2cf49f473 --- /dev/null +++ b/src/cdrom/osf/Makefile.am @@ -0,0 +1,8 @@ + +## Makefile.am for the osf cdrom driver for SDL + +noinst_LTLIBRARIES = libcdrom_osf.la +libcdrom_osf_la_SOURCES = $(SRCS) + +# The SDL cdrom driver sources +SRCS = SDL_syscdrom.c diff --git a/src/cdrom/osf/SDL_syscdrom.c b/src/cdrom/osf/SDL_syscdrom.c new file mode 100644 index 000000000..4ee92c0c1 --- /dev/null +++ b/src/cdrom/osf/SDL_syscdrom.c @@ -0,0 +1,453 @@ +/* + 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 + + +*/ + + +/* Functions for system-level CD-ROM audio control */ + +//#define DEBUG_CDROM 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "SDL_error.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 */ +/* Caution!! Not tested. */ +static int CheckDrive(char *drive, struct stat *stbuf) +{ + int is_cd, cdfd; + struct cd_sub_channel 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_RDWR|O_NDELAY), 0); + if ( cdfd >= 0 ) { + info.sch_address_format = CDROM_MSF_FORMAT; + info.sch_data_format = CDROM_CURRENT_POSITION; + info.sch_alloc_length = 0; + info.sch_track_number = 0; + info.sch_buffer = 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, CDROM_READ_SUBCHANNEL, &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; ist_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] = (char *)malloc(strlen(drive)+1); + if ( SDL_cdlist[i] == NULL ) { + SDL_OutOfMemory(); + return; + } + + strcpy(SDL_cdlist[i], drive); + 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[] = { + "?0 rdisk/cdrom?",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 = getenv("SDL_CDROM"); /* ':' separated list of devices */ + if ( SDLcdrom != NULL ) { + char *cdpath, *delim; + cdpath = malloc(strlen(SDLcdrom)+1); + if ( cdpath != NULL ) { + strcpy(cdpath, SDLcdrom); + SDLcdrom = cdpath; + do { + delim = strchr(SDLcdrom, ':'); + if ( delim ) { + *delim++ = '\0'; + } + if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) { + AddDrive(SDLcdrom, &stbuf); + } + if ( delim ) { + SDLcdrom = delim; + } else { + SDLcdrom = NULL; + } + } while ( SDLcdrom ); + 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 ) { + sprintf(drive, "/dev/%sc", &checklist[i][3]); + insert = 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 { + sprintf(drive, "/dev/%s", checklist[i]); + if ( CheckDrive(drive, &stbuf) > 0 ) { + AddDrive(drive, &stbuf); + } + } + } +/* + SDLcdrom=malloc(sizeof(char) * 32); + strcpy(SDLcdrom,"/dev/rdisk/cdrom0c"); + SDL_cdlist[0] = SDLcdrom; + stat(SDLcdrom, &stbuf); + SDL_cdmode[0] = stbuf.st_rdev; + SDL_numcds = 1; + */ + 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; + } + + (char *)cdte = 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, + &msf.msf_starting_M_unit, + &msf.msf_starting_S_unit, + &msf.msf_starting_F_unit); + FRAMES_TO_MSF(end, + &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