SDL-1.2.14
[sdl_omap.git] / src / cdrom / os2 / SDL_syscdrom.c
CommitLineData
e14743d1 1/*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2009 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 Sam Lantinga
20 slouken@libsdl.org
21*/
22#include "SDL_config.h"
23
24#ifdef SDL_CDROM_OS2
25
26/* Functions for system-level CD-ROM audio control */
27
28#define INCL_MCIOS2
29#include <os2.h>
30#include <os2me.h>
31
32#include "SDL_cdrom.h"
33#include "../SDL_syscdrom.h"
34
35/* Size of MCI result buffer (in bytes) */
36#define MCI_CMDRETBUFSIZE 128
37
38/* The maximum number of CD-ROM drives we'll detect */
39#define MAX_DRIVES 16
40
41/* A list of available CD-ROM drives */
42static char *SDL_cdlist[MAX_DRIVES];
43//static dev_t SDL_cdmode[MAX_DRIVES];
44
45/* The system-dependent CD control functions */
46static const char *SDL_SYS_CDName(int drive);
47static int SDL_SYS_CDOpen(int drive);
48static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
49static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
50static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
51static int SDL_SYS_CDPause(SDL_CD *cdrom);
52static int SDL_SYS_CDResume(SDL_CD *cdrom);
53static int SDL_SYS_CDStop(SDL_CD *cdrom);
54static int SDL_SYS_CDEject(SDL_CD *cdrom);
55static void SDL_SYS_CDClose(SDL_CD *cdrom);
56
57/* MCI Timing Functions */
58#define MCI_MMTIMEPERSECOND 3000
59#define FRAMESFROMMM(mmtime) (((mmtime)*CD_FPS)/MCI_MMTIMEPERSECOND)
60
61
62/* Ready for MCI CDAudio Devices */
63int SDL_SYS_CDInit(void)
64{
65int i; /* generig counter */
66MCI_SYSINFO_PARMS msp; /* Structure to MCI SysInfo parameters */
67CHAR SysInfoRet[MCI_CMDRETBUFSIZE]; /* Buffer for MCI Command result */
68
69/* Fill in our driver capabilities */
70SDL_CDcaps.Name = SDL_SYS_CDName;
71SDL_CDcaps.Open = SDL_SYS_CDOpen;
72SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
73SDL_CDcaps.Status = SDL_SYS_CDStatus;
74SDL_CDcaps.Play = SDL_SYS_CDPlay;
75SDL_CDcaps.Pause = SDL_SYS_CDPause;
76SDL_CDcaps.Resume = SDL_SYS_CDResume;
77SDL_CDcaps.Stop = SDL_SYS_CDStop;
78SDL_CDcaps.Eject = SDL_SYS_CDEject;
79SDL_CDcaps.Close = SDL_SYS_CDClose;
80
81/* Get the number of CD ROMs in the System */
82/* Clean SysInfo structure */
83SDL_memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));
84/* Prepare structure to Ask Numer of Audio CDs */
85msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
86msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
87msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
88if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
89SDL_numcds = atoi(SysInfoRet);
90if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */
91
92/* Get and Add their system name to the SDL_cdlist */
93msp.pszReturn = (PSZ)&SysInfoRet; /* Return Structure */
94msp.ulRetSize = MCI_CMDRETBUFSIZE; /* Size of ret struct */
95msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO; /* CD Audio Type */
96for (i=0; i<SDL_numcds; i++)
97 {
98 msp.ulNumber = i+1;
99 mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_NAME | MCI_WAIT,&msp, 0);
100 SDL_cdlist[i] = SDL_strdup(SysInfoRet);
101 if ( SDL_cdlist[i] == NULL )
102 {
103 SDL_OutOfMemory();
104 return(-1);
105 }
106 }
107return(0);
108}
109
110/* Return CDAudio System Dependent Device Name - Ready for MCI*/
111static const char *SDL_SYS_CDName(int drive)
112{
113return(SDL_cdlist[drive]);
114}
115
116/* Open CDAudio Device - Ready for MCI */
117static int SDL_SYS_CDOpen(int drive)
118{
119MCI_OPEN_PARMS mop;
120MCI_SET_PARMS msp;
121MCI_GENERIC_PARMS mgp;
122
123/* Open the device */
124mop.hwndCallback = (HWND)NULL; // None
125mop.usDeviceID = (USHORT)NULL; // Will be returned.
126mop.pszDeviceType = (PSZ)SDL_cdlist[drive]; // CDAudio Device
127if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
128/* Set time format */
129msp.hwndCallback = (HWND)NULL; // None
130msp.ulTimeFormat = MCI_FORMAT_MSF; // Minute : Second : Frame structure
131msp.ulSpeedFormat = (ULONG)NULL; // No change
132msp.ulAudio = (ULONG)NULL; // No Channel
133msp.ulLevel = (ULONG)NULL; // No Volume
134msp.ulOver = (ULONG)NULL; // No Delay
135msp.ulItem = (ULONG)NULL; // No item
136msp.ulValue = (ULONG)NULL; // No value for item flag
137if (LOUSHORT(mciSendCommand(mop.usDeviceID,MCI_SET,MCI_WAIT | MCI_SET_TIME_FORMAT,&msp, 0)) == MCIERR_SUCCESS) return (mop.usDeviceID);
138/* Error setting time format? - Close opened device */
139mgp.hwndCallback = (HWND)NULL; // None
140mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);
141return(CD_ERROR);
142}
143
144/* Get CD Table Of Contents - Ready for MCI */
145static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
146{
147MCI_TOC_PARMS mtp;
148MCI_STATUS_PARMS msp;
149MCI_TOC_REC * mtr;
150INT i;
151
152/* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */
153if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;
154
155/* Get Number of Tracks */
156msp.hwndCallback = (HWND)NULL; /* None */
157msp.ulReturn = (ULONG)NULL; /* We want this information */
158msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;
159msp.ulValue = (ULONG)NULL; /* No additional information */
160if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
161cdrom->numtracks = msp.ulReturn;
162if ( cdrom->numtracks > SDL_MAX_TRACKS )
163 {
164 cdrom->numtracks = SDL_MAX_TRACKS;
165 }
166/* Alocate space for TOC data */
167mtr = (MCI_TOC_REC *)SDL_malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));
168if ( mtr == NULL )
169 {
170 SDL_OutOfMemory();
171 return(-1);
172 }
173/* Get TOC from CD */
174mtp.pBuf = mtr;
175mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);
176if (LOUSHORT(mciSendCommand(cdrom->id,MCI_GETTOC,MCI_WAIT,&mtp, 0)) != MCIERR_SUCCESS)
177 {
178 SDL_OutOfMemory();
179 SDL_free(mtr);
180 return(CD_ERROR);
181 }
182/* Fill SDL Tracks Structure */
183for (i=0; i<cdrom->numtracks; i++)
184 {
185 /* Set Track ID */
186 cdrom->track[i].id = (mtr+i)->TrackNum;
187 /* Set Track Type */
188 msp.hwndCallback = (HWND)NULL; /* None */
189 msp.ulReturn = (ULONG)NULL; /* We want this information */
190 msp.ulItem = MCI_CD_STATUS_TRACK_TYPE;
191 msp.ulValue = (ULONG)((mtr+i)->TrackNum); /* Track Number? */
192 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_TRACK | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS)
193 {
194 SDL_free(mtr);
195 return (CD_ERROR);
196 }
197 if (msp.ulReturn==MCI_CD_TRACK_AUDIO) cdrom->track[i].type = SDL_AUDIO_TRACK;
198 else cdrom->track[i].type = SDL_DATA_TRACK;
199 /* Set Track Length - values from MCI are in MMTIMEs - 3000 MMTIME = 1 second */
200 cdrom->track[i].length = FRAMESFROMMM((mtr+i)->ulEndAddr - (mtr+i)->ulStartAddr);
201 /* Set Track Offset */
202 cdrom->track[i].offset = FRAMESFROMMM((mtr+i)->ulStartAddr);
203 }
204SDL_free(mtr);
205return(0);
206}
207
208
209/* Get CD-ROM status - Ready for MCI */
210static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
211{
212CDstatus status;
213MCI_STATUS_PARMS msp;
214
215/* Get Status from MCI */
216msp.hwndCallback = (HWND)NULL; /* None */
217msp.ulReturn = (ULONG)NULL; /* We want this information */
218msp.ulItem = MCI_STATUS_MODE;
219msp.ulValue = (ULONG)NULL; /* No additional information */
220if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;
221else
222 {
223 switch(msp.ulReturn)
224 {
225 case MCI_MODE_NOT_READY:
226 status = CD_TRAYEMPTY;
227 break;
228 case MCI_MODE_PAUSE:
229 status = CD_PAUSED;
230 break;
231 case MCI_MODE_PLAY:
232 status = CD_PLAYING;
233 break;
234 case MCI_MODE_STOP:
235 status = CD_STOPPED;
236 break;
237 /* These cases should not occour */
238 case MCI_MODE_RECORD:
239 case MCI_MODE_SEEK:
240 default:
241 status = CD_ERROR;
242 break;
243 }
244 }
245
246/* Determine position */
247if (position != NULL) /* The SDL $&$&%# CDROM call sends NULL pointer here! */
248 {
249 if ((status == CD_PLAYING) || (status == CD_PAUSED))
250 {
251 /* Get Position */
252 msp.hwndCallback = (HWND)NULL; /* None */
253 msp.ulReturn = (ULONG)NULL; /* We want this information */
254 msp.ulItem = MCI_STATUS_POSITION;
255 msp.ulValue = (ULONG)NULL; /* No additiona info */
256 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return (CD_ERROR);
257 /* Convert from MSF (format selected in the Open process) to Frames (format that will be returned) */
258 *position = MSF_TO_FRAMES(MSF_MINUTE(msp.ulReturn),MSF_SECOND(msp.ulReturn),MSF_FRAME(msp.ulReturn));
259 }
260 else *position = 0;
261 }
262return(status);
263}
264
265/* Start play - Ready for MCI */
266static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
267{
268MCI_GENERIC_PARMS mgp;
269MCI_STATUS_PARMS msp;
270MCI_PLAY_PARMS mpp;
271ULONG min,sec,frm;
272
273/* Start MSF */
274FRAMES_TO_MSF(start, &min, &sec, &frm);
275MSF_MINUTE(mpp.ulFrom) = min;
276MSF_SECOND(mpp.ulFrom) = sec;
277MSF_FRAME(mpp.ulFrom) = frm;
278/* End MSF */
279FRAMES_TO_MSF(start+length, &min, &sec, &frm);
280MSF_MINUTE(mpp.ulTo) = min;
281MSF_SECOND(mpp.ulTo) = sec;
282MSF_FRAME(mpp.ulTo) = frm;
283#ifdef DEBUG_CDROM
284 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
285 playtime.cdmsf_min0, playtime.cdmsf_sec0, playtime.cdmsf_frame0,
286 playtime.cdmsf_min1, playtime.cdmsf_sec1, playtime.cdmsf_frame1);
287#endif
288/* Verifies if it is paused first... and if it is, unpause before stopping it. */
289msp.hwndCallback = (HWND)NULL; /* None */
290msp.ulReturn = (ULONG)NULL; /* We want this information */
291msp.ulItem = MCI_STATUS_MODE;
292msp.ulValue = (ULONG)NULL; /* No additional information */
293if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
294 {
295 if (msp.ulReturn == MCI_MODE_PAUSE)
296 {
297 mgp.hwndCallback = (HWND)NULL; // None
298 mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0);
299 }
300 }
301/* Now play it. */
302mpp.hwndCallback = (HWND)NULL; // We do not want the info. temp
303if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;
304return (CD_ERROR);
305}
306
307/* Pause play - Ready for MCI */
308static int SDL_SYS_CDPause(SDL_CD *cdrom)
309{
310MCI_GENERIC_PARMS mgp;
311
312mgp.hwndCallback = (HWND)NULL; // None
313if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
314return(CD_ERROR);
315}
316
317/* Resume play - Ready for MCI */
318static int SDL_SYS_CDResume(SDL_CD *cdrom)
319{
320MCI_GENERIC_PARMS mgp;
321
322mgp.hwndCallback = (HWND)NULL; // None
323if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
324return(CD_ERROR);
325}
326
327/* Stop play - Ready for MCI */
328static int SDL_SYS_CDStop(SDL_CD *cdrom)
329{
330MCI_GENERIC_PARMS mgp;
331MCI_STATUS_PARMS msp;
332
333/* Verifies if it is paused first... and if it is, unpause before stopping it. */
334msp.hwndCallback = (HWND)NULL; /* None */
335msp.ulReturn = (ULONG)NULL; /* We want this information */
336msp.ulItem = MCI_STATUS_MODE;
337msp.ulValue = (ULONG)NULL; /* No additional information */
338if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) == MCIERR_SUCCESS)
339 {
340 if (msp.ulReturn == MCI_MODE_PAUSE)
341 {
342 mgp.hwndCallback = (HWND)NULL; // None
343 mciSendCommand(cdrom->id,MCI_RESUME,0,&mgp, 0);
344 }
345 }
346/* Now stops the media */
347mgp.hwndCallback = (HWND)NULL; // None
348if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
349return(CD_ERROR);
350}
351
352/* Eject the CD-ROM - Ready for MCI */
353static int SDL_SYS_CDEject(SDL_CD *cdrom)
354{
355MCI_SET_PARMS msp;
356
357msp.hwndCallback = (HWND)NULL; // None
358msp.ulTimeFormat = (ULONG)NULL; // No change
359msp.ulSpeedFormat = (ULONG)NULL; // No change
360msp.ulAudio = (ULONG)NULL; // No Channel
361msp.ulLevel = (ULONG)NULL; // No Volume
362msp.ulOver = (ULONG)NULL; // No Delay
363msp.ulItem = (ULONG)NULL; // No item
364msp.ulValue = (ULONG)NULL; // No value for item flag
365if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;
366return(CD_ERROR);
367}
368
369/* Close the CD-ROM handle - Ready for MCI */
370static void SDL_SYS_CDClose(SDL_CD *cdrom)
371{
372MCI_GENERIC_PARMS mgp;
373
374mgp.hwndCallback = (HWND)NULL; // None
375mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);
376}
377
378/* Finalize CDROM Subsystem - Ready for MCI */
379void SDL_SYS_CDQuit(void)
380{
381int i;
382
383if ( SDL_numcds > 0 )
384 {
385 for ( i=0; i<SDL_numcds; ++i )
386 {
387 SDL_free(SDL_cdlist[i]);
388 }
389 SDL_numcds = 0;
390 }
391}
392
393#endif /* SDL_CDROM_OS2 */