src/cdrom/aix/SDL_syscdrom.c
author Ryan C. Gordon
Wed, 29 Nov 2006 10:30:05 +0000
branchSDL-1.2
changeset 3900 ce3a2bd11305
parent 1635 92947e3a18db
child 1662 782fd950bd46
child 1895 c121d94672cb
child 4159 a1b03ba2fcd0
permissions -rw-r--r--
Wrapped some macro params in parentheses for alloca wrappers.
Thansk, Suzuki Masahiro.
     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 */