CD-ROM support is so passé :)

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%403773
This commit is contained in:
Sam Lantinga 2009-09-05 09:11:03 +00:00
parent 8c260f6e84
commit 633d710201
40 changed files with 3 additions and 9394 deletions

2
TODO
View File

@ -50,4 +50,4 @@ we should do it though, since the 1.2 series should not break binary
compatibility in this way.
Requests:
* PCM and CDROM volume control (deprecated, but possible)
* PCM volume control (deprecated, but possible)

View File

@ -206,7 +206,6 @@ fi
# Standard C sources
SOURCES="$SOURCES $srcdir/src/*.c"
SOURCES="$SOURCES $srcdir/src/audio/*.c"
SOURCES="$SOURCES $srcdir/src/cdrom/*.c"
SOURCES="$SOURCES $srcdir/src/cpuinfo/*.c"
SOURCES="$SOURCES $srcdir/src/events/*.c"
SOURCES="$SOURCES $srcdir/src/file/*.c"
@ -265,12 +264,6 @@ if test x$enable_power != xyes; then
else
SOURCES="$SOURCES $srcdir/src/power/*.c"
fi
AC_ARG_ENABLE(cdrom,
AC_HELP_STRING([--enable-cdrom], [Enable the cdrom subsystem [[default=yes]]]),
, enable_cdrom=yes)
if test x$enable_cdrom != xyes; then
AC_DEFINE(SDL_CDROM_DISABLED)
fi
AC_ARG_ENABLE(threads,
AC_HELP_STRING([--enable-threads], [Enable the threading subsystem [[default=yes]]]),
, enable_threads=yes)
@ -2481,41 +2474,6 @@ case "$host" in
;;
esac
fi
# Set up files for the cdrom library
if test x$enable_cdrom = xyes; then
case $ARCH in
linux|solaris)
AC_DEFINE(SDL_CDROM_LINUX)
SOURCES="$SOURCES $srcdir/src/cdrom/linux/*.c"
have_cdrom=yes
;;
*freebsd*)
AC_DEFINE(SDL_CDROM_FREEBSD)
SOURCES="$SOURCES $srcdir/src/cdrom/freebsd/*.c"
have_cdrom=yes
;;
*openbsd*|*netbsd*)
AC_DEFINE(SDL_CDROM_OPENBSD)
SOURCES="$SOURCES $srcdir/src/cdrom/openbsd/*.c"
have_cdrom=yes
;;
bsdi)
AC_DEFINE(SDL_CDROM_BSDI)
SOURCES="$SOURCES $srcdir/src/cdrom/bsdi/*.c"
have_cdrom=yes
;;
aix)
AC_DEFINE(SDL_CDROM_AIX)
SOURCES="$SOURCES $srcdir/src/cdrom/aix/*.c"
have_cdrom=yes
;;
osf)
AC_DEFINE(SDL_CDROM_OSF)
SOURCES="$SOURCES $srcdir/src/cdrom/osf/*.c"
have_cdrom=yes
;;
esac
fi
# Set up files for the thread library
if test x$enable_threads = xyes -a x$use_pthreads != xyes -a x$use_pth != xyes -a x$ARCH = xirix; then
AC_DEFINE(SDL_THREAD_SPROC)
@ -2560,12 +2518,6 @@ case "$host" in
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lasound"
have_audio=yes
fi
# Set up files for the cdrom library
if test x$enable_cdrom = xyes; then
AC_DEFINE(SDL_CDROM_QNX)
SOURCES="$SOURCES $srcdir/src/cdrom/qnx/*.c"
have_cdrom=yes
fi
# Set up files for the timer library
if test x$enable_timers = xyes; then
AC_DEFINE(SDL_TIMER_UNIX)
@ -2743,12 +2695,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
SOURCES="$SOURCES $srcdir/src/power/windows/SDL_syspower.c"
have_power=yes
fi
# Set up files for the cdrom library
if test x$enable_cdrom = xyes; then
AC_DEFINE(SDL_CDROM_WIN32)
SOURCES="$SOURCES $srcdir/src/cdrom/win32/*.c"
have_cdrom=yes
fi
# Set up files for the thread library
if test x$enable_threads = xyes; then
AC_DEFINE(SDL_THREAD_WIN32)
@ -2801,12 +2747,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
SOURCES="$SOURCES $srcdir/src/joystick/beos/*.cc"
have_joystick=yes
fi
# Set up files for the cdrom library
if test x$enable_cdrom = xyes; then
AC_DEFINE(SDL_CDROM_BEOS)
SOURCES="$SOURCES $srcdir/src/cdrom/beos/*.cc"
have_cdrom=yes
fi
# Set up files for the thread library
if test x$enable_threads = xyes; then
AC_DEFINE(SDL_THREAD_BEOS)
@ -2910,12 +2850,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
SOURCES="$SOURCES $srcdir/src/power/macosx/*.c"
have_power=yes
fi
# Set up files for the cdrom library
if test x$enable_cdrom = xyes; then
AC_DEFINE(SDL_CDROM_MACOSX)
SOURCES="$SOURCES $srcdir/src/cdrom/macosx/*.c"
have_cdrom=yes
fi
# Set up files for the timer library
if test x$enable_timers = xyes; then
AC_DEFINE(SDL_TIMER_UNIX)
@ -2929,7 +2863,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
# If either the audio or CD driver is used, add the AudioUnit framework
if test x$enable_audio = xyes -o x$enable_cdrom = xyes; then
if test x$enable_audio = xyes; then
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
fi
;;
@ -2959,12 +2893,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
SOURCES="$SOURCES $srcdir/src/joystick/mint/*.c"
have_joystick=yes
fi
# Set up files for the cdrom library
if test x$enable_cdrom = xyes; then
AC_DEFINE(SDL_CDROM_MINT)
SOURCES="$SOURCES $srcdir/src/cdrom/mint/*.c"
have_cdrom=yes
fi
# Set up files for the timer library
if test x$enable_timers = xyes; then
if test x$enable_threads = xyes -a x$enable_pth = xyes; then
@ -3025,12 +2953,6 @@ if test x$have_haptic != xyes; then
fi
SOURCES="$SOURCES $srcdir/src/haptic/dummy/*.c"
fi
if test x$have_cdrom != xyes; then
if test x$enable_cdrom = xyes; then
AC_DEFINE(SDL_CDROM_DISABLED)
fi
SOURCES="$SOURCES $srcdir/src/cdrom/dummy/*.c"
fi
if test x$have_threads != xyes; then
if test x$enable_threads = xyes; then
AC_DEFINE(SDL_THREADS_DISABLED)

View File

@ -78,7 +78,6 @@ Enjoy!
#include "SDL_stdinc.h"
#include "SDL_atomic.h"
#include "SDL_audio.h"
#include "SDL_cdrom.h"
#include "SDL_cpuinfo.h"
#include "SDL_endian.h"
#include "SDL_error.h"
@ -109,7 +108,6 @@ extern "C" {
#define SDL_INIT_TIMER 0x00000001
#define SDL_INIT_AUDIO 0x00000010
#define SDL_INIT_VIDEO 0x00000020
#define SDL_INIT_CDROM 0x00000100
#define SDL_INIT_JOYSTICK 0x00000200
#define SDL_INIT_HAPTIC 0x00001000
#define SDL_INIT_NOPARACHUTE 0x00100000 /* Don't catch fatal signals */

View File

@ -1,186 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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
*/
/**
* \file SDL_cdrom.h
*
* This is the CD-audio control API for Simple DirectMedia Layer
*/
#ifndef _SDL_cdrom_h
#define _SDL_cdrom_h
#include "SDL_stdinc.h"
#include "SDL_error.h"
#include "begin_code.h"
/* Set up for C function definitions, even when using C++ */
#ifdef __cplusplus
/* *INDENT-OFF* */
extern "C" {
/* *INDENT-ON* */
#endif
/* In order to use these functions, SDL_Init() must have been called
with the SDL_INIT_CDROM flag. This causes SDL to scan the system
for CD-ROM drives, and load appropriate drivers.
*/
/* The maximum number of CD-ROM tracks on a disk */
#define SDL_MAX_TRACKS 99
/* The types of CD-ROM track possible */
#define SDL_AUDIO_TRACK 0x00
#define SDL_DATA_TRACK 0x04
/* The possible states which a CD-ROM drive can be in. */
typedef enum
{
CD_TRAYEMPTY,
CD_STOPPED,
CD_PLAYING,
CD_PAUSED,
CD_ERROR = -1
} CDstatus;
/* Given a status, returns true if there's a disk in the drive */
#define CD_INDRIVE(status) ((int)(status) > 0)
typedef struct SDL_CDtrack
{
Uint8 id; /* Track number */
Uint8 type; /* Data or audio track */
Uint16 unused;
Uint32 length; /* Length, in frames, of this track */
Uint32 offset; /* Offset, in frames, from start of disk */
} SDL_CDtrack;
/* This structure is only current as of the last call to SDL_CDStatus() */
typedef struct SDL_CD
{
int id; /* Private drive identifier */
CDstatus status; /* Current drive status */
/* The rest of this structure is only valid if there's a CD in drive */
int numtracks; /* Number of tracks on disk */
int cur_track; /* Current track position */
int cur_frame; /* Current frame offset within current track */
SDL_CDtrack track[SDL_MAX_TRACKS + 1];
} SDL_CD;
/* Conversion functions from frames to Minute/Second/Frames and vice versa */
#define CD_FPS 75
#define FRAMES_TO_MSF(f, M,S,F) { \
int value = f; \
*(F) = value%CD_FPS; \
value /= CD_FPS; \
*(S) = value%60; \
value /= 60; \
*(M) = value; \
}
#define MSF_TO_FRAMES(M, S, F) ((M)*60*CD_FPS+(S)*CD_FPS+(F))
/* CD-audio API functions: */
/* Returns the number of CD-ROM drives on the system, or -1 if
SDL_Init() has not been called with the SDL_INIT_CDROM flag.
*/
extern DECLSPEC int SDLCALL SDL_CDNumDrives(void);
/* Returns a human-readable, system-dependent identifier for the CD-ROM.
Example:
"/dev/cdrom"
"E:"
"/dev/disk/ide/1/master"
*/
extern DECLSPEC const char *SDLCALL SDL_CDName(int drive);
/* Opens a CD-ROM drive for access. It returns a drive handle on success,
or NULL if the drive was invalid or busy. This newly opened CD-ROM
becomes the default CD used when other CD functions are passed a NULL
CD-ROM handle.
Drives are numbered starting with 0. Drive 0 is the system default CD-ROM.
*/
extern DECLSPEC SDL_CD *SDLCALL SDL_CDOpen(int drive);
/* This function returns the current status of the given drive.
If the drive has a CD in it, the table of contents of the CD and current
play position of the CD will be stored in the SDL_CD structure.
*/
extern DECLSPEC CDstatus SDLCALL SDL_CDStatus(SDL_CD * cdrom);
/* Play the given CD starting at 'start_track' and 'start_frame' for 'ntracks'
tracks and 'nframes' frames. If both 'ntrack' and 'nframe' are 0, play
until the end of the CD. This function will skip data tracks.
This function should only be called after calling SDL_CDStatus() to
get track information about the CD.
For example:
// Play entire CD:
if ( CD_INDRIVE(SDL_CDStatus(cdrom)) )
SDL_CDPlayTracks(cdrom, 0, 0, 0, 0);
// Play last track:
if ( CD_INDRIVE(SDL_CDStatus(cdrom)) ) {
SDL_CDPlayTracks(cdrom, cdrom->numtracks-1, 0, 0, 0);
}
// Play first and second track and 10 seconds of third track:
if ( CD_INDRIVE(SDL_CDStatus(cdrom)) )
SDL_CDPlayTracks(cdrom, 0, 0, 2, 10);
This function returns 0, or -1 if there was an error.
*/
extern DECLSPEC int SDLCALL SDL_CDPlayTracks(SDL_CD * cdrom,
int start_track,
int start_frame, int ntracks,
int nframes);
/* Play the given CD starting at 'start' frame for 'length' frames.
It returns 0, or -1 if there was an error.
*/
extern DECLSPEC int SDLCALL SDL_CDPlay(SDL_CD * cdrom, int start, int length);
/* Pause play -- returns 0, or -1 on error */
extern DECLSPEC int SDLCALL SDL_CDPause(SDL_CD * cdrom);
/* Resume play -- returns 0, or -1 on error */
extern DECLSPEC int SDLCALL SDL_CDResume(SDL_CD * cdrom);
/* Stop play -- returns 0, or -1 on error */
extern DECLSPEC int SDLCALL SDL_CDStop(SDL_CD * cdrom);
/* Eject CD-ROM -- returns 0, or -1 on error */
extern DECLSPEC int SDLCALL SDL_CDEject(SDL_CD * cdrom);
/* Closes the handle for the CD-ROM drive */
extern DECLSPEC void SDLCALL SDL_CDClose(SDL_CD * cdrom);
/* Ends C function definitions when using C++ */
#ifdef __cplusplus
/* *INDENT-OFF* */
}
/* *INDENT-ON* */
#endif
#include "close_code.h"
#endif /* _SDL_video_h */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -160,7 +160,6 @@
/* Allow disabling of core subsystems */
#undef SDL_AUDIO_DISABLED
#undef SDL_CDROM_DISABLED
#undef SDL_CPUINFO_DISABLED
#undef SDL_EVENTS_DISABLED
#undef SDL_FILE_DISABLED
@ -204,22 +203,6 @@
#undef SDL_AUDIO_DRIVER_FUSIONSOUND
#undef SDL_AUDIO_DRIVER_FUSIONSOUND_DYNAMIC
/* Enable various cdrom drivers */
#undef SDL_CDROM_AIX
#undef SDL_CDROM_BEOS
#undef SDL_CDROM_BSDI
#undef SDL_CDROM_DC
#undef SDL_CDROM_DUMMY
#undef SDL_CDROM_FREEBSD
#undef SDL_CDROM_LINUX
#undef SDL_CDROM_MACOSX
#undef SDL_CDROM_MINT
#undef SDL_CDROM_OPENBSD
#undef SDL_CDROM_OS2
#undef SDL_CDROM_OSF
#undef SDL_CDROM_QNX
#undef SDL_CDROM_WIN32
/* Enable various input drivers */
#undef SDL_INPUT_LINUXEV
#undef SDL_INPUT_TSLIB

View File

@ -88,9 +88,6 @@ typedef unsigned long uintptr_t;
#define SDL_AUDIO_DRIVER_DISK 1
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable various cdrom drivers */
#define SDL_CDROM_DC 1
/* Enable various input drivers */
#define SDL_JOYSTICK_DC 1
#define SDL_HAPTIC_DUMMY 1

View File

@ -106,9 +106,6 @@ typedef unsigned long uintptr_t;
/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable the stub cdrom driver (src/cdrom/dummy/\*.c) */
#define SDL_CDROM_DISABLED 1
/* Enable the stub haptic driver (src/haptic/dummy/\*.c) */
#define SDL_HAPTIC_DISABLED 1

View File

@ -106,9 +106,6 @@
#define SDL_AUDIO_DRIVER_DISK 1
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable various cdrom drivers */
#define SDL_CDROM_MACOSX 1
/* Enable various input drivers */
#define SDL_JOYSTICK_IOKIT 1
#define SDL_HAPTIC_IOKIT 1

View File

@ -43,9 +43,6 @@ typedef unsigned long uintptr_t;
/* Enable the dummy audio driver (src/audio/dummy/\*.c) */
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable the stub cdrom driver (src/cdrom/dummy/\*.c) */
#define SDL_CDROM_DISABLED 1
/* Enable the stub joystick driver (src/joystick/dummy/\*.c) */
#define SDL_JOYSTICK_DISABLED 1

View File

@ -96,9 +96,6 @@ typedef unsigned __PTRDIFF_TYPE__ uintptr_t;
#define SDL_AUDIO_DRIVER_NDS 1
/*#define SDL_AUDIO_DRIVER_DUMMY 1 TODO: uncomment this later*/
/* DS doesn't have optical media */
#define SDL_CDROM_DISABLED 1
/* Enable various input drivers */
#define SDL_JOYSTICK_NDS 1
/*#define SDL_JOYSTICK_DUMMY 1 TODO: uncomment this later*/

View File

@ -116,9 +116,6 @@ typedef unsigned long long uint64_t;
#define SDL_AUDIO_DRIVER_DISK 1
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable various cdrom drivers */
#define SDL_CDROM_OS2 1
/* Enable various input drivers */
#define SDL_JOYSTICK_OS2 1
#define SDL_HAPTIC_DUMMY 1

View File

@ -95,7 +95,6 @@
#define HAVE_SETJMP 1
#define HAVE_NANOSLEEP 1
#define SDL_CDROM_DISABLED 1
#define SDL_AUDIO_DRIVER_DUMMY 1
#define SDL_AUDIO_DRIVER_OSS 1

View File

@ -150,13 +150,6 @@ typedef unsigned int uintptr_t;
#define SDL_AUDIO_DRIVER_DISK 1
#define SDL_AUDIO_DRIVER_DUMMY 1
/* Enable various cdrom drivers */
#ifdef _WIN32_WCE
#define SDL_CDROM_DISABLED 1
#else
#define SDL_CDROM_WIN32 1
#endif
/* Enable various input drivers */
#ifdef _WIN32_WCE
#define SDL_JOYSTICK_DISABLED 1

View File

@ -42,10 +42,6 @@ extern void SDL_JoystickQuit(void);
extern int SDL_HapticInit(void);
extern int SDL_HapticQuit(void);
#endif
#if !SDL_CDROM_DISABLED
extern int SDL_CDROMInit(void);
extern void SDL_CDROMQuit(void);
#endif
#if !SDL_TIMERS_DISABLED
extern void SDL_StartTicks(void);
extern int SDL_TimerInit(void);
@ -145,22 +141,6 @@ SDL_InitSubSystem(Uint32 flags)
return (-1);
}
#endif
#if !SDL_CDROM_DISABLED
/* Initialize the CD-ROM subsystem */
if ((flags & SDL_INIT_CDROM) && !(SDL_initialized & SDL_INIT_CDROM)) {
if (SDL_CDROMInit() < 0) {
return (-1);
}
SDL_initialized |= SDL_INIT_CDROM;
}
#else
if (flags & SDL_INIT_CDROM) {
SDL_SetError("SDL not built with cdrom support");
return (-1);
}
#endif
return (0);
}
@ -198,12 +178,6 @@ void
SDL_QuitSubSystem(Uint32 flags)
{
/* Shut down requested initialized subsystems */
#if !SDL_CDROM_DISABLED
if ((flags & SDL_initialized & SDL_INIT_CDROM)) {
SDL_CDROMQuit();
SDL_initialized &= ~SDL_INIT_CDROM;
}
#endif
#if !SDL_JOYSTICK_DISABLED
if ((flags & SDL_initialized & SDL_INIT_JOYSTICK)) {
SDL_JoystickQuit();

View File

@ -1,357 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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"
#define CLIP_FRAMES 10 /* Some CD-ROMs won't go all the way */
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;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,78 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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);
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,665 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,427 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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;
int raw_fd;
struct ide_ctrl_info info;
/* 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,550 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,187 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,44 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,422 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,585 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,397 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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.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 != kAudioUnitComponentType) {
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_SetInputCallback,
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_SetInputCallback,
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 (chunkHeader.ckID != 'FORM') {
result = -1;
if (result)
return 0; /*THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'"); */
}
if (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") */
/* 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") */
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;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,178 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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>
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
#include <AudioUnit/AUNTComponent.h>
#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;
SInt16 mForkRefNum;
AudioUnitInputCallback 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,
UInt32 * 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,
AudioBuffer * ioData);
OSStatus(*GetFileData) (struct S_AudioFileManager * afm,
void **inOutData, UInt32 * inOutDataSize);
void (*AfterRender) (struct S_AudioFileManager * afm);
/*public:*/
/*static */
OSStatus(*FileInputProc) (void *inRefCon,
AudioUnitRenderActionFlags inActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber, AudioBuffer * ioData);
} AudioFileManager;
AudioFileManager *new_AudioFileManager(AudioFilePlayer * inParent,
SInt16 inForkRefNum,
SInt64 inFileLength,
UInt32 inChunkSize);
void delete_AudioFileManager(AudioFileManager * afm);
#endif
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,657 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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;
UInt32 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;
UInt32 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, UInt32 * 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 inActionFlags,
const AudioTimeStamp * inTimeStamp,
UInt32 inBusNumber, AudioBuffer * ioData)
{
AudioFileManager *afm = (AudioFileManager *) inRefCon;
return afm->Render(afm, ioData);
}
static OSStatus
AudioFileManager_Render(AudioFileManager * afm, AudioBuffer * ioData)
{
OSStatus result = noErr;
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 (ioData->mDataByteSize > afm->mBufferSize - afm->mBufferOffset)
ioData->mDataByteSize = afm->mBufferSize - afm->mBufferOffset;
ioData->mData = (char *) afm->mTmpBuffer + afm->mBufferOffset;
afm->mBufferOffset += ioData->mDataByteSize;
afm->mByteCounter += ioData->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;
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,669 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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;
SInt16 forkRefNum;
SInt64 forkSize;
Ptr forkData = 0;
ByteCount actualRead;
CFDataRef dataRef = 0;
CFPropertyListRef propertyListRef = 0;
FSRefParam fsRefPB;
FSRef tocPlistFSRef;
const char *error = "Unspecified Error";
/* get stuff from .TOC.plist */
fsRefPB.ioCompletion = NULL;
fsRefPB.ioNamePtr = "\p.TOC.plist";
fsRefPB.ioVRefNum = theVolume;
fsRefPB.ioDirID = 0;
fsRefPB.newRef = &tocPlistFSRef;
theErr = PBMakeFSRefSync(&fsRefPB);
if (theErr != noErr) {
error = "PBMakeFSRefSync";
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 = kAudioUnitComponentType;
desc.componentSubType = kAudioUnitSubType_Output;
desc.componentManufacturer = kAudioUnitID_DefaultOutput;
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" */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,72 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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_cdrom.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__ */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,205 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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);
}
}
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,116 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,523 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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)
{
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;
}
/* 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,136 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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."
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,339 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 <cdromio.h>
#include <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
{
unsigned 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,430 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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)
{
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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,442 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,464 +0,0 @@
/*
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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,507 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -1,400 +0,0 @@
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2009 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_numcds = 0;
}
}
#endif /* SDL_CDROM_WIN32 */
/* vi: set ts=4 sw=4 expandtab: */

View File

@ -7,7 +7,7 @@ EXE = @EXE@
CFLAGS = @CFLAGS@
LIBS = @LIBS@
TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcdrom$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) testatomic$(EXE)
TARGETS = checkkeys$(EXE) graywin$(EXE) loopwave$(EXE) testresample$(EXE) testaudioinfo$(EXE) testmultiaudio$(EXE) testpower$(EXE) testalpha$(EXE) testbitmap$(EXE) testblitspeed$(EXE) testcursor$(EXE) testintersections$(EXE) testdraw2$(EXE) testdyngl$(EXE) testdyngles$(EXE) testerror$(EXE) testfile$(EXE) testgamma$(EXE) testgl$(EXE) testgl2$(EXE) testgles$(EXE) testhread$(EXE) testiconv$(EXE) testjoystick$(EXE) testkeys$(EXE) testlock$(EXE) testoverlay2$(EXE) testoverlay$(EXE) testpalette$(EXE) testplatform$(EXE) testsem$(EXE) testsprite$(EXE) testsprite2$(EXE) testtimer$(EXE) testver$(EXE) testvidinfo$(EXE) testwin$(EXE) testwm$(EXE) testwm2$(EXE) threadwin$(EXE) torturethread$(EXE) testloadso$(EXE) testhaptic$(EXE) testmmousetablet$(EXE) testatomic$(EXE)
all: Makefile $(TARGETS)
@ -44,9 +44,6 @@ testbitmap$(EXE): $(srcdir)/testbitmap.c
testblitspeed$(EXE): $(srcdir)/testblitspeed.c
$(CC) -o $@ $? $(CFLAGS) $(LIBS)
testcdrom$(EXE): $(srcdir)/testcdrom.c
$(CC) -o $@ $? $(CFLAGS) $(LIBS)
testcursor$(EXE): $(srcdir)/testcursor.c
$(CC) -o $@ $? $(CFLAGS) $(LIBS)

View File

@ -1,203 +0,0 @@
/* Test the SDL CD-ROM audio functions */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "SDL.h"
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
quit(int rc)
{
SDL_Quit();
exit(rc);
}
static void
PrintStatus(int driveindex, SDL_CD * cdrom)
{
CDstatus status;
char *status_str;
status = SDL_CDStatus(cdrom);
switch (status) {
case CD_TRAYEMPTY:
status_str = "tray empty";
break;
case CD_STOPPED:
status_str = "stopped";
break;
case CD_PLAYING:
status_str = "playing";
break;
case CD_PAUSED:
status_str = "paused";
break;
case CD_ERROR:
status_str = "error state";
break;
}
printf("Drive %d status: %s\n", driveindex, status_str);
if (status >= CD_PLAYING) {
int m, s, f;
FRAMES_TO_MSF(cdrom->cur_frame, &m, &s, &f);
printf("Currently playing track %d, %d:%2.2d\n",
cdrom->track[cdrom->cur_track].id, m, s);
}
}
static void
ListTracks(SDL_CD * cdrom)
{
int i;
int m, s, f;
char *trtype;
SDL_CDStatus(cdrom);
printf("Drive tracks: %d\n", cdrom->numtracks);
for (i = 0; i < cdrom->numtracks; ++i) {
FRAMES_TO_MSF(cdrom->track[i].length, &m, &s, &f);
if (f > 0)
++s;
switch (cdrom->track[i].type) {
case SDL_AUDIO_TRACK:
trtype = "audio";
break;
case SDL_DATA_TRACK:
trtype = "data";
break;
default:
trtype = "unknown";
break;
}
printf("\tTrack (index %d) %d: %d:%2.2d / %d [%s track]\n", i,
cdrom->track[i].id, m, s, cdrom->track[i].length, trtype);
}
}
static void
PrintUsage(char *argv0)
{
fprintf(stderr, "Usage: %s [drive#] [command] [command] ...\n", argv0);
fprintf(stderr, "Where 'command' is one of:\n");
fprintf(stderr, " -status\n");
fprintf(stderr, " -list\n");
fprintf(stderr,
" -play [first_track] [first_frame] [num_tracks] [num_frames]\n");
fprintf(stderr, " -pause\n");
fprintf(stderr, " -resume\n");
fprintf(stderr, " -stop\n");
fprintf(stderr, " -eject\n");
fprintf(stderr, " -sleep <milliseconds>\n");
}
int
main(int argc, char *argv[])
{
int drive;
int i;
SDL_CD *cdrom;
/* Initialize SDL first */
if (SDL_Init(SDL_INIT_CDROM) < 0) {
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
return (1);
}
/* Find out how many CD-ROM drives are connected to the system */
if (SDL_CDNumDrives() == 0) {
printf("No CD-ROM devices detected\n");
quit(0);
}
printf("Drives available: %d\n", SDL_CDNumDrives());
for (i = 0; i < SDL_CDNumDrives(); ++i) {
printf("Drive %d: \"%s\"\n", i, SDL_CDName(i));
}
/* Open the CD-ROM */
drive = 0;
i = 1;
if (argv[i] && isdigit(argv[i][0])) {
drive = atoi(argv[i++]);
}
cdrom = SDL_CDOpen(drive);
if (cdrom == NULL) {
fprintf(stderr, "Couldn't open drive %d: %s\n", drive,
SDL_GetError());
quit(2);
}
#ifdef TEST_NULLCD
cdrom = NULL;
#endif
/* Find out which function to perform */
for (; argv[i]; ++i) {
if (strcmp(argv[i], "-status") == 0) {
/* PrintStatus(drive, cdrom); */
} else if (strcmp(argv[i], "-list") == 0) {
ListTracks(cdrom);
} else if (strcmp(argv[i], "-play") == 0) {
int strack, sframe;
int ntrack, nframe;
strack = 0;
if (argv[i + 1] && isdigit(argv[i + 1][0])) {
strack = atoi(argv[++i]);
}
sframe = 0;
if (argv[i + 1] && isdigit(argv[i + 1][0])) {
sframe = atoi(argv[++i]);
}
ntrack = 0;
if (argv[i + 1] && isdigit(argv[i + 1][0])) {
ntrack = atoi(argv[++i]);
}
nframe = 0;
if (argv[i + 1] && isdigit(argv[i + 1][0])) {
nframe = atoi(argv[++i]);
}
if (CD_INDRIVE(SDL_CDStatus(cdrom))) {
if (SDL_CDPlayTracks(cdrom, strack, sframe,
ntrack, nframe) < 0) {
fprintf(stderr,
"Couldn't play tracks %d/%d for %d/%d: %s\n",
strack, sframe, ntrack, nframe, SDL_GetError());
}
} else {
fprintf(stderr, "No CD in drive!\n");
}
} else if (strcmp(argv[i], "-pause") == 0) {
if (SDL_CDPause(cdrom) < 0) {
fprintf(stderr, "Couldn't pause CD: %s\n", SDL_GetError());
}
} else if (strcmp(argv[i], "-resume") == 0) {
if (SDL_CDResume(cdrom) < 0) {
fprintf(stderr, "Couldn't resume CD: %s\n", SDL_GetError());
}
} else if (strcmp(argv[i], "-stop") == 0) {
if (SDL_CDStop(cdrom) < 0) {
fprintf(stderr, "Couldn't eject CD: %s\n", SDL_GetError());
}
} else if (strcmp(argv[i], "-eject") == 0) {
if (SDL_CDEject(cdrom) < 0) {
fprintf(stderr, "Couldn't eject CD: %s\n", SDL_GetError());
}
} else if ((strcmp(argv[i], "-sleep") == 0) &&
(argv[i + 1] && isdigit(argv[i + 1][0]))) {
SDL_Delay(atoi(argv[++i]));
printf("Delayed %d milliseconds\n", atoi(argv[i]));
} else {
PrintUsage(argv[0]);
SDL_CDClose(cdrom);
quit(1);
}
}
PrintStatus(drive, cdrom);
SDL_CDClose(cdrom);
SDL_Quit();
return (0);
}