src/cdrom/qnx/SDL_syscdrom.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. ERRNO_TRAYEMPTY
  2. CheckDrive
  3. AddDrive
  4. SDL_SYS_CDInit
  5. SDL_SYS_CDName
  6. SDL_SYS_CDOpen
  7. SDL_SYS_CDGetTOC
  8. SDL_SYS_CDStatus
  9. SDL_SYS_CDPlay
  10. SDL_SYS_CDPause
  11. SDL_SYS_CDResume
  12. SDL_SYS_CDStop
  13. SDL_SYS_CDEject
  14. SDL_SYS_CDClose
  15. SDL_SYS_CDQuit

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 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     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_syscdrom.c,v 1.1.2.2 2001/02/10 07:20:04 hercules Exp $";
  26 #endif
  27 
  28 /* Functions for system-level CD-ROM audio control */
  29 
  30 #include <sys/types.h>
  31 #include <stdlib.h>
  32 #include <sys/stat.h>
  33 #include <sys/ioctl.h>
  34 #include <fcntl.h>
  35 #include <stdio.h>
  36 #include <string.h>
  37 #include <errno.h>
  38 #include <unistd.h>
  39 #include <sys/cdrom.h>
  40 #include <sys/dcmd_cam.h>
  41 
  42 
  43 #include "SDL_error.h"
  44 #include "SDL_cdrom.h"
  45 #include "SDL_syscdrom.h"
  46 
  47 
  48 /* The maximum number of CD-ROM drives we'll detect */
  49 #define MAX_DRIVES      16      
  50 
  51 /* A list of available CD-ROM drives */
  52 static char *SDL_cdlist[MAX_DRIVES];
  53 static dev_t SDL_cdmode[MAX_DRIVES];
  54 
  55 /* The system-dependent CD control functions */
  56 static const char *SDL_SYS_CDName(int drive);
  57 static int SDL_SYS_CDOpen(int drive);
  58 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
  59 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
  60 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
  61 static int SDL_SYS_CDPause(SDL_CD *cdrom);
  62 static int SDL_SYS_CDResume(SDL_CD *cdrom);
  63 static int SDL_SYS_CDStop(SDL_CD *cdrom);
  64 static int SDL_SYS_CDEject(SDL_CD *cdrom);
  65 static void SDL_SYS_CDClose(SDL_CD *cdrom);
  66 
  67 /* Some ioctl() errno values which occur when the tray is empty */
  68 #define ERRNO_TRAYEMPTY(errno)  \
     /* [<][>][^][v][top][bottom][index][help] */
  69         ((errno == EIO) || (errno == ENOENT) || (errno == EINVAL))
  70 
  71 /* Check a drive to see if it is a CD-ROM */
  72 static int CheckDrive(char *drive, char *mnttype, struct stat *stbuf)
     /* [<][>][^][v][top][bottom][index][help] */
  73 {
  74         int is_cd, cdfd;
  75         cdrom_subch_data_t info;
  76 
  77         /* If it doesn't exist, return -1 */
  78         if ( stat(drive, stbuf) < 0 ) {
  79                 return(-1);
  80         }
  81 
  82         /* If it does exist, verify that it's an available CD-ROM */
  83         is_cd = 0;
  84         if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) {
  85                 cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
  86                 if ( cdfd >= 0 ) {
  87                         info.subch_command.data_format = CDROM_MSF;
  88                         /* Under Linux, EIO occurs when a disk is not present.
  89                          */
  90                         if ((devctl(cdfd,DCMD_CAM_CDROMSUBCHNL,&info,sizeof(info),0) == 0) ||
  91                                                 ERRNO_TRAYEMPTY(errno) )
  92                         {
  93                                 is_cd = 1;
  94                         }
  95                         close(cdfd);
  96                 }
  97         }
  98         return(is_cd);
  99 }
 100 
 101 /* Add a CD-ROM drive to our list of valid drives */
 102 static void AddDrive(char *drive, struct stat *stbuf)
     /* [<][>][^][v][top][bottom][index][help] */
 103 {
 104         int i;
 105 
 106         if ( SDL_numcds < MAX_DRIVES ) {
 107                 /* Check to make sure it's not already in our list.
 108                    This can happen when we see a drive via symbolic link.
 109                  */
 110                 for ( i=0; i<SDL_numcds; ++i ) {
 111                         if ( stbuf->st_rdev == SDL_cdmode[i] ) {
 112 #ifdef DEBUG_CDROM
 113   fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
 114 #endif
 115                                 return;
 116                         }
 117                 }
 118 
 119                 /* Add this drive to our list */
 120                 i = SDL_numcds;
 121                 SDL_cdlist[i] = (char *)malloc(strlen(drive)+1);
 122                 if ( SDL_cdlist[i] == NULL ) {
 123                         SDL_OutOfMemory();
 124                         return;
 125                 }
 126                 strcpy(SDL_cdlist[i], drive);
 127                 SDL_cdmode[i] = stbuf->st_rdev;
 128                 ++SDL_numcds;
 129 #ifdef DEBUG_CDROM
 130   fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
 131 #endif
 132         }
 133 }
 134 
 135 int  SDL_SYS_CDInit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 136 {
 137         /* checklist: /dev/cdrom, /dev/hd?, /dev/scd? /dev/sr? */
 138         static char *checklist[] = {
 139                 "cdrom", "?0 cd?", "?1 cd?", "?a hd?", "?0 scd?", "?0 sr?", NULL
 140         };
 141         char *SDLcdrom;
 142         int i, j, exists;
 143         char drive[32];
 144         struct stat stbuf;
 145 
 146         /* Fill in our driver capabilities */
 147         SDL_CDcaps.Name = SDL_SYS_CDName;
 148         SDL_CDcaps.Open = SDL_SYS_CDOpen;
 149         SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
 150         SDL_CDcaps.Status = SDL_SYS_CDStatus;
 151         SDL_CDcaps.Play = SDL_SYS_CDPlay;
 152         SDL_CDcaps.Pause = SDL_SYS_CDPause;
 153         SDL_CDcaps.Resume = SDL_SYS_CDResume;
 154         SDL_CDcaps.Stop = SDL_SYS_CDStop;
 155         SDL_CDcaps.Eject = SDL_SYS_CDEject;
 156         SDL_CDcaps.Close = SDL_SYS_CDClose;
 157 
 158         /* Look in the environment for our CD-ROM drive list */
 159         SDLcdrom = getenv("SDL_CDROM"); /* ':' separated list of devices */
 160         if ( SDLcdrom != NULL ) {
 161                 char *cdpath, *delim;
 162                 cdpath = malloc(strlen(SDLcdrom)+1);
 163                 if ( cdpath != NULL ) {
 164                         strcpy(cdpath, SDLcdrom);
 165                         SDLcdrom = cdpath;
 166                         do {
 167                                 delim = strchr(SDLcdrom, ':');
 168                                 if ( delim ) {
 169                                         *delim++ = '\0';
 170                                 }
 171 #ifdef DEBUG_CDROM
 172   fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom);
 173 #endif
 174                                 if ( CheckDrive(SDLcdrom, NULL, &stbuf) > 0 ) {
 175                                         AddDrive(SDLcdrom, &stbuf);
 176                                 }
 177                                 if ( delim ) {
 178                                         SDLcdrom = delim;
 179                                 } else {
 180                                         SDLcdrom = NULL;
 181                                 }
 182                         } while ( SDLcdrom );
 183                         free(cdpath);
 184                 }
 185 
 186                 /* If we found our drives, there's nothing left to do */
 187                 if ( SDL_numcds > 0 ) {
 188                         return(0);
 189                 }
 190         }
 191 
 192         /* Scan the system for CD-ROM drives */
 193         for ( i=0; checklist[i]; ++i ) {
 194                 if ( checklist[i][0] == '?' ) {
 195                         char *insert;
 196                         exists = 1;
 197                         for ( j=checklist[i][1]; exists; ++j ) {
 198                                 sprintf(drive, "/dev/%s", &checklist[i][3]);
 199                                 insert = strchr(drive, '?');
 200                                 if ( insert != NULL ) {
 201                                         *insert = j;
 202                                 }
 203 #ifdef DEBUG_CDROM
 204   fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive);
 205 #endif
 206                                 switch (CheckDrive(drive, NULL, &stbuf)) {
 207                                         /* Drive exists and is a CD-ROM */
 208                                         case 1:
 209                                                 AddDrive(drive, &stbuf);
 210                                                 break;
 211                                         /* Drive exists, but isn't a CD-ROM */
 212                                         case 0:
 213                                                 break;
 214                                         /* Drive doesn't exist */
 215                                         case -1:
 216                                                 exists = 0;
 217                                                 break;
 218                                 }
 219                         }
 220                 } else {
 221                         sprintf(drive, "/dev/%s", checklist[i]);
 222 #ifdef DEBUG_CDROM
 223   fprintf(stderr, "Checking possible CD-ROM drive: %s\n", drive);
 224 #endif
 225                         if ( CheckDrive(drive, NULL, &stbuf) > 0 ) {
 226                                 AddDrive(drive, &stbuf);
 227                         }
 228                 }
 229         }
 230         return(0);
 231 }
 232 
 233 static const char *SDL_SYS_CDName(int drive)
     /* [<][>][^][v][top][bottom][index][help] */
 234 {
 235         return(SDL_cdlist[drive]);
 236 }
 237 
 238 static int SDL_SYS_CDOpen(int drive)
     /* [<][>][^][v][top][bottom][index][help] */
 239 {
 240         return(open(SDL_cdlist[drive], (O_RDONLY|O_EXCL|O_NONBLOCK), 0));
 241 }
 242 
 243 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 244 {
 245         cdrom_read_toc_t toc;
 246         int i, okay;
 247 
 248         okay = 0;
 249         if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), 0) == 0) {
 250                 cdrom->numtracks = toc.last_track - toc.first_track + 1;
 251                 if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
 252                         cdrom->numtracks = SDL_MAX_TRACKS;
 253                 }
 254                 /* Read all the track TOC entries */
 255                 for ( i=0; i<=cdrom->numtracks; ++i ) {
 256                         if ( i == cdrom->numtracks ) {
 257                                 cdrom->track[i].id = CDROM_LEADOUT;
 258                         } else {
 259 #if 0 /* Sam 11/6/00 - an obsolete field? */
 260                                 cdrom->track[i].id = toc.cdth_trk0+i;
 261 #else
 262                                 cdrom->track[i].id = toc.first_track+i;
 263 #endif
 264                         }
 265                         cdrom->track[i].type = toc.toc_entry[i].control_adr;
 266                         cdrom->track[i].offset = MSF_TO_FRAMES(
 267                                                 toc.toc_entry[i].addr.msf.minute,
 268                                                 toc.toc_entry[i].addr.msf.second,
 269                                                 toc.toc_entry[i].addr.msf.frame);                       
 270                         cdrom->track[i].length = 0;
 271                         if ( i > 0 ) {
 272                                 cdrom->track[i-1].length =
 273                                         cdrom->track[i].offset-
 274                                         cdrom->track[i-1].offset;
 275                         }
 276                 }
 277                 if ( i == (cdrom->numtracks+1) ) {
 278                         okay = 1;
 279                 }
 280         }
 281         return(okay ? 0 : -1);
 282 }
 283 
 284 /* Get CD-ROM status */
 285 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
     /* [<][>][^][v][top][bottom][index][help] */
 286 {
 287         CDstatus status;
 288         cdrom_read_toc_t toc;
 289         subch_current_position_t info;
 290 
 291 #if 0 /* Sam 11/6/00 - an obsolete field? */
 292         info.subch_command.data_format = CDROM_SUBCH_CURRENT_POSITION;
 293         info.subch_command.track_number = 0;
 294 #else
 295         info.data_format = CDROM_SUBCH_CURRENT_POSITION;
 296         info.track_number = 0;
 297 #endif
 298         if (devctl(cdrom->id, DCMD_CAM_CDROMSUBCHNL, &info, sizeof(info), 0) != 0) {
 299                 if ( ERRNO_TRAYEMPTY(errno) ) {
 300                         status = CD_TRAYEMPTY;
 301                 } else {
 302                         status = CD_ERROR;
 303                 }
 304         } else {
 305                 switch (info.header.audio_status) {
 306                         case CDROM_AUDIO_INVALID:
 307                         case CDROM_AUDIO_NO_STATUS:
 308                                 /* Try to determine if there's a CD available */
 309                                 if (devctl(cdrom->id, DCMD_CAM_CDROMREADTOC, &toc, sizeof(toc), 0)==0)
 310                                         status = CD_STOPPED;
 311                                 else
 312                                         status = CD_TRAYEMPTY;
 313                                 break;
 314                         case CDROM_AUDIO_COMPLETED:
 315                                 status = CD_STOPPED;
 316                                 break;
 317                         case CDROM_AUDIO_PLAY:
 318                                 status = CD_PLAYING;
 319                                 break;
 320                         case CDROM_AUDIO_PAUSED:
 321                                 /* Workaround buggy CD-ROM drive */
 322                                 if ( info.data_format == CDROM_LEADOUT ) {
 323                                         status = CD_STOPPED;
 324                                 } else {
 325                                         status = CD_PAUSED;
 326                                 }
 327                                 break;
 328                         default:
 329                                 status = CD_ERROR;
 330                                 break;
 331                 }
 332         }
 333         if ( position ) {
 334                 if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
 335                         *position = MSF_TO_FRAMES(
 336                                         info.addr.msf.minute,
 337                                         info.addr.msf.second,
 338                                         info.addr.msf.frame);
 339                 } else {
 340                         *position = 0;
 341                 }
 342         }
 343         return(status);
 344 }
 345 
 346 /* Start play */
 347 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
     /* [<][>][^][v][top][bottom][index][help] */
 348 {
 349         cdrom_playmsf_t playtime;
 350 
 351         FRAMES_TO_MSF(start,
 352            &playtime.start_minute, &playtime.start_second, &playtime.start_frame);
 353         FRAMES_TO_MSF(start+length,
 354            &playtime.end_minute, &playtime.end_second, &playtime.end_frame);
 355 #ifdef DEBUG_CDROM
 356   fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
 357         playtime.start_minute, playtime.start_second, playtime.start_frame,
 358         playtime.end_minute, playtime.end_second, playtime.end_frame);
 359 #endif
 360         return(devctl(cdrom->id, DCMD_CAM_CDROMPLAYMSF, &playtime, sizeof(playtime), 0));
 361 }
 362 
 363 /* Pause play */
 364 static int SDL_SYS_CDPause(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 365 {
 366         return(devctl(cdrom->id, DCMD_CAM_CDROMPAUSE, NULL, 0, 0));
 367 }
 368 
 369 /* Resume play */
 370 static int SDL_SYS_CDResume(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 371 {
 372         return(devctl(cdrom->id, DCMD_CAM_CDROMRESUME, NULL, 0, 0));
 373 }
 374 
 375 /* Stop play */
 376 static int SDL_SYS_CDStop(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 377 {
 378         return(devctl(cdrom->id, DCMD_CAM_CDROMSTOP, NULL, 0, 0));
 379 }
 380 
 381 /* Eject the CD-ROM */
 382 static int SDL_SYS_CDEject(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 383 {
 384         return(devctl(cdrom->id, DCMD_CAM_EJECT_MEDIA, NULL, 0, 0));
 385 }
 386 
 387 /* Close the CD-ROM handle */
 388 static void SDL_SYS_CDClose(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 389 {
 390         close(cdrom->id);
 391 }
 392 
 393 void SDL_SYS_CDQuit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 394 {
 395         int i;
 396 
 397         if ( SDL_numcds > 0 ) {
 398                 for ( i=0; i<SDL_numcds; ++i ) {
 399                         free(SDL_cdlist[i]);
 400                 }
 401                 SDL_numcds = 0;
 402         }
 403 }
 404 

/* [<][>][^][v][top][bottom][index][help] */