src/cdrom/SDL_cdrom.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 01 Feb 2006 06:32:25 +0000
changeset 1312 c9b51268668f
parent 769 b8d311d90021
child 1330 450721ad5436
permissions -rw-r--r--
Updated copyright information and removed rcs id lines (problematic in branch merges)
I batch edited these files, so please let me know if I've accidentally removed anybody's
credit here.
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997-2006 Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Lesser General Public
     7     License as published by the Free Software Foundation; either
     8     version 2.1 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Lesser General Public License for more details.
    14 
    15     You should have received a copy of the GNU Lesser General Public
    16     License along with this library; if not, write to the Free Software
    17     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 /* This is the CD-audio control API for Simple DirectMedia Layer */
    24 
    25 #include <stdio.h>
    26 #include <stdlib.h>
    27 #include <string.h>
    28 
    29 #include "SDL_error.h"
    30 #include "SDL_cdrom.h"
    31 #include "SDL_syscdrom.h"
    32 
    33 #if !defined(macintosh)
    34 #define CLIP_FRAMES	10	/* Some CD-ROMs won't go all the way */
    35 #endif
    36 
    37 static int SDL_cdinitted = 0;
    38 static SDL_CD *default_cdrom;
    39 
    40 /* The system level CD-ROM control functions */
    41 struct CDcaps SDL_CDcaps = {
    42 	NULL,					/* Name */
    43 	NULL,					/* Open */
    44 	NULL,					/* GetTOC */
    45 	NULL,					/* Status */
    46 	NULL,					/* Play */
    47 	NULL,					/* Pause */
    48 	NULL,					/* Resume */
    49 	NULL,					/* Stop */
    50 	NULL,					/* Eject */
    51 	NULL,					/* Close */
    52 };
    53 int SDL_numcds;
    54 
    55 int SDL_CDROMInit(void)
    56 {
    57 	int retval;
    58 
    59 	SDL_numcds = 0;
    60 	retval = SDL_SYS_CDInit();
    61 	if ( retval == 0 ) {
    62 		SDL_cdinitted = 1;
    63 	}
    64 	default_cdrom = NULL;
    65 	return(retval);
    66 }
    67 
    68 /* Check to see if the CD-ROM subsystem has been initialized */
    69 static int CheckInit(int check_cdrom, SDL_CD **cdrom)
    70 {
    71 	int okay;
    72 
    73 	okay = SDL_cdinitted;
    74 	if ( check_cdrom && (*cdrom == NULL) ) {
    75 		*cdrom = default_cdrom;
    76 		if ( *cdrom == NULL ) {
    77 			SDL_SetError("CD-ROM not opened");
    78 			okay = 0;
    79 		}
    80 	}
    81 	if ( ! SDL_cdinitted ) {
    82 		SDL_SetError("CD-ROM subsystem not initialized");
    83 	}
    84 	return(okay);
    85 }
    86 
    87 int SDL_CDNumDrives(void)
    88 {
    89 	if ( ! CheckInit(0, NULL) ) {
    90 		return(-1);
    91 	}
    92 	return(SDL_numcds);
    93 }
    94 
    95 const char *SDL_CDName(int drive)
    96 {
    97 	if ( ! CheckInit(0, NULL) ) {
    98 		return(NULL);
    99 	}
   100 	if ( drive >= SDL_numcds ) {
   101 		SDL_SetError("Invalid CD-ROM drive index");
   102 		return(NULL);
   103 	}
   104 	if ( SDL_CDcaps.Name ) {
   105 		return(SDL_CDcaps.Name(drive));
   106 	} else {
   107 		return("");
   108 	}
   109 }
   110 
   111 SDL_CD *SDL_CDOpen(int drive)
   112 {
   113 	struct SDL_CD *cdrom;
   114 
   115 	if ( ! CheckInit(0, NULL) ) {
   116 		return(NULL);
   117 	}
   118 	if ( drive >= SDL_numcds ) {
   119 		SDL_SetError("Invalid CD-ROM drive index");
   120 		return(NULL);
   121 	}
   122 	cdrom = (SDL_CD *)malloc(sizeof(*cdrom));
   123 	if ( cdrom == NULL ) {
   124 		SDL_OutOfMemory();
   125 		return(NULL);
   126 	}
   127 	memset(cdrom, 0, sizeof(*cdrom));
   128 	cdrom->id = SDL_CDcaps.Open(drive);
   129 	if ( cdrom->id < 0 ) {
   130 		free(cdrom);
   131 		return(NULL);
   132 	}
   133 	default_cdrom = cdrom;
   134 	return(cdrom);
   135 }
   136 
   137 CDstatus SDL_CDStatus(SDL_CD *cdrom)
   138 {
   139 	CDstatus status;
   140 	int i;
   141 	Uint32 position;
   142 
   143 	/* Check if the CD-ROM subsystem has been initialized */
   144 	if ( ! CheckInit(1, &cdrom) ) {
   145 		return(CD_ERROR);
   146 	}
   147 
   148 	/* Get the current status of the drive */
   149 	cdrom->numtracks = 0;
   150 	cdrom->cur_track = 0;
   151 	cdrom->cur_frame = 0;
   152 	status = SDL_CDcaps.Status(cdrom, &i);
   153 	position = (Uint32)i;
   154 	cdrom->status = status;
   155 
   156 	/* Get the table of contents, if there's a CD available */
   157 	if ( CD_INDRIVE(status) ) {
   158 		if ( SDL_CDcaps.GetTOC(cdrom) < 0 ) {
   159 			status = CD_ERROR;
   160 		}
   161 		/* If the drive is playing, get current play position */
   162 		if ( (status == CD_PLAYING) || (status == CD_PAUSED) ) {
   163 			for ( i=1; cdrom->track[i].offset <= position; ++i ) {
   164 				/* Keep looking */;
   165 			}
   166 #ifdef DEBUG_CDROM
   167   fprintf(stderr, "Current position: %d, track = %d (offset is %d)\n",
   168 				position, i-1, cdrom->track[i-1].offset);
   169 #endif
   170 			cdrom->cur_track = i-1;
   171 			position -= cdrom->track[cdrom->cur_track].offset;
   172 			cdrom->cur_frame = position;
   173 		}
   174 	}
   175 	return(status);
   176 }
   177 
   178 int SDL_CDPlayTracks(SDL_CD *cdrom,
   179 			int strack, int sframe, int ntracks, int nframes)
   180 {
   181 	int etrack, eframe;
   182 	int start, length;
   183 
   184 	/* Check if the CD-ROM subsystem has been initialized */
   185 	if ( ! CheckInit(1, &cdrom) ) {
   186 		return(CD_ERROR);
   187 	}
   188 
   189 	/* Determine the starting and ending tracks */
   190 	if ( (strack < 0) || (strack >= cdrom->numtracks) ) {
   191 		SDL_SetError("Invalid starting track");
   192 		return(CD_ERROR);
   193 	}
   194 	if ( ! ntracks && ! nframes ) {
   195 		etrack = cdrom->numtracks;
   196 		eframe = 0;
   197 	} else {
   198 		etrack = strack+ntracks;
   199 		if ( etrack == strack ) {
   200 			eframe = sframe + nframes;
   201 		} else {
   202 			eframe = nframes;
   203 		}
   204 	}
   205 	if ( etrack > cdrom->numtracks ) {
   206 		SDL_SetError("Invalid play length");
   207 		return(CD_ERROR);
   208 	}
   209 
   210 	/* Skip data tracks and verify frame offsets */
   211 	while ( (strack <= etrack) &&
   212 			(cdrom->track[strack].type == SDL_DATA_TRACK) ) {
   213 		++strack;
   214 	}
   215 	if ( sframe >= (int)cdrom->track[strack].length ) {
   216 		SDL_SetError("Invalid starting frame for track %d", strack);
   217 		return(CD_ERROR);
   218 	}
   219 	while ( (etrack > strack) &&
   220 			(cdrom->track[etrack-1].type == SDL_DATA_TRACK) ) {
   221 		--etrack;
   222 	}
   223 	if ( eframe > (int)cdrom->track[etrack].length ) {
   224 		SDL_SetError("Invalid ending frame for track %d", etrack);
   225 		return(CD_ERROR);
   226 	}
   227 
   228 	/* Determine start frame and play length */
   229 	start = (cdrom->track[strack].offset+sframe);
   230 	length = (cdrom->track[etrack].offset+eframe)-start;
   231 #ifdef CLIP_FRAMES
   232 	/* I've never seen this necessary, but xmcd does it.. */
   233 	length -= CLIP_FRAMES;	/* CLIP_FRAMES == 10 */
   234 #endif
   235 	if ( length < 0 ) {
   236 		return(0);
   237 	}
   238 
   239 	/* Play! */
   240 #ifdef DEBUG_CDROM
   241   fprintf(stderr, "Playing %d frames at offset %d\n", length, start);
   242 #endif
   243 	return(SDL_CDcaps.Play(cdrom, start, length));
   244 }
   245 
   246 int SDL_CDPlay(SDL_CD *cdrom, int sframe, int length)
   247 {
   248 	/* Check if the CD-ROM subsystem has been initialized */
   249 	if ( ! CheckInit(1, &cdrom) ) {
   250 		return(CD_ERROR);
   251 	}
   252 
   253 	return(SDL_CDcaps.Play(cdrom, sframe, length));
   254 }
   255 
   256 int SDL_CDPause(SDL_CD *cdrom)
   257 {
   258 	CDstatus status;
   259 	int retval;
   260 
   261 	/* Check if the CD-ROM subsystem has been initialized */
   262 	if ( ! CheckInit(1, &cdrom) ) {
   263 		return(CD_ERROR);
   264 	}
   265 
   266 	status = SDL_CDcaps.Status(cdrom, NULL);
   267 	switch (status) {
   268 		case CD_PLAYING:
   269 			retval = SDL_CDcaps.Pause(cdrom);
   270 			break;
   271 		default:
   272 			retval = 0;
   273 			break;
   274 	}
   275 	return(retval);
   276 }
   277 
   278 int SDL_CDResume(SDL_CD *cdrom)
   279 {
   280 	CDstatus status;
   281 	int retval;
   282 
   283 	/* Check if the CD-ROM subsystem has been initialized */
   284 	if ( ! CheckInit(1, &cdrom) ) {
   285 		return(CD_ERROR);
   286 	}
   287 
   288 	status = SDL_CDcaps.Status(cdrom, NULL);
   289 	switch (status) {
   290 		case CD_PAUSED:
   291 			retval = SDL_CDcaps.Resume(cdrom);
   292 		default:
   293 			retval = 0;
   294 			break;
   295 	}
   296 	return(retval);
   297 }
   298 
   299 int SDL_CDStop(SDL_CD *cdrom)
   300 {
   301 	CDstatus status;
   302 	int retval;
   303 
   304 	/* Check if the CD-ROM subsystem has been initialized */
   305 	if ( ! CheckInit(1, &cdrom) ) {
   306 		return(CD_ERROR);
   307 	}
   308 
   309 	status = SDL_CDcaps.Status(cdrom, NULL);
   310 	switch (status) {
   311 		case CD_PLAYING:
   312 		case CD_PAUSED:
   313 			retval = SDL_CDcaps.Stop(cdrom);
   314 		default:
   315 			retval = 0;
   316 			break;
   317 	}
   318 	return(retval);
   319 }
   320 
   321 int SDL_CDEject(SDL_CD *cdrom)
   322 {
   323 	/* Check if the CD-ROM subsystem has been initialized */
   324 	if ( ! CheckInit(1, &cdrom) ) {
   325 		return(CD_ERROR);
   326 	}
   327 	return(SDL_CDcaps.Eject(cdrom));
   328 }
   329 
   330 void SDL_CDClose(SDL_CD *cdrom)
   331 {
   332 	/* Check if the CD-ROM subsystem has been initialized */
   333 	if ( ! CheckInit(1, &cdrom) ) {
   334 		return;
   335 	}
   336 	SDL_CDcaps.Close(cdrom);
   337 	free(cdrom);
   338 	default_cdrom = NULL;
   339 }
   340 
   341 void SDL_CDROMQuit(void)
   342 {
   343 	SDL_SYS_CDQuit();
   344 	SDL_cdinitted = 0;
   345 }