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