SDL_syscdrom.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:18k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

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