comparison src/cdrom/os2/SDL_syscdrom.c @ 1190:173c063d4f55

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