symbian-qemu-0.9.1-12/libsdl-trunk/src/cdrom/aix/SDL_syscdrom.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     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     Carsten Griwodz
       
    20     griff@kom.tu-darmstadt.de
       
    21 
       
    22     based on linux/SDL_syscdrom.c by Sam Lantinga
       
    23 */
       
    24 #include "SDL_config.h"
       
    25 
       
    26 #ifdef SDL_CDROM_AIX
       
    27 
       
    28 /* Functions for system-level CD-ROM audio control */
       
    29 
       
    30 /*#define DEBUG_CDROM 1*/
       
    31 
       
    32 #include <sys/types.h>
       
    33 #include <sys/stat.h>
       
    34 #include <fcntl.h>
       
    35 #include <errno.h>
       
    36 #include <unistd.h>
       
    37 
       
    38 #include <sys/ioctl.h>
       
    39 #include <sys/devinfo.h>
       
    40 #include <sys/mntctl.h>
       
    41 #include <sys/statfs.h>
       
    42 #include <sys/vmount.h>
       
    43 #include <fstab.h>
       
    44 #include <sys/scdisk.h>
       
    45 
       
    46 #include "SDL_cdrom.h"
       
    47 #include "../SDL_syscdrom.h"
       
    48 
       
    49 /* The maximum number of CD-ROM drives we'll detect */
       
    50 #define MAX_DRIVES	16	
       
    51 
       
    52 /* A list of available CD-ROM drives */
       
    53 static char *SDL_cdlist[MAX_DRIVES];
       
    54 static dev_t SDL_cdmode[MAX_DRIVES];
       
    55 
       
    56 /* The system-dependent CD control functions */
       
    57 static const char *SDL_SYS_CDName(int drive);
       
    58 static int         SDL_SYS_CDOpen(int drive);
       
    59 static int         SDL_SYS_CDGetTOC(SDL_CD *cdrom);
       
    60 static CDstatus    SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
       
    61 static int         SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
       
    62 static int         SDL_SYS_CDPause(SDL_CD *cdrom);
       
    63 static int         SDL_SYS_CDResume(SDL_CD *cdrom);
       
    64 static int         SDL_SYS_CDStop(SDL_CD *cdrom);
       
    65 static int         SDL_SYS_CDEject(SDL_CD *cdrom);
       
    66 static void        SDL_SYS_CDClose(SDL_CD *cdrom);
       
    67 static int         SDL_SYS_CDioctl(int id, int command, void *arg);
       
    68 
       
    69 /* Check a drive to see if it is a CD-ROM */
       
    70 static int CheckDrive(char *drive, struct stat *stbuf)
       
    71 {
       
    72     int is_cd;
       
    73     int cdfd;
       
    74     int ret;
       
    75     struct devinfo 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             ret = SDL_SYS_CDioctl( cdfd, IOCINFO, &info );
       
    88 	    if ( ret < 0 ) {
       
    89 		/* Some kind of error */
       
    90 		is_cd = 0;
       
    91 	    } else {
       
    92 		if ( info.devtype == DD_CDROM ) {
       
    93 		    is_cd = 1;
       
    94 		} else {
       
    95 		    is_cd = 0;
       
    96 		}
       
    97 	    }
       
    98             close(cdfd);
       
    99 	}
       
   100 #ifdef DEBUG_CDROM
       
   101 	else
       
   102 	{
       
   103             fprintf(stderr, "Could not open drive %s (%s)\n", drive, strerror(errno));
       
   104 	}
       
   105 #endif
       
   106     }
       
   107     return is_cd;
       
   108 }
       
   109 
       
   110 /* Add a CD-ROM drive to our list of valid drives */
       
   111 static void AddDrive(char *drive, struct stat *stbuf)
       
   112 {
       
   113 	int i;
       
   114 
       
   115 	if ( SDL_numcds < MAX_DRIVES ) {
       
   116 		/* Check to make sure it's not already in our list.
       
   117 	 	   This can happen when we see a drive via symbolic link.
       
   118 		 */
       
   119 		for ( i=0; i<SDL_numcds; ++i ) {
       
   120 			if ( stbuf->st_rdev == SDL_cdmode[i] ) {
       
   121 #ifdef DEBUG_CDROM
       
   122   fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
       
   123 #endif
       
   124 				return;
       
   125 			}
       
   126 		}
       
   127 
       
   128 		/* Add this drive to our list */
       
   129 		i = SDL_numcds;
       
   130 		SDL_cdlist[i] = SDL_strdup(drive);
       
   131 		if ( SDL_cdlist[i] == NULL ) {
       
   132 			SDL_OutOfMemory();
       
   133 			return;
       
   134 		}
       
   135 		SDL_cdmode[i] = stbuf->st_rdev;
       
   136 		++SDL_numcds;
       
   137 #ifdef DEBUG_CDROM
       
   138   fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
       
   139 #endif
       
   140 	}
       
   141 }
       
   142 
       
   143 static void CheckMounts()
       
   144 {
       
   145     char*          buffer;
       
   146     int            bufsz;
       
   147     struct vmount* ptr;
       
   148     int            ret;
       
   149 
       
   150     buffer = (char*)SDL_malloc(10);
       
   151     bufsz  = 10;
       
   152     if ( buffer==NULL )
       
   153     {
       
   154         fprintf(stderr, "Could not allocate 10 bytes in aix/SDL_syscdrom.c:CheckMounts\n" );
       
   155 	exit ( -10 );
       
   156     }
       
   157 
       
   158     do
       
   159     {
       
   160 	/* mntctrl() returns an array of all mounted filesystems */
       
   161         ret = mntctl ( MCTL_QUERY, bufsz, buffer );
       
   162         if ( ret == 0 )
       
   163         {
       
   164 				   /* Buffer was too small, realloc.    */
       
   165             bufsz = *(int*)buffer; /* Required size is in first word.   */
       
   166 				   /* (whatever a word is in AIX 4.3.3) */
       
   167 				   /* int seems to be OK in 32bit mode. */
       
   168             SDL_free(buffer);
       
   169             buffer = (char*)SDL_malloc(bufsz);
       
   170             if ( buffer==NULL )
       
   171             {
       
   172                 fprintf(stderr,
       
   173 			"Could not allocate %d bytes in aix/SDL_syscdrom.c:CheckMounts\n",
       
   174 			bufsz );
       
   175 	        exit ( -10 );
       
   176             }
       
   177         }
       
   178 	else if ( ret < 0 )
       
   179 	{
       
   180 #ifdef DEBUG_CDROM
       
   181             fprintf(stderr, "Error reading vmount structures\n");
       
   182 #endif
       
   183 	    return;
       
   184 	}
       
   185     }
       
   186     while ( ret == 0 );
       
   187 
       
   188 #ifdef DEBUG_CDROM
       
   189     fprintf ( stderr, "Read %d vmount structures\n",ret );
       
   190 #endif
       
   191     ptr = (struct vmount*)buffer;
       
   192     do
       
   193     {
       
   194             switch(ptr->vmt_gfstype)
       
   195             {
       
   196             case MNT_CDROM :
       
   197                 {
       
   198 		    struct stat stbuf;
       
   199 		    char*       text;
       
   200 
       
   201 		    text = (char*)ptr + ptr->vmt_data[VMT_OBJECT].vmt_off;
       
   202 #ifdef DEBUG_CDROM
       
   203   fprintf(stderr, "Checking mount path: %s mounted on %s\n",
       
   204 	text, (char*)ptr + ptr->vmt_data[VMT_STUB].vmt_off );
       
   205 #endif
       
   206 		    if ( CheckDrive( text, &stbuf) > 0)
       
   207 		    {
       
   208 		        AddDrive( text, &stbuf);
       
   209 		    }
       
   210                 }
       
   211                 break;
       
   212             default :
       
   213                 break;
       
   214             }
       
   215             ptr = (struct vmount*)((char*)ptr + ptr->vmt_length);
       
   216             ret--;
       
   217     }
       
   218     while ( ret > 0 );
       
   219 
       
   220     free ( buffer );
       
   221 }
       
   222 
       
   223 static int CheckNonmounts()
       
   224 {
       
   225 #ifdef _THREAD_SAFE
       
   226     AFILE_t      fsFile = NULL;
       
   227     int          passNo = 0;
       
   228     int          ret;
       
   229     struct fstab entry;
       
   230     struct stat  stbuf;
       
   231 
       
   232     ret = setfsent_r( &fsFile, &passNo );
       
   233     if ( ret != 0 ) return -1;
       
   234     do
       
   235     {
       
   236         ret = getfsent_r ( &entry, &fsFile, &passNo );
       
   237         if ( ret == 0 ) {
       
   238             char* l = SDL_strrchr(entry.fs_spec,'/');
       
   239             if ( l != NULL ) {
       
   240                 if ( !SDL_strncmp("cd",++l,2) ) {
       
   241 #ifdef DEBUG_CDROM
       
   242                     fprintf(stderr,
       
   243 			    "Found unmounted CD ROM drive with device name %s\n",
       
   244 			    entry.fs_spec);
       
   245 #endif
       
   246 		    if ( CheckDrive( entry.fs_spec, &stbuf) > 0)
       
   247 		    {
       
   248 		        AddDrive( entry.fs_spec, &stbuf);
       
   249 		    }
       
   250                 }
       
   251             }
       
   252         }
       
   253     }
       
   254     while ( ret == 0 );
       
   255     ret = endfsent_r ( &fsFile );
       
   256     if ( ret != 0 ) return -1;
       
   257     return 0;
       
   258 #else
       
   259     struct fstab* entry;
       
   260     struct stat  stbuf;
       
   261 
       
   262     setfsent();
       
   263     do
       
   264     {
       
   265         entry = getfsent();
       
   266         if ( entry != NULL ) {
       
   267             char* l = SDL_strrchr(entry->fs_spec,'/');
       
   268             if ( l != NULL ) {
       
   269                 if ( !SDL_strncmp("cd",++l,2) ) {
       
   270 #ifdef DEBUG_CDROM
       
   271                     fprintf(stderr,"Found unmounted CD ROM drive with device name %s", entry->fs_spec);
       
   272 #endif
       
   273 		    if ( CheckDrive( entry->fs_spec, &stbuf) > 0)
       
   274 		    {
       
   275 		        AddDrive( entry->fs_spec, &stbuf);
       
   276 		    }
       
   277                 }
       
   278             }
       
   279         }
       
   280     }
       
   281     while ( entry != NULL );
       
   282     endfsent();
       
   283 #endif
       
   284 }
       
   285 
       
   286 int  SDL_SYS_CDInit(void)
       
   287 {
       
   288 	char *SDLcdrom;
       
   289 	struct stat stbuf;
       
   290 
       
   291 	/* Fill in our driver capabilities */
       
   292 	SDL_CDcaps.Name = SDL_SYS_CDName;
       
   293 	SDL_CDcaps.Open = SDL_SYS_CDOpen;
       
   294 	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
       
   295 	SDL_CDcaps.Status = SDL_SYS_CDStatus;
       
   296 	SDL_CDcaps.Play = SDL_SYS_CDPlay;
       
   297 	SDL_CDcaps.Pause = SDL_SYS_CDPause;
       
   298 	SDL_CDcaps.Resume = SDL_SYS_CDResume;
       
   299 	SDL_CDcaps.Stop = SDL_SYS_CDStop;
       
   300 	SDL_CDcaps.Eject = SDL_SYS_CDEject;
       
   301 	SDL_CDcaps.Close = SDL_SYS_CDClose;
       
   302 
       
   303 	/* Look in the environment for our CD-ROM drive list */
       
   304 	SDLcdrom = SDL_getenv("SDL_CDROM");	/* ':' separated list of devices */
       
   305 	if ( SDLcdrom != NULL ) {
       
   306 		char *cdpath, *delim;
       
   307 		size_t len = SDL_strlen(SDLcdrom)+1;
       
   308 		cdpath = SDL_stack_alloc(char, len);
       
   309 		if ( cdpath != NULL ) {
       
   310 			SDL_strlcpy(cdpath, SDLcdrom, len);
       
   311 			SDLcdrom = cdpath;
       
   312 			do {
       
   313 				delim = SDL_strchr(SDLcdrom, ':');
       
   314 				if ( delim ) {
       
   315 					*delim++ = '\0';
       
   316 				}
       
   317 #ifdef DEBUG_CDROM
       
   318   fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom);
       
   319 #endif
       
   320 				if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
       
   321 					AddDrive(SDLcdrom, &stbuf);
       
   322 				}
       
   323 				if ( delim ) {
       
   324 					SDLcdrom = delim;
       
   325 				} else {
       
   326 					SDLcdrom = NULL;
       
   327 				}
       
   328 			} while ( SDLcdrom );
       
   329 			SDL_stack_free(cdpath);
       
   330 		}
       
   331 
       
   332 		/* If we found our drives, there's nothing left to do */
       
   333 		if ( SDL_numcds > 0 ) {
       
   334 			return(0);
       
   335 		}
       
   336 	}
       
   337 
       
   338 	CheckMounts();
       
   339 	CheckNonmounts();
       
   340 
       
   341 	return 0;
       
   342 }
       
   343 
       
   344 /* General ioctl() CD-ROM command function */
       
   345 static int SDL_SYS_CDioctl(int id, int command, void *arg)
       
   346 {
       
   347     int retval;
       
   348 
       
   349     retval = ioctl(id, command, arg);
       
   350     if ( retval < 0 ) {
       
   351         SDL_SetError("ioctl() error: %s", strerror(errno));
       
   352     }
       
   353     return retval;
       
   354 }
       
   355 
       
   356 static const char *SDL_SYS_CDName(int drive)
       
   357 {
       
   358 	return(SDL_cdlist[drive]);
       
   359 }
       
   360 
       
   361 static int SDL_SYS_CDOpen(int drive)
       
   362 {
       
   363     int   fd;
       
   364     char* lastsl;
       
   365     char* cdromname;
       
   366     size_t len;
       
   367 
       
   368     /*
       
   369      * We found /dev/cd? drives and that is in our list. But we can
       
   370      * open only the /dev/rcd? versions of those devices for Audio CD.
       
   371      */
       
   372     len = SDL_strlen(SDL_cdlist[drive])+2;
       
   373     cdromname = (char*)SDL_malloc(len);
       
   374     SDL_strlcpy(cdromname,SDL_cdlist[drive],len);
       
   375     lastsl = SDL_strrchr(cdromname,'/');
       
   376     if (lastsl) {
       
   377 	*lastsl = 0;
       
   378 	SDL_strlcat(cdromname,"/r",len);
       
   379 	lastsl = SDL_strrchr(SDL_cdlist[drive],'/');
       
   380 	if (lastsl) {
       
   381 	    lastsl++;
       
   382 	    SDL_strlcat(cdromname,lastsl,len);
       
   383 	}
       
   384     }
       
   385 
       
   386 #ifdef DEBUG_CDROM
       
   387     fprintf(stderr, "Should open drive %s, opening %s\n", SDL_cdlist[drive], cdromname);
       
   388 #endif
       
   389 
       
   390     /*
       
   391      * Use exclusive access. Don't use SC_DIAGNOSTICS as xmcd does because they
       
   392      * require root priviledges, and we don't want that. SC_SINGLE provides
       
   393      * exclusive access with less trouble.
       
   394      */
       
   395     fd = openx(cdromname, O_RDONLY, NULL, SC_SINGLE);
       
   396     if ( fd < 0 )
       
   397     {
       
   398 #ifdef DEBUG_CDROM
       
   399             fprintf(stderr, "Could not open drive %s (%s)\n", cdromname, strerror(errno));
       
   400 #endif
       
   401     }
       
   402     else
       
   403     {
       
   404 	struct mode_form_op cdMode;
       
   405 	int                 ret;
       
   406 #ifdef DEBUG_CDROM
       
   407 	cdMode.action = CD_GET_MODE;
       
   408 	ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode);
       
   409 	if ( ret < 0 ) {
       
   410             fprintf(stderr,
       
   411 	            "Could not get drive mode for %s (%s)\n",
       
   412 		    cdromname, strerror(errno));
       
   413 	} else {
       
   414 	    switch(cdMode.cd_mode_form) {
       
   415 		case CD_MODE1 :
       
   416                     fprintf(stderr,
       
   417 	                "Drive mode for %s is %s\n",
       
   418 		        cdromname, "CD-ROM Data Mode 1");
       
   419 		    break;
       
   420 		case CD_MODE2_FORM1 :
       
   421                     fprintf(stderr,
       
   422 	                "Drive mode for %s is %s\n",
       
   423 		        cdromname, "CD-ROM XA Data Mode 2 Form 1");
       
   424 		    break;
       
   425 		case CD_MODE2_FORM2 :
       
   426                     fprintf(stderr,
       
   427 	                "Drive mode for %s is %s\n",
       
   428 		        cdromname, "CD-ROM XA Data Mode 2 Form 2");
       
   429 		    break;
       
   430 		case CD_DA :
       
   431                     fprintf(stderr,
       
   432 	                "Drive mode for %s is %s\n",
       
   433 		        cdromname, "CD-DA");
       
   434 		    break;
       
   435 		default :
       
   436                     fprintf(stderr,
       
   437 	                "Drive mode for %s is %s\n",
       
   438 		        cdromname, "unknown");
       
   439 		    break;
       
   440 	    }
       
   441 	}
       
   442 #endif
       
   443 
       
   444 	cdMode.action       = CD_CHG_MODE;
       
   445 	cdMode.cd_mode_form = CD_DA;
       
   446 	ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode);
       
   447 	if ( ret < 0 ) {
       
   448 #ifdef DEBUG_CDROM
       
   449             fprintf(stderr,
       
   450 	            "Could not set drive mode for %s (%s)\n",
       
   451 		    cdromname, strerror(errno));
       
   452 #endif
       
   453             SDL_SetError("ioctl() error: Could not set CD drive mode, %s",
       
   454 	                 strerror(errno));
       
   455 	} else {
       
   456 #ifdef DEBUG_CDROM
       
   457             fprintf(stderr,
       
   458 	            "Drive mode for %s set to CD_DA\n",
       
   459 		    cdromname);
       
   460 #endif
       
   461 	}
       
   462     }
       
   463     SDL_free(cdromname);
       
   464     return fd;
       
   465 }
       
   466 
       
   467 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
       
   468 {
       
   469     struct cd_audio_cmd cmd;
       
   470     struct cd_audio_cmd entry;
       
   471     int                 i;
       
   472     int                 okay;
       
   473 
       
   474     cmd.audio_cmds = CD_TRK_INFO_AUDIO;
       
   475     cmd.msf_flag   = FALSE;
       
   476     if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) {
       
   477 	return -1;
       
   478     }
       
   479 
       
   480     okay = 0;
       
   481     cdrom->numtracks = cmd.indexing.track_index.last_track
       
   482 		     - cmd.indexing.track_index.first_track+1;
       
   483     if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
       
   484         cdrom->numtracks = SDL_MAX_TRACKS;
       
   485     }
       
   486 
       
   487     /* Read all the track TOC entries */
       
   488     for ( i=0; i<=cdrom->numtracks; ++i ) {
       
   489         if ( i == cdrom->numtracks ) {
       
   490             cdrom->track[i].id = 0xAA;;
       
   491         } else {
       
   492             cdrom->track[i].id = cmd.indexing.track_index.first_track+i;
       
   493         }
       
   494         entry.audio_cmds         = CD_GET_TRK_MSF;
       
   495 	entry.indexing.track_msf.track = cdrom->track[i].id;
       
   496 	if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &entry) < 0 ) {
       
   497             break;
       
   498         } else {
       
   499             cdrom->track[i].type = 0;    /* don't know how to detect 0x04 data track */
       
   500             cdrom->track[i].offset = MSF_TO_FRAMES(
       
   501                 entry.indexing.track_msf.mins,
       
   502                 entry.indexing.track_msf.secs,
       
   503                 entry.indexing.track_msf.frames);
       
   504             cdrom->track[i].length = 0;
       
   505             if ( i > 0 ) {
       
   506                 cdrom->track[i-1].length = cdrom->track[i].offset
       
   507 		                         - cdrom->track[i-1].offset;
       
   508             }
       
   509         }
       
   510     }
       
   511     if ( i == (cdrom->numtracks+1) ) {
       
   512         okay = 1;
       
   513     }
       
   514     return(okay ? 0 : -1);
       
   515 }
       
   516 
       
   517 /* Get CD-ROM status */
       
   518 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
       
   519 {
       
   520     CDstatus            status;
       
   521     struct cd_audio_cmd cmd;
       
   522     cmd.audio_cmds = CD_INFO_AUDIO;
       
   523 
       
   524     if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) {
       
   525 #ifdef DEBUG_CDROM
       
   526     fprintf(stderr, "ioctl failed in SDL_SYS_CDStatus (%s)\n", SDL_GetError());
       
   527 #endif
       
   528         status = CD_ERROR;
       
   529     } else {
       
   530         switch (cmd.status) {
       
   531             case CD_NO_AUDIO:
       
   532             case CD_COMPLETED:
       
   533                 status = CD_STOPPED;
       
   534                 break;
       
   535             case CD_PLAY_AUDIO:
       
   536                 status = CD_PLAYING;
       
   537                 break;
       
   538             case CD_PAUSE_AUDIO:
       
   539                 status = CD_PAUSED;
       
   540                 break;
       
   541             case CD_NOT_VALID:
       
   542 #ifdef DEBUG_CDROM
       
   543     fprintf(stderr, "cdStatus failed with CD_NOT_VALID\n");
       
   544 #endif
       
   545                 status = CD_ERROR;
       
   546                 break;
       
   547             case CD_STATUS_ERROR:
       
   548 #ifdef DEBUG_CDROM
       
   549     fprintf(stderr, "cdStatus failed with CD_STATUS_ERROR\n");
       
   550 #endif
       
   551                 status = CD_ERROR;
       
   552                 break;
       
   553             default:
       
   554 #ifdef DEBUG_CDROM
       
   555     fprintf(stderr, "cdStatus failed with unknown error\n");
       
   556 #endif
       
   557                 status = CD_ERROR;
       
   558                 break;
       
   559         }
       
   560     }
       
   561     if ( position ) {
       
   562         if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
       
   563             *position = MSF_TO_FRAMES( cmd.indexing.info_audio.current_mins,
       
   564                                        cmd.indexing.info_audio.current_secs,
       
   565                                        cmd.indexing.info_audio.current_frames);
       
   566         } else {
       
   567             *position = 0;
       
   568         }
       
   569     }
       
   570     return status;
       
   571 }
       
   572 
       
   573 /* Start play */
       
   574 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
       
   575 {
       
   576     struct cd_audio_cmd cmd;
       
   577 
       
   578     /*
       
   579      * My CD Rom is muted by default. I think I read that this is new with
       
   580      * AIX 4.3. SDL does not change the volume, so I need a kludge. Maybe
       
   581      * its better to do this elsewhere?
       
   582      */
       
   583     cmd.audio_cmds = CD_PLAY_AUDIO | CD_SET_VOLUME;
       
   584     cmd.msf_flag   = TRUE;
       
   585     FRAMES_TO_MSF(start,
       
   586                   &cmd.indexing.msf.first_mins,
       
   587                   &cmd.indexing.msf.first_secs,
       
   588                   &cmd.indexing.msf.first_frames);
       
   589     FRAMES_TO_MSF(start+length,
       
   590                   &cmd.indexing.msf.last_mins,
       
   591                   &cmd.indexing.msf.last_secs,
       
   592                   &cmd.indexing.msf.last_frames);
       
   593     cmd.volume_type     = CD_VOLUME_ALL;
       
   594     cmd.all_channel_vol = 255;   /* This is a uchar. What is a good value? No docu! */
       
   595     cmd.out_port_0_sel  = CD_AUDIO_CHNL_0;
       
   596     cmd.out_port_1_sel  = CD_AUDIO_CHNL_1;
       
   597     cmd.out_port_2_sel  = CD_AUDIO_CHNL_2;
       
   598     cmd.out_port_3_sel  = CD_AUDIO_CHNL_3;
       
   599 
       
   600 #ifdef DEBUG_CDROM
       
   601   fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
       
   602 	cmd.indexing.msf.first_mins,
       
   603 	cmd.indexing.msf.first_secs,
       
   604 	cmd.indexing.msf.first_frames,
       
   605 	cmd.indexing.msf.last_mins,
       
   606 	cmd.indexing.msf.last_secs,
       
   607 	cmd.indexing.msf.last_frames);
       
   608 #endif
       
   609 	return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
       
   610 }
       
   611 
       
   612 /* Pause play */
       
   613 static int SDL_SYS_CDPause(SDL_CD *cdrom)
       
   614 {
       
   615     struct cd_audio_cmd cmd;
       
   616     cmd.audio_cmds = CD_PAUSE_AUDIO;
       
   617     return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
       
   618 }
       
   619 
       
   620 /* Resume play */
       
   621 static int SDL_SYS_CDResume(SDL_CD *cdrom)
       
   622 {
       
   623     struct cd_audio_cmd cmd;
       
   624     cmd.audio_cmds = CD_RESUME_AUDIO;
       
   625     return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
       
   626 }
       
   627 
       
   628 /* Stop play */
       
   629 static int SDL_SYS_CDStop(SDL_CD *cdrom)
       
   630 {
       
   631     struct cd_audio_cmd cmd;
       
   632     cmd.audio_cmds = CD_STOP_AUDIO;
       
   633     return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
       
   634 }
       
   635 
       
   636 /* Eject the CD-ROM */
       
   637 static int SDL_SYS_CDEject(SDL_CD *cdrom)
       
   638 {
       
   639     return(SDL_SYS_CDioctl(cdrom->id, DKEJECT, 0));
       
   640 }
       
   641 
       
   642 /* Close the CD-ROM handle */
       
   643 static void SDL_SYS_CDClose(SDL_CD *cdrom)
       
   644 {
       
   645     close(cdrom->id);
       
   646 }
       
   647 
       
   648 void SDL_SYS_CDQuit(void)
       
   649 {
       
   650 	int i;
       
   651 
       
   652 	if ( SDL_numcds > 0 ) {
       
   653 		for ( i=0; i<SDL_numcds; ++i ) {
       
   654 			SDL_free(SDL_cdlist[i]);
       
   655 		}
       
   656 		SDL_numcds = 0;
       
   657 	}
       
   658 }
       
   659 
       
   660 #endif /* SDL_CDROM_AIX */