146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SDL_CDROM_WIN32
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Functions for system-level CD-ROM audio control */
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define WIN32_LEAN_AND_MEAN
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <windows.h>
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <mmsystem.h>
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_cdrom.h"
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_syscdrom.h"
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* This really broken?? */
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define BROKEN_MCI_PAUSE	/* Pausing actually stops play -- Doh! */
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The maximum number of CD-ROM drives we'll detect (Don't change!) */
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_DRIVES	26
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* A list of available CD-ROM drives */
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic char *SDL_cdlist[MAX_DRIVES];
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic MCIDEVICEID SDL_mciID[MAX_DRIVES];
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef BROKEN_MCI_PAUSE
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_paused[MAX_DRIVES];
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_CD_end_position;
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The system-dependent CD control functions */
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic const char *SDL_SYS_CDName(int drive);
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDOpen(int drive);
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPause(SDL_CD *cdrom);
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDResume(SDL_CD *cdrom);
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDStop(SDL_CD *cdrom);
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDEject(SDL_CD *cdrom);
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SDL_SYS_CDClose(SDL_CD *cdrom);
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Add a CD-ROM drive to our list of valid drives */
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void AddDrive(char *drive)
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_numcds < MAX_DRIVES ) {
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Add this drive to our list */
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		i = SDL_numcds;
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_cdlist[i] = SDL_strdup(drive);
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( SDL_cdlist[i] == NULL ) {
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_OutOfMemory();
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return;
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		++SDL_numcds;
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef CDROM_DEBUG
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint  SDL_SYS_CDInit(void)
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* checklist: Drive 'A' - 'Z' */
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char drive[4];
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Fill in our driver capabilities */
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Name = SDL_SYS_CDName;
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Open = SDL_SYS_CDOpen;
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Status = SDL_SYS_CDStatus;
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Play = SDL_SYS_CDPlay;
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Pause = SDL_SYS_CDPause;
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Resume = SDL_SYS_CDResume;
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Stop = SDL_SYS_CDStop;
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Eject = SDL_SYS_CDEject;
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Close = SDL_SYS_CDClose;
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Scan the system for CD-ROM drives */
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( i='A'; i<='Z'; ++i ) {
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_snprintf(drive, SDL_arraysize(drive), "%c:\\", i);
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( GetDriveType(drive) == DRIVE_CDROM ) {
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			AddDrive(drive);
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_memset(SDL_mciID, 0, sizeof(SDL_mciID));
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* General ioctl() CD-ROM command function */
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDioctl(int id, UINT msg, DWORD flags, void *arg)
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCIERROR mci_error;
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_error = mciSendCommand(SDL_mciID[id], msg, flags, (DWORD_PTR)arg);
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( mci_error ) {
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		char error[256];
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		mciGetErrorString(mci_error, error, 256);
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_SetError("mciSendCommand() error: %s", error);
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(!mci_error ? 0 : -1);
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic const char *SDL_SYS_CDName(int drive)
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_cdlist[drive]);
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDOpen(int drive)
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCI_OPEN_PARMS mci_open;
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCI_SET_PARMS mci_set;
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char device[3];
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DWORD flags;
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Open the requested device */
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	device[0] = *SDL_cdlist[drive];
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	device[1] = ':';
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	device[2] = '\0';
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_open.lpstrElementName = device;
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	flags =
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	  (MCI_OPEN_TYPE|MCI_OPEN_SHAREABLE|MCI_OPEN_TYPE_ID|MCI_OPEN_ELEMENT);
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) {
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		flags &= ~MCI_OPEN_SHAREABLE;
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( SDL_SYS_CDioctl(0, MCI_OPEN, flags, &mci_open) < 0 ) {
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(-1);
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_mciID[drive] = mci_open.wDeviceID;
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Set the minute-second-frame time format */
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_set.dwTimeFormat = MCI_FORMAT_MSF;
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SYS_CDioctl(drive, MCI_SET, MCI_SET_TIME_FORMAT, &mci_set);
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef BROKEN_MCI_PAUSE
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_paused[drive] = 0;
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(drive);
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCI_STATUS_PARMS mci_status;
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i, okay;
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DWORD flags;
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	okay = 0;
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_status.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	flags = MCI_STATUS_ITEM | MCI_WAIT;
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) {
17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		cdrom->numtracks = mci_status.dwReturn;
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->numtracks = SDL_MAX_TRACKS;
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Read all the track TOC entries */
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		flags = MCI_STATUS_ITEM | MCI_TRACK | MCI_WAIT;
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; i<cdrom->numtracks; ++i ) {
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].id = i+1;
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mci_status.dwTrack = cdrom->track[i].id;
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef MCI_CDA_STATUS_TYPE_TRACK
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mci_status.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner							&mci_status) < 0 ) {
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( mci_status.dwReturn == MCI_CDA_TRACK_AUDIO ) {
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				cdrom->track[i].type = SDL_AUDIO_TRACK;
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} else {
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				cdrom->track[i].type = SDL_DATA_TRACK;
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].type = SDL_AUDIO_TRACK;
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mci_status.dwItem = MCI_STATUS_POSITION;
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner							&mci_status) < 0 ) {
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].offset = MSF_TO_FRAMES(
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_MINUTE(mci_status.dwReturn),
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_SECOND(mci_status.dwReturn),
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_FRAME(mci_status.dwReturn));
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].length = 0;
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( i > 0 ) {
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				cdrom->track[i-1].length =
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						cdrom->track[i].offset-
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						cdrom->track[i-1].offset;
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( i == cdrom->numtracks ) {
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mci_status.dwTrack = cdrom->track[i - 1].id;
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mci_status.dwItem = MCI_STATUS_LENGTH;
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner							&mci_status) == 0 ) {
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				cdrom->track[i - 1].length = MSF_TO_FRAMES(
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_MINUTE(mci_status.dwReturn),
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_SECOND(mci_status.dwReturn),
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_FRAME(mci_status.dwReturn));
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				/* compute lead-out offset */
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				cdrom->track[i].offset = cdrom->track[i - 1].offset +
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					cdrom->track[i - 1].length;
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				cdrom->track[i].length = 0;
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				okay = 1;
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(okay ? 0 : -1);
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Get CD-ROM status */
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	CDstatus status;
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCI_STATUS_PARMS mci_status;
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DWORD flags;
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	flags = MCI_STATUS_ITEM | MCI_WAIT;
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_status.dwItem = MCI_STATUS_MODE;
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) < 0 ) {
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		status = CD_ERROR;
24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	} else {
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		switch (mci_status.dwReturn) {
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MCI_MODE_NOT_READY:
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MCI_MODE_OPEN:
24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_TRAYEMPTY;
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MCI_MODE_STOP:
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef BROKEN_MCI_PAUSE
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( SDL_paused[cdrom->id] ) {
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					status = CD_PAUSED;
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				} else {
25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					status = CD_STOPPED;
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_STOPPED;
25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* BROKEN_MCI_PAUSE */
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MCI_MODE_PLAY:
26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef BROKEN_MCI_PAUSE
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( SDL_paused[cdrom->id] ) {
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					status = CD_PAUSED;
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				} else {
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					status = CD_PLAYING;
26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_PLAYING;
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* BROKEN_MCI_PAUSE */
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case MCI_MODE_PAUSE:
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_PAUSED;
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			default:
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_ERROR;
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( position ) {
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			mci_status.dwItem = MCI_STATUS_POSITION;
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags,
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner							&mci_status) == 0 ) {
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				*position = MSF_TO_FRAMES(
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_MINUTE(mci_status.dwReturn),
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_SECOND(mci_status.dwReturn),
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					MCI_MSF_FRAME(mci_status.dwReturn));
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} else {
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				*position = 0;
29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else {
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			*position = 0;
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(status);
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Start play */
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCI_PLAY_PARMS mci_play;
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int m, s, f;
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	DWORD flags;
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_play.dwCallback = 0;
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	FRAMES_TO_MSF(start, &m, &s, &f);
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_play.dwFrom = MCI_MAKE_MSF(m, s, f);
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	FRAMES_TO_MSF(start+length, &m, &s, &f);
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_play.dwTo = MCI_MAKE_MSF(m, s, f);
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CD_end_position = mci_play.dwTo;
31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_SYS_CDioctl(cdrom->id, MCI_PLAY, flags, &mci_play));
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Pause play */
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPause(SDL_CD *cdrom)
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef BROKEN_MCI_PAUSE
32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_paused[cdrom->id] = 1;
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_SYS_CDioctl(cdrom->id, MCI_PAUSE, MCI_WAIT, NULL));
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Resume play */
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDResume(SDL_CD *cdrom)
32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef BROKEN_MCI_PAUSE
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	MCI_STATUS_PARMS mci_status;
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int okay;
33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int flags;
33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	okay = 0;
33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Play from the current play position to the end position set earlier */
33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	flags = MCI_STATUS_ITEM | MCI_WAIT;
33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	mci_status.dwItem = MCI_STATUS_POSITION;
33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_SYS_CDioctl(cdrom->id, MCI_STATUS, flags, &mci_status) == 0 ) {
33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		MCI_PLAY_PARMS mci_play;
33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		mci_play.dwCallback = 0;
34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		mci_play.dwFrom = mci_status.dwReturn;
34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		mci_play.dwTo = SDL_CD_end_position;
34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if (SDL_SYS_CDioctl(cdrom->id,MCI_PLAY,flags,&mci_play) == 0) {
34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			okay = 1;
34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_paused[cdrom->id] = 0;
34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(okay ? 0 : -1);
35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#else
35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_SYS_CDioctl(cdrom->id, MCI_RESUME, MCI_WAIT, NULL));
35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* BROKEN_MCI_PAUSE */
35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Stop play */
35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDStop(SDL_CD *cdrom)
35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_SYS_CDioctl(cdrom->id, MCI_STOP, MCI_WAIT, NULL));
35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Eject the CD-ROM */
36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDEject(SDL_CD *cdrom)
36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_SYS_CDioctl(cdrom->id, MCI_SET, MCI_SET_DOOR_OPEN, NULL));
36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Close the CD-ROM handle */
36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SDL_SYS_CDClose(SDL_CD *cdrom)
36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_SYS_CDioctl(cdrom->id, MCI_CLOSE, MCI_WAIT, NULL);
37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_CDQuit(void)
37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_numcds > 0 ) {
37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; i<SDL_numcds; ++i ) {
37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_free(SDL_cdlist[i]);
38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_numcds = 0;
38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* SDL_CDROM_WIN32 */
386