Example #1
0
/* Resume play */
static int SDL_SYS_CDResume(SDL_CD *cdrom)
{
#ifdef BROKEN_MCI_PAUSE
	MCI_STATUS_PARMS mci_status;
	int okay;
	int flags;

	okay = 0;
	/* Play from the current play position to the end position set earlier */
	flags = MCI_STATUS_ITEM | MCI_WAIT;
	mci_status.dwItem = MCI_STATUS_POSITION;
	if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) {
		MCI_PLAY_PARMS mci_play;

		flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
		mci_play.dwCallback = 0;
		mci_play.dwFrom = mci_status.dwReturn;
		mci_play.dwTo = SDL_CD_end_position;
		if (SDL_SYS_CDioctl(cdrom->id,MCI_PLAY,flags,&mci_play) == 0) {
			okay = 1;
			SDL_paused[cdrom->id] = 0;
		}
	}
	return(okay ? 0 : -1);
#else
	return(SDL_SYS_CDioctl(cdrom->id, MCI_RESUME, MCI_WAIT, NULL));
#endif /* BROKEN_MCI_PAUSE */
}
Example #2
0
static int SDL_SYS_CDOpen(int drive)
{
	MCI_OPEN_PARMS mci_open;
	MCI_SET_PARMS mci_set;
	char device[3];
	DWORD flags;

	/* Open the requested device */
	mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
	device[0] = *SDL_cdlist[drive];
	device[1] = ':';
	device[2] = '\0';
	mci_open.lpstrElementName = device;
	flags =
	  (MCI_OPEN_TYPE|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT);
	if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) {
		flags &= ~MCI_OPEN_SHAREABLE;
		if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) {
			return(-1);
		}
	}
	SDL_mciID[drive] = mci_open.wDeviceID;

	/* Set the minute-second-frame time format */
	mci_set.dwTimeFormat = MCI_FORMAT_MSF;
	SDL_SYS_CDioctl(drive, MCI_SET, MCI_SET_TIME_FORMAT, &mci_set);

#ifdef BROKEN_MCI_PAUSE
	SDL_paused[drive] = 0;
#endif
	return(drive);
}
Example #3
0
/* Get CD-ROM status */
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
{
	CDstatus status;
	struct cdrom_tochdr toc;
	struct cdrom_subchnl info;

	info.cdsc_format = CDROM_MSF;
	if ( SDL_SYS_CDioctl(cdrom->id, CDROMSUBCHNL, &info) < 0 ) {
		if ( ERRNO_TRAYEMPTY(errno) ) {
			status = CD_TRAYEMPTY;
		} else {
			status = CD_ERROR;
		}
	} else {
		switch (info.cdsc_audiostatus) {
			case CDROM_AUDIO_INVALID:
			case CDROM_AUDIO_NO_STATUS:
				/* Try to determine if there's a CD available */
				if (SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc)==0) {
					status = CD_STOPPED;
				} else {
					status = CD_TRAYEMPTY;
				}
				break;
			case CDROM_AUDIO_COMPLETED:
				status = CD_STOPPED;
				break;
			case CDROM_AUDIO_PLAY:
				status = CD_PLAYING;
				break;
			case CDROM_AUDIO_PAUSED:
				/* Workaround buggy CD-ROM drive */
				if ( info.cdsc_trk == CDROM_LEADOUT ) {
					status = CD_STOPPED;
				} else {
					status = CD_PAUSED;
				}
				break;
			default:
				status = CD_ERROR;
				break;
		}
	}
	if ( position ) {
		if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
			*position = MSF_TO_FRAMES(
					info.cdsc_absaddr.msf.minute,
					info.cdsc_absaddr.msf.second,
					info.cdsc_absaddr.msf.frame);
		} else {
			*position = 0;
		}
	}
	return(status);
}
Example #4
0
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
{
    struct cd_audio_cmd cmd;
    struct cd_audio_cmd entry;
    int                 i;
    int                 okay;

    cmd.audio_cmds = CD_TRK_INFO_AUDIO;
    cmd.msf_flag   = FALSE;
    if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) {
	return -1;
    }

    okay = 0;
    cdrom->numtracks = cmd.indexing.track_index.last_track
		     - cmd.indexing.track_index.first_track+1;
    if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
        cdrom->numtracks = SDL_MAX_TRACKS;
    }

    /* Read all the track TOC entries */
    for ( i=0; i<=cdrom->numtracks; ++i ) {
        if ( i == cdrom->numtracks ) {
            cdrom->track[i].id = 0xAA;;
        } else {
            cdrom->track[i].id = cmd.indexing.track_index.first_track+i;
        }
        entry.audio_cmds         = CD_GET_TRK_MSF;
	entry.indexing.track_msf.track = cdrom->track[i].id;
	if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &entry) < 0 ) {
            break;
        } else {
            cdrom->track[i].type = 0;    /* don't know how to detect 0x04 data track */
            cdrom->track[i].offset = MSF_TO_FRAMES(
                entry.indexing.track_msf.mins,
                entry.indexing.track_msf.secs,
                entry.indexing.track_msf.frames);
            cdrom->track[i].length = 0;
            if ( i > 0 ) {
                cdrom->track[i-1].length = cdrom->track[i].offset
		                         - cdrom->track[i-1].offset;
            }
        }
    }
    if ( i == (cdrom->numtracks+1) ) {
        okay = 1;
    }
    return(okay ? 0 : -1);
}
Example #5
0
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
{
	struct cdrom_tochdr toc;
	int i, okay;
	struct cdrom_tocentry entry;

	okay = 0;
	if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCHDR, &toc) == 0 ) {
		cdrom->numtracks = toc.cdth_trk1-toc.cdth_trk0+1;
		if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
			cdrom->numtracks = SDL_MAX_TRACKS;
		}
		/* Read all the track TOC entries */
		for ( i=0; i<=cdrom->numtracks; ++i ) {
			if ( i == cdrom->numtracks ) {
				cdrom->track[i].id = CDROM_LEADOUT;
			} else {
				cdrom->track[i].id = toc.cdth_trk0+i;
			}
			entry.cdte_track = cdrom->track[i].id;
			entry.cdte_format = CDROM_MSF;
			if ( SDL_SYS_CDioctl(cdrom->id, CDROMREADTOCENTRY,
								&entry) < 0 ) {
				break;
			} else {
				if ( entry.cdte_ctrl & CDROM_DATA_TRACK ) {
					cdrom->track[i].type = SDL_DATA_TRACK;
				} else {
					cdrom->track[i].type = SDL_AUDIO_TRACK;
				}
				cdrom->track[i].offset = MSF_TO_FRAMES(
						entry.cdte_addr.msf.minute,
						entry.cdte_addr.msf.second,
						entry.cdte_addr.msf.frame);
				cdrom->track[i].length = 0;
				if ( i > 0 ) {
					cdrom->track[i-1].length =
						cdrom->track[i].offset-
						cdrom->track[i-1].offset;
				}
			}
		}
		if ( i == (cdrom->numtracks+1) ) {
			okay = 1;
		}
	}
	return(okay ? 0 : -1);
}
Example #6
0
/* Pause play */
static int SDL_SYS_CDPause(SDL_CD *cdrom)
{
#ifdef BROKEN_MCI_PAUSE
	SDL_paused[cdrom->id] = 1;
#endif
	return(SDL_SYS_CDioctl(cdrom->id, MCI_PAUSE, MCI_WAIT, NULL));
}
Example #7
0
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
{
	struct ioc_toc_header toc;
	int i, okay;
	struct ioc_read_toc_entry entry;
	struct cd_toc_entry data;

	okay = 0;
	if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCHEADER, &toc) == 0 ) {
		cdrom->numtracks = toc.ending_track-toc.starting_track+1;
		if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
			cdrom->numtracks = SDL_MAX_TRACKS;
		}
		/* Read all the track TOC entries */
		for ( i=0; i<=cdrom->numtracks; ++i ) {
			if ( i == cdrom->numtracks ) {
				cdrom->track[i].id = 0xAA; /* CDROM_LEADOUT */
			} else {
				cdrom->track[i].id = toc.starting_track+i;
			}
			entry.starting_track = cdrom->track[i].id;
			entry.address_format = CD_MSF_FORMAT;
			entry.data_len = sizeof(data);
			entry.data = &data;
			if ( SDL_SYS_CDioctl(cdrom->id, CDIOREADTOCENTRYS,
								&entry) < 0 ) {
				break;
			} else {
				cdrom->track[i].type = data.control;
				cdrom->track[i].offset = MSF_TO_FRAMES(
						data.addr.msf.minute,
						data.addr.msf.second,
						data.addr.msf.frame);
				cdrom->track[i].length = 0;
				if ( i > 0 ) {
					cdrom->track[i-1].length =
						cdrom->track[i].offset-
						cdrom->track[i-1].offset;
				}
			}
		}
		if ( i == (cdrom->numtracks+1) ) {
			okay = 1;
		}
	}
	return(okay ? 0 : -1);
}
Example #8
0
/* Get CD-ROM status */
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
{
    CDstatus            status;
    struct cd_audio_cmd cmd;
    cmd.audio_cmds = CD_INFO_AUDIO;

    if ( SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd) < 0 ) {
#ifdef DEBUG_CDROM
    fprintf(stderr, "ioctl failed in SDL_SYS_CDStatus (%s)\n", SDL_GetError());
#endif
        status = CD_ERROR;
    } else {
        switch (cmd.status) {
            case CD_NO_AUDIO:
            case CD_COMPLETED:
                status = CD_STOPPED;
                break;
            case CD_PLAY_AUDIO:
                status = CD_PLAYING;
                break;
            case CD_PAUSE_AUDIO:
                status = CD_PAUSED;
                break;
            case CD_NOT_VALID:
#ifdef DEBUG_CDROM
    fprintf(stderr, "cdStatus failed with CD_NOT_VALID\n");
#endif
                status = CD_ERROR;
                break;
            case CD_STATUS_ERROR:
#ifdef DEBUG_CDROM
    fprintf(stderr, "cdStatus failed with CD_STATUS_ERROR\n");
#endif
                status = CD_ERROR;
                break;
            default:
#ifdef DEBUG_CDROM
    fprintf(stderr, "cdStatus failed with unknown error\n");
#endif
                status = CD_ERROR;
                break;
        }
    }
    if ( position ) {
        if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
            *position = MSF_TO_FRAMES( cmd.indexing.info_audio.current_mins,
                                       cmd.indexing.info_audio.current_secs,
                                       cmd.indexing.info_audio.current_frames);
        } else {
            *position = 0;
        }
    }
    return status;
}
Example #9
0
/* Start play */
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
{
	struct cdrom_msf playtime;

	FRAMES_TO_MSF(start,
	   &playtime.cdmsf_min0, &playtime.cdmsf_sec0, &playtime.cdmsf_frame0);
	FRAMES_TO_MSF(start+length,
	   &playtime.cdmsf_min1, &playtime.cdmsf_sec1, &playtime.cdmsf_frame1);
#ifdef DEBUG_CDROM
  fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
	playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
	playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
#endif
	return(SDL_SYS_CDioctl(cdrom->id, CDROMPLAYMSF, &playtime));
}
Example #10
0
/* Start play */
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
{
	MCI_PLAY_PARMS mci_play;
	int m, s, f;
	DWORD flags;

	flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
	mci_play.dwCallback = 0;
	FRAMES_TO_MSF(start, &m, &s, &f);
	mci_play.dwFrom = MCI_MAKE_MSF(m, s, f);
	FRAMES_TO_MSF(start+length, &m, &s, &f);
	mci_play.dwTo = MCI_MAKE_MSF(m, s, f);
	SDL_CD_end_position = mci_play.dwTo;
	return(SDL_SYS_CDioctl(cdrom->id, MCI_PLAY, flags, &mci_play));
}
Example #11
0
/* Check a drive to see if it is a CD-ROM */
static int CheckDrive(char *drive, struct stat *stbuf)
{
    int is_cd;
    int cdfd;
    int ret;
    struct devinfo info;

    /* If it doesn't exist, return -1 */
    if ( stat(drive, stbuf) < 0 ) {
        return -1;
    }

    /* If it does exist, verify that it's an available CD-ROM */
    is_cd = 0;
    if ( S_ISCHR(stbuf->st_mode) || S_ISBLK(stbuf->st_mode) ) {
        cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
        if ( cdfd >= 0 ) {
            ret = SDL_SYS_CDioctl( cdfd, IOCINFO, &info );
	    if ( ret < 0 ) {
		/* Some kind of error */
		is_cd = 0;
	    } else {
		if ( info.devtype == DD_CDROM ) {
		    is_cd = 1;
		} else {
		    is_cd = 0;
		}
	    }
            close(cdfd);
	}
#ifdef DEBUG_CDROM
	else
	{
            fprintf(stderr, "Could not open drive %s (%s)\n", drive, strerror(errno));
	}
#endif
    }
    return is_cd;
}
Example #12
0
/* Start play */
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
{
    struct cd_audio_cmd cmd;

    /*
     * My CD Rom is muted by default. I think I read that this is new with
     * AIX 4.3. SDL does not change the volume, so I need a kludge. Maybe
     * its better to do this elsewhere?
     */
    cmd.audio_cmds = CD_PLAY_AUDIO | CD_SET_VOLUME;
    cmd.msf_flag   = TRUE;
    FRAMES_TO_MSF(start,
                  &cmd.indexing.msf.first_mins,
                  &cmd.indexing.msf.first_secs,
                  &cmd.indexing.msf.first_frames);
    FRAMES_TO_MSF(start+length,
                  &cmd.indexing.msf.last_mins,
                  &cmd.indexing.msf.last_secs,
                  &cmd.indexing.msf.last_frames);
    cmd.volume_type     = CD_VOLUME_ALL;
    cmd.all_channel_vol = 255;   /* This is a uchar. What is a good value? No docu! */
    cmd.out_port_0_sel  = CD_AUDIO_CHNL_0;
    cmd.out_port_1_sel  = CD_AUDIO_CHNL_1;
    cmd.out_port_2_sel  = CD_AUDIO_CHNL_2;
    cmd.out_port_3_sel  = CD_AUDIO_CHNL_3;

#ifdef DEBUG_CDROM
  fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
	cmd.indexing.msf.first_mins,
	cmd.indexing.msf.first_secs,
	cmd.indexing.msf.first_frames,
	cmd.indexing.msf.last_mins,
	cmd.indexing.msf.last_secs,
	cmd.indexing.msf.last_frames);
#endif
	return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
}
Example #13
0
/* Get CD-ROM status */
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
{
	CDstatus status;
	MCI_STATUS_PARMS mci_status;
	DWORD flags;

	flags = MCI_STATUS_ITEM | MCI_WAIT;
	mci_status.dwItem = MCI_STATUS_MODE;
	if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) {
		status = CD_ERROR;
	} else {
		switch (mci_status.dwReturn) {
			case MCI_MODE_NOT_READY:
			case MCI_MODE_OPEN:
				status = CD_TRAYEMPTY;
				break;
			case MCI_MODE_STOP:
#ifdef BROKEN_MCI_PAUSE
				if ( SDL_paused[cdrom->id] ) {
					status = CD_PAUSED;
				} else {
					status = CD_STOPPED;
				}
#else
				status = CD_STOPPED;
#endif /* BROKEN_MCI_PAUSE */
				break;
			case MCI_MODE_PLAY:
#ifdef BROKEN_MCI_PAUSE
				if ( SDL_paused[cdrom->id] ) {
					status = CD_PAUSED;
				} else {
					status = CD_PLAYING;
				}
#else
				status = CD_PLAYING;
#endif /* BROKEN_MCI_PAUSE */
				break;
			case MCI_MODE_PAUSE:
				status = CD_PAUSED;
				break;
			default:
				status = CD_ERROR;
				break;
		}
	}
	if ( position ) {
		if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
			mci_status.dwItem = MCI_STATUS_POSITION;
			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
							&mci_status) == 0 ) {
				*position = MSF_TO_FRAMES(
					MCI_MSF_MINUTE(mci_status.dwReturn),
					MCI_MSF_SECOND(mci_status.dwReturn),
					MCI_MSF_FRAME(mci_status.dwReturn));
			} else {
				*position = 0;
			}
		} else {
			*position = 0;
		}
	}
	return(status);
}
Example #14
0
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
{
	MCI_STATUS_PARMS mci_status;
	int i, okay;
	DWORD flags;

	okay = 0;
	mci_status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
	flags = MCI_STATUS_ITEM | MCI_WAIT;
	if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) {
		cdrom->numtracks = mci_status.dwReturn;
		if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
			cdrom->numtracks = SDL_MAX_TRACKS;
		}
		/* Read all the track TOC entries */
		flags = MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT;
		for ( i=0; i<cdrom->numtracks; ++i ) {
			cdrom->track[i].id = i+1;
			mci_status.dwTrack = cdrom->track[i].id;
#ifdef MCI_CDA_STATUS_TYPE_TRACK
			mci_status.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
							&mci_status) < 0 ) {
				break;
			}
			if ( mci_status.dwReturn == MCI_CDA_TRACK_AUDIO ) {
				cdrom->track[i].type = SDL_AUDIO_TRACK;
			} else {
				cdrom->track[i].type = SDL_DATA_TRACK;
			}
#else
			cdrom->track[i].type = SDL_AUDIO_TRACK;
#endif
			mci_status.dwItem = MCI_STATUS_POSITION;
			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
							&mci_status) < 0 ) {
				break;
			}
			cdrom->track[i].offset = MSF_TO_FRAMES(
					MCI_MSF_MINUTE(mci_status.dwReturn),
					MCI_MSF_SECOND(mci_status.dwReturn),
					MCI_MSF_FRAME(mci_status.dwReturn));
			cdrom->track[i].length = 0;
			if ( i > 0 ) {
				cdrom->track[i-1].length =
						cdrom->track[i].offset-
						cdrom->track[i-1].offset;
			}
		}
		if ( i == cdrom->numtracks ) {
			mci_status.dwTrack = cdrom->track[i - 1].id;
			mci_status.dwItem = MCI_STATUS_LENGTH;
			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
							&mci_status) == 0 ) {
				cdrom->track[i - 1].length = MSF_TO_FRAMES(
					MCI_MSF_MINUTE(mci_status.dwReturn),
					MCI_MSF_SECOND(mci_status.dwReturn),
					MCI_MSF_FRAME(mci_status.dwReturn));
				/* compute lead-out offset */
				cdrom->track[i].offset = cdrom->track[i - 1].offset +
					cdrom->track[i - 1].length;
				cdrom->track[i].length = 0;
				okay = 1;
			}
		}
	}
	return(okay ? 0 : -1);
}
Example #15
0
/* Eject the CD-ROM */
static int SDL_SYS_CDEject(SDL_CD *cdrom)
{
	return(SDL_SYS_CDioctl(cdrom->id, CDROMEJECT, 0));
}
Example #16
0
/* Stop play */
static int SDL_SYS_CDStop(SDL_CD *cdrom)
{
	return(SDL_SYS_CDioctl(cdrom->id, CDROMSTOP, 0));
}
Example #17
0
/* Resume play */
static int SDL_SYS_CDResume(SDL_CD *cdrom)
{
	return(SDL_SYS_CDioctl(cdrom->id, CDROMRESUME, 0));
}
Example #18
0
/* Eject the CD-ROM */
static int SDL_SYS_CDEject(SDL_CD *cdrom)
{
	return(SDL_SYS_CDioctl(cdrom->id, MCI_SET, MCI_SET_DOOR_OPEN, NULL));
}
Example #19
0
/* Pause play */
static int SDL_SYS_CDPause(SDL_CD *cdrom)
{
    struct cd_audio_cmd cmd;
    cmd.audio_cmds = CD_PAUSE_AUDIO;
    return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
}
Example #20
0
/* Resume play */
static int SDL_SYS_CDResume(SDL_CD *cdrom)
{
    struct cd_audio_cmd cmd;
    cmd.audio_cmds = CD_RESUME_AUDIO;
    return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
}
Example #21
0
/* Stop play */
static int SDL_SYS_CDStop(SDL_CD *cdrom)
{
    struct cd_audio_cmd cmd;
    cmd.audio_cmds = CD_STOP_AUDIO;
    return(SDL_SYS_CDioctl(cdrom->id, DKAUDIO, &cmd));
}
Example #22
0
/* Stop play */
static int SDL_SYS_CDStop(SDL_CD *cdrom)
{
	return(SDL_SYS_CDioctl(cdrom->id, MCI_STOP, MCI_WAIT, NULL));
}
Example #23
0
/* Pause play */
static int SDL_SYS_CDPause(SDL_CD *cdrom)
{
	return(SDL_SYS_CDioctl(cdrom->id, CDROMPAUSE, 0));
}
Example #24
0
/* Close the CD-ROM handle */
static void SDL_SYS_CDClose(SDL_CD *cdrom)
{
	SDL_SYS_CDioctl(cdrom->id, MCI_CLOSE, MCI_WAIT, NULL);
}
Example #25
0
static int SDL_SYS_CDOpen(int drive)
{
    int   fd;
    char* lastsl;
    char* cdromname;

    /*
     * We found /dev/cd? drives and that is in our list. But we can
     * open only the /dev/rcd? versions of those devices for Audio CD.
     */
    cdromname = (char*)malloc( strlen(SDL_cdlist[drive]+2) );
    strcpy(cdromname,SDL_cdlist[drive]);
    lastsl = strrchr(cdromname,'/');
    if (lastsl) {
	*lastsl = 0;
	strcat(cdromname,"/r");
	lastsl = strrchr(SDL_cdlist[drive],'/');
	if (lastsl) {
	    lastsl++;
	    strcat(cdromname,lastsl);
	}
    }

#ifdef DEBUG_CDROM
    fprintf(stderr, "Should open drive %s, opening %s\n", SDL_cdlist[drive], cdromname);
#endif

    /*
     * Use exclusive access. Don't use SC_DIAGNOSTICS as xmcd does because they
     * require root priviledges, and we don't want that. SC_SINGLE provides
     * exclusive access with less trouble.
     */
    fd = openx(cdromname, O_RDONLY, NULL, SC_SINGLE);
    if ( fd < 0 )
    {
#ifdef DEBUG_CDROM
            fprintf(stderr, "Could not open drive %s (%s)\n", cdromname, strerror(errno));
#endif
    }
    else
    {
	struct mode_form_op cdMode;
	int                 ret;
#ifdef DEBUG_CDROM
	cdMode.action = CD_GET_MODE;
	ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode);
	if ( ret < 0 ) {
            fprintf(stderr,
	            "Could not get drive mode for %s (%s)\n",
		    cdromname, strerror(errno));
	} else {
	    switch(cdMode.cd_mode_form) {
		case CD_MODE1 :
                    fprintf(stderr,
	                "Drive mode for %s is %s\n",
		        cdromname, "CD-ROM Data Mode 1");
		    break;
		case CD_MODE2_FORM1 :
                    fprintf(stderr,
	                "Drive mode for %s is %s\n",
		        cdromname, "CD-ROM XA Data Mode 2 Form 1");
		    break;
		case CD_MODE2_FORM2 :
                    fprintf(stderr,
	                "Drive mode for %s is %s\n",
		        cdromname, "CD-ROM XA Data Mode 2 Form 2");
		    break;
		case CD_DA :
                    fprintf(stderr,
	                "Drive mode for %s is %s\n",
		        cdromname, "CD-DA");
		    break;
		default :
                    fprintf(stderr,
	                "Drive mode for %s is %s\n",
		        cdromname, "unknown");
		    break;
	    }
	}
#endif

	cdMode.action       = CD_CHG_MODE;
	cdMode.cd_mode_form = CD_DA;
	ret = SDL_SYS_CDioctl(fd, DK_CD_MODE, &cdMode);
	if ( ret < 0 ) {
#ifdef DEBUG_CDROM
            fprintf(stderr,
	            "Could not set drive mode for %s (%s)\n",
		    cdromname, strerror(errno));
#endif
            SDL_SetError("ioctl() error: Could not set CD drive mode, %s",
	                 strerror(errno));
	} else {
#ifdef DEBUG_CDROM
            fprintf(stderr,
	            "Drive mode for %s set to CD_DA\n",
		    cdromname);
#endif
	}
    }
    free(cdromname);
    return fd;
}