• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     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 */
42 static char *SDL_cdlist[MAX_DRIVES];
43 //static dev_t SDL_cdmode[MAX_DRIVES];
44 
45 /* The system-dependent CD control functions */
46 static const char *SDL_SYS_CDName(int drive);
47 static int SDL_SYS_CDOpen(int drive);
48 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
49 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
50 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
51 static int SDL_SYS_CDPause(SDL_CD *cdrom);
52 static int SDL_SYS_CDResume(SDL_CD *cdrom);
53 static int SDL_SYS_CDStop(SDL_CD *cdrom);
54 static int SDL_SYS_CDEject(SDL_CD *cdrom);
55 static 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 */
SDL_SYS_CDInit(void)63 int  SDL_SYS_CDInit(void)
64 {
65 int i; /* generig counter */
66 MCI_SYSINFO_PARMS		msp;	/* Structure to MCI SysInfo parameters */
67 CHAR 						SysInfoRet[MCI_CMDRETBUFSIZE];	/* Buffer for MCI Command result */
68 
69 /* Fill in our driver capabilities */
70 SDL_CDcaps.Name = SDL_SYS_CDName;
71 SDL_CDcaps.Open = SDL_SYS_CDOpen;
72 SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
73 SDL_CDcaps.Status = SDL_SYS_CDStatus;
74 SDL_CDcaps.Play = SDL_SYS_CDPlay;
75 SDL_CDcaps.Pause = SDL_SYS_CDPause;
76 SDL_CDcaps.Resume = SDL_SYS_CDResume;
77 SDL_CDcaps.Stop = SDL_SYS_CDStop;
78 SDL_CDcaps.Eject = SDL_SYS_CDEject;
79 SDL_CDcaps.Close = SDL_SYS_CDClose;
80 
81 /* Get the number of CD ROMs in the System */
82 /* Clean SysInfo structure */
83 SDL_memset(&msp, 0x00, sizeof(MCI_SYSINFO_PARMS));
84 /* Prepare structure to Ask Numer of Audio CDs */
85 msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO;	/* CD Audio Type */
86 msp.pszReturn = (PSZ)&SysInfoRet; 	/* Return Structure */
87 msp.ulRetSize = MCI_CMDRETBUFSIZE; 	/* Size of ret struct */
88 if (LOUSHORT(mciSendCommand(0,MCI_SYSINFO, MCI_SYSINFO_QUANTITY | MCI_WAIT, (PVOID)&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
89 SDL_numcds = atoi(SysInfoRet);
90 if (SDL_numcds > MAX_DRIVES) SDL_numcds = MAX_DRIVES; /* Limit maximum CD number */
91 
92 /* Get and Add their system name to the SDL_cdlist */
93 msp.pszReturn = (PSZ)&SysInfoRet; 				/* Return Structure */
94 msp.ulRetSize = MCI_CMDRETBUFSIZE; 			/* Size of ret struct */
95 msp.usDeviceType = MCI_DEVTYPE_CD_AUDIO;		/* CD Audio Type */
96 for (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 	}
107 return(0);
108 }
109 
110 /* Return CDAudio System Dependent Device Name - Ready for MCI*/
SDL_SYS_CDName(int drive)111 static const char *SDL_SYS_CDName(int drive)
112 {
113 return(SDL_cdlist[drive]);
114 }
115 
116 /* Open CDAudio Device - Ready for MCI */
SDL_SYS_CDOpen(int drive)117 static int SDL_SYS_CDOpen(int drive)
118 {
119 MCI_OPEN_PARMS	mop;
120 MCI_SET_PARMS msp;
121 MCI_GENERIC_PARMS mgp;
122 
123 /* Open the device */
124 mop.hwndCallback = (HWND)NULL;		// None
125 mop.usDeviceID = (USHORT)NULL;		// Will be returned.
126 mop.pszDeviceType = (PSZ)SDL_cdlist[drive];		// CDAudio Device
127 if (LOUSHORT(mciSendCommand(0,MCI_OPEN,MCI_WAIT,&mop, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
128 /* Set time format */
129 msp.hwndCallback = (HWND)NULL;		// None
130 msp.ulTimeFormat = MCI_FORMAT_MSF;	// Minute : Second : Frame structure
131 msp.ulSpeedFormat = (ULONG)NULL;		// No change
132 msp.ulAudio = (ULONG)NULL;				// No Channel
133 msp.ulLevel = (ULONG)NULL;				// No Volume
134 msp.ulOver = (ULONG)NULL;				// No Delay
135 msp.ulItem = (ULONG)NULL;				// No item
136 msp.ulValue = (ULONG)NULL;				// No value for item flag
137 if (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 */
139 mgp.hwndCallback = (HWND)NULL;		// None
140 mciSendCommand(mop.usDeviceID,MCI_CLOSE,MCI_WAIT,&mgp, 0);
141 return(CD_ERROR);
142 }
143 
144 /* Get CD Table Of Contents - Ready for MCI */
SDL_SYS_CDGetTOC(SDL_CD * cdrom)145 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
146 {
147 MCI_TOC_PARMS mtp;
148 MCI_STATUS_PARMS msp;
149 MCI_TOC_REC * mtr;
150 INT i;
151 
152 /* Correction because MCI cannot read TOC while CD is playing (it'll stop!) */
153 if (cdrom->status == CD_PLAYING || cdrom->status == CD_PAUSED) return 0;
154 
155 /* Get Number of Tracks */
156 msp.hwndCallback = (HWND)NULL; /* None */
157 msp.ulReturn = (ULONG)NULL; /* We want this information */
158 msp.ulItem = MCI_STATUS_NUMBER_OF_TRACKS;
159 msp.ulValue = (ULONG)NULL; /* No additional information */
160 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) return(CD_ERROR);
161 cdrom->numtracks = msp.ulReturn;
162 if ( cdrom->numtracks > SDL_MAX_TRACKS )
163 	{
164 	cdrom->numtracks = SDL_MAX_TRACKS;
165 	}
166 /* Alocate space for TOC data */
167 mtr = (MCI_TOC_REC *)SDL_malloc(cdrom->numtracks*sizeof(MCI_TOC_REC));
168 if ( mtr == NULL )
169 	{
170 	SDL_OutOfMemory();
171 	return(-1);
172 	}
173 /* Get TOC from CD */
174 mtp.pBuf = mtr;
175 mtp.ulBufSize = cdrom->numtracks*sizeof(MCI_TOC_REC);
176 if (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 */
183 for (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 	}
204 SDL_free(mtr);
205 return(0);
206 }
207 
208 
209 /* Get CD-ROM status - Ready for MCI */
SDL_SYS_CDStatus(SDL_CD * cdrom,int * position)210 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
211 {
212 CDstatus status;
213 MCI_STATUS_PARMS msp;
214 
215 /* Get Status from MCI */
216 msp.hwndCallback = (HWND)NULL; /* None */
217 msp.ulReturn = (ULONG)NULL; /* We want this information */
218 msp.ulItem = MCI_STATUS_MODE;
219 msp.ulValue = (ULONG)NULL; /* No additional information */
220 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STATUS,MCI_WAIT | MCI_STATUS_ITEM,&msp, 0)) != MCIERR_SUCCESS) status = CD_ERROR;
221 else
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 */
247 if (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 	}
262 return(status);
263 }
264 
265 /* Start play - Ready for MCI */
SDL_SYS_CDPlay(SDL_CD * cdrom,int start,int length)266 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
267 {
268 MCI_GENERIC_PARMS mgp;
269 MCI_STATUS_PARMS msp;
270 MCI_PLAY_PARMS	mpp;
271 ULONG min,sec,frm;
272 
273 /* Start MSF */
274 FRAMES_TO_MSF(start, &min, &sec, &frm);
275 MSF_MINUTE(mpp.ulFrom) = min;
276 MSF_SECOND(mpp.ulFrom) = sec;
277 MSF_FRAME(mpp.ulFrom) = frm;
278 /* End MSF */
279 FRAMES_TO_MSF(start+length, &min, &sec, &frm);
280 MSF_MINUTE(mpp.ulTo) = min;
281 MSF_SECOND(mpp.ulTo) = sec;
282 MSF_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. */
289 msp.hwndCallback = (HWND)NULL; /* None */
290 msp.ulReturn = (ULONG)NULL; /* We want this information */
291 msp.ulItem = MCI_STATUS_MODE;
292 msp.ulValue = (ULONG)NULL; /* No additional information */
293 if (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. */
302 mpp.hwndCallback = (HWND)NULL;		// We do not want the info. temp
303 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PLAY,MCI_FROM | MCI_TO,&mpp, 0)) == MCIERR_SUCCESS) return 0;
304 return (CD_ERROR);
305 }
306 
307 /* Pause play - Ready for MCI */
SDL_SYS_CDPause(SDL_CD * cdrom)308 static int SDL_SYS_CDPause(SDL_CD *cdrom)
309 {
310 MCI_GENERIC_PARMS mgp;
311 
312 mgp.hwndCallback = (HWND)NULL;		// None
313 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_PAUSE,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
314 return(CD_ERROR);
315 }
316 
317 /* Resume play - Ready for MCI */
SDL_SYS_CDResume(SDL_CD * cdrom)318 static int SDL_SYS_CDResume(SDL_CD *cdrom)
319 {
320 MCI_GENERIC_PARMS mgp;
321 
322 mgp.hwndCallback = (HWND)NULL;		// None
323 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_RESUME,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
324 return(CD_ERROR);
325 }
326 
327 /* Stop play - Ready for MCI */
SDL_SYS_CDStop(SDL_CD * cdrom)328 static int SDL_SYS_CDStop(SDL_CD *cdrom)
329 {
330 MCI_GENERIC_PARMS mgp;
331 MCI_STATUS_PARMS msp;
332 
333 /* Verifies if it is paused first... and if it is, unpause before stopping it. */
334 msp.hwndCallback = (HWND)NULL; /* None */
335 msp.ulReturn = (ULONG)NULL; /* We want this information */
336 msp.ulItem = MCI_STATUS_MODE;
337 msp.ulValue = (ULONG)NULL; /* No additional information */
338 if (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 */
347 mgp.hwndCallback = (HWND)NULL;		// None
348 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_STOP,MCI_WAIT,&mgp, 0)) == MCIERR_SUCCESS) return 0;
349 return(CD_ERROR);
350 }
351 
352 /* Eject the CD-ROM - Ready for MCI */
SDL_SYS_CDEject(SDL_CD * cdrom)353 static int SDL_SYS_CDEject(SDL_CD *cdrom)
354 {
355 MCI_SET_PARMS msp;
356 
357 msp.hwndCallback = (HWND)NULL;		// None
358 msp.ulTimeFormat = (ULONG)NULL;		// No change
359 msp.ulSpeedFormat = (ULONG)NULL;		// No change
360 msp.ulAudio = (ULONG)NULL;				// No Channel
361 msp.ulLevel = (ULONG)NULL;				// No Volume
362 msp.ulOver = (ULONG)NULL;				// No Delay
363 msp.ulItem = (ULONG)NULL;					// No item
364 msp.ulValue = (ULONG)NULL;					// No value for item flag
365 if (LOUSHORT(mciSendCommand(cdrom->id,MCI_SET,MCI_WAIT | MCI_SET_DOOR_OPEN,&msp, 0)) == MCIERR_SUCCESS) return 0;
366 return(CD_ERROR);
367 }
368 
369 /* Close the CD-ROM handle - Ready for MCI */
SDL_SYS_CDClose(SDL_CD * cdrom)370 static void SDL_SYS_CDClose(SDL_CD *cdrom)
371 {
372 MCI_GENERIC_PARMS mgp;
373 
374 mgp.hwndCallback = (HWND)NULL;		// None
375 mciSendCommand(cdrom->id,MCI_CLOSE,MCI_WAIT,&mgp, 0);
376 }
377 
378 /* Finalize CDROM Subsystem - Ready for MCI */
SDL_SYS_CDQuit(void)379 void SDL_SYS_CDQuit(void)
380 {
381 int i;
382 
383 if ( 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 */
394