src/cdrom/SDL_cdrom.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 29 Oct 2006 14:45:46 +0000
changeset 2063 dea73e1d07b0
parent 1978 542c78b6fb12
child 2698 e1da92da346c
permissions -rw-r--r--
Merged Ryan's fix, in case we need it later.
     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 #include "SDL_config.h"
    23 
    24 /* This is the CD-audio control API for Simple DirectMedia Layer */
    25 
    26 #include "SDL_cdrom.h"
    27 #include "SDL_syscdrom.h"
    28 
    29 #define CLIP_FRAMES	10      /* Some CD-ROMs won't go all the way */
    30 
    31 static int SDL_cdinitted = 0;
    32 static SDL_CD *default_cdrom;
    33 
    34 /* The system level CD-ROM control functions */
    35 struct CDcaps SDL_CDcaps = {
    36     NULL,                       /* Name */
    37     NULL,                       /* Open */
    38     NULL,                       /* GetTOC */
    39     NULL,                       /* Status */
    40     NULL,                       /* Play */
    41     NULL,                       /* Pause */
    42     NULL,                       /* Resume */
    43     NULL,                       /* Stop */
    44     NULL,                       /* Eject */
    45     NULL,                       /* Close */
    46 };
    47 int SDL_numcds;
    48 
    49 int
    50 SDL_CDROMInit(void)
    51 {
    52     int retval;
    53 
    54     SDL_numcds = 0;
    55     retval = SDL_SYS_CDInit();
    56     if (retval == 0) {
    57         SDL_cdinitted = 1;
    58     }
    59     default_cdrom = NULL;
    60     return (retval);
    61 }
    62 
    63 /* Check to see if the CD-ROM subsystem has been initialized */
    64 static int
    65 CheckInit(int check_cdrom, SDL_CD ** cdrom)
    66 {
    67     int okay;
    68 
    69     okay = SDL_cdinitted;
    70     if (check_cdrom && (*cdrom == NULL)) {
    71         *cdrom = default_cdrom;
    72         if (*cdrom == NULL) {
    73             SDL_SetError("CD-ROM not opened");
    74             okay = 0;
    75         }
    76     }
    77     if (!SDL_cdinitted) {
    78         SDL_SetError("CD-ROM subsystem not initialized");
    79     }
    80     return (okay);
    81 }
    82 
    83 int
    84 SDL_CDNumDrives(void)
    85 {
    86     if (!CheckInit(0, NULL)) {
    87         return (-1);
    88     }
    89     return (SDL_numcds);
    90 }
    91 
    92 const char *
    93 SDL_CDName(int drive)
    94 {
    95     if (!CheckInit(0, NULL)) {
    96         return (NULL);
    97     }
    98     if (drive >= SDL_numcds) {
    99         SDL_SetError("Invalid CD-ROM drive index");
   100         return (NULL);
   101     }
   102     if (SDL_CDcaps.Name) {
   103         return (SDL_CDcaps.Name(drive));
   104     } else {
   105         return ("");
   106     }
   107 }
   108 
   109 SDL_CD *
   110 SDL_CDOpen(int drive)
   111 {
   112     struct SDL_CD *cdrom;
   113 
   114     if (!CheckInit(0, NULL)) {
   115         return (NULL);
   116     }
   117     if (drive >= SDL_numcds) {
   118         SDL_SetError("Invalid CD-ROM drive index");
   119         return (NULL);
   120     }
   121     cdrom = (SDL_CD *) SDL_malloc(sizeof(*cdrom));
   122     if (cdrom == NULL) {
   123         SDL_OutOfMemory();
   124         return (NULL);
   125     }
   126     SDL_memset(cdrom, 0, sizeof(*cdrom));
   127     cdrom->id = SDL_CDcaps.Open(drive);
   128     if (cdrom->id < 0) {
   129         SDL_free(cdrom);
   130         return (NULL);
   131     }
   132     default_cdrom = cdrom;
   133     return (cdrom);
   134 }
   135 
   136 CDstatus
   137 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,
   168                     "Current position: %d, track = %d (offset is %d)\n",
   169                     position, i - 1, cdrom->track[i - 1].offset);
   170 #endif
   171             cdrom->cur_track = i - 1;
   172             position -= cdrom->track[cdrom->cur_track].offset;
   173             cdrom->cur_frame = position;
   174         }
   175     }
   176     return (status);
   177 }
   178 
   179 int
   180 SDL_CDPlayTracks(SDL_CD * cdrom,
   181                  int strack, int sframe, int ntracks, int nframes)
   182 {
   183     int etrack, eframe;
   184     int start, length;
   185 
   186     /* Check if the CD-ROM subsystem has been initialized */
   187     if (!CheckInit(1, &cdrom)) {
   188         return (CD_ERROR);
   189     }
   190 
   191     /* Determine the starting and ending tracks */
   192     if ((strack < 0) || (strack >= cdrom->numtracks)) {
   193         SDL_SetError("Invalid starting track");
   194         return (CD_ERROR);
   195     }
   196     if (!ntracks && !nframes) {
   197         etrack = cdrom->numtracks;
   198         eframe = 0;
   199     } else {
   200         etrack = strack + ntracks;
   201         if (etrack == strack) {
   202             eframe = sframe + nframes;
   203         } else {
   204             eframe = nframes;
   205         }
   206     }
   207     if (etrack > cdrom->numtracks) {
   208         SDL_SetError("Invalid play length");
   209         return (CD_ERROR);
   210     }
   211 
   212     /* Skip data tracks and verify frame offsets */
   213     while ((strack <= etrack) &&
   214            (cdrom->track[strack].type == SDL_DATA_TRACK)) {
   215         ++strack;
   216     }
   217     if (sframe >= (int) cdrom->track[strack].length) {
   218         SDL_SetError("Invalid starting frame for track %d", strack);
   219         return (CD_ERROR);
   220     }
   221     while ((etrack > strack) &&
   222            (cdrom->track[etrack - 1].type == SDL_DATA_TRACK)) {
   223         --etrack;
   224     }
   225     if (eframe > (int) cdrom->track[etrack].length) {
   226         SDL_SetError("Invalid ending frame for track %d", etrack);
   227         return (CD_ERROR);
   228     }
   229 
   230     /* Determine start frame and play length */
   231     start = (cdrom->track[strack].offset + sframe);
   232     length = (cdrom->track[etrack].offset + eframe) - start;
   233 #ifdef CLIP_FRAMES
   234     /* I've never seen this necessary, but xmcd does it.. */
   235     length -= CLIP_FRAMES;      /* CLIP_FRAMES == 10 */
   236 #endif
   237     if (length < 0) {
   238         return (0);
   239     }
   240 
   241     /* Play! */
   242 #ifdef DEBUG_CDROM
   243     fprintf(stderr, "Playing %d frames at offset %d\n", length, start);
   244 #endif
   245     return (SDL_CDcaps.Play(cdrom, start, length));
   246 }
   247 
   248 int
   249 SDL_CDPlay(SDL_CD * cdrom, int sframe, int length)
   250 {
   251     /* Check if the CD-ROM subsystem has been initialized */
   252     if (!CheckInit(1, &cdrom)) {
   253         return (CD_ERROR);
   254     }
   255 
   256     return (SDL_CDcaps.Play(cdrom, sframe, length));
   257 }
   258 
   259 int
   260 SDL_CDPause(SDL_CD * cdrom)
   261 {
   262     CDstatus status;
   263     int retval;
   264 
   265     /* Check if the CD-ROM subsystem has been initialized */
   266     if (!CheckInit(1, &cdrom)) {
   267         return (CD_ERROR);
   268     }
   269 
   270     status = SDL_CDcaps.Status(cdrom, NULL);
   271     switch (status) {
   272     case CD_PLAYING:
   273         retval = SDL_CDcaps.Pause(cdrom);
   274         break;
   275     default:
   276         retval = 0;
   277         break;
   278     }
   279     return (retval);
   280 }
   281 
   282 int
   283 SDL_CDResume(SDL_CD * cdrom)
   284 {
   285     CDstatus status;
   286     int retval;
   287 
   288     /* Check if the CD-ROM subsystem has been initialized */
   289     if (!CheckInit(1, &cdrom)) {
   290         return (CD_ERROR);
   291     }
   292 
   293     status = SDL_CDcaps.Status(cdrom, NULL);
   294     switch (status) {
   295     case CD_PAUSED:
   296         retval = SDL_CDcaps.Resume(cdrom);
   297     default:
   298         retval = 0;
   299         break;
   300     }
   301     return (retval);
   302 }
   303 
   304 int
   305 SDL_CDStop(SDL_CD * cdrom)
   306 {
   307     CDstatus status;
   308     int retval;
   309 
   310     /* Check if the CD-ROM subsystem has been initialized */
   311     if (!CheckInit(1, &cdrom)) {
   312         return (CD_ERROR);
   313     }
   314 
   315     status = SDL_CDcaps.Status(cdrom, NULL);
   316     switch (status) {
   317     case CD_PLAYING:
   318     case CD_PAUSED:
   319         retval = SDL_CDcaps.Stop(cdrom);
   320     default:
   321         retval = 0;
   322         break;
   323     }
   324     return (retval);
   325 }
   326 
   327 int
   328 SDL_CDEject(SDL_CD * cdrom)
   329 {
   330     /* Check if the CD-ROM subsystem has been initialized */
   331     if (!CheckInit(1, &cdrom)) {
   332         return (CD_ERROR);
   333     }
   334     return (SDL_CDcaps.Eject(cdrom));
   335 }
   336 
   337 void
   338 SDL_CDClose(SDL_CD * cdrom)
   339 {
   340     /* Check if the CD-ROM subsystem has been initialized */
   341     if (!CheckInit(1, &cdrom)) {
   342         return;
   343     }
   344     SDL_CDcaps.Close(cdrom);
   345     SDL_free(cdrom);
   346     default_cdrom = NULL;
   347 }
   348 
   349 void
   350 SDL_CDROMQuit(void)
   351 {
   352     SDL_SYS_CDQuit();
   353     SDL_cdinitted = 0;
   354 }
   355 
   356 /* vi: set ts=4 sw=4 expandtab: */