SDL-1.2.14
[sdl_omap.git] / src / cdrom / os2 / SDL_syscdrom.c
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 */
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 */
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*/
111 static const char *SDL_SYS_CDName(int drive)
112 {
113 return(SDL_cdlist[drive]);
114 }
115
116 /* Open CDAudio Device - Ready for MCI */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */