Release 980601
[wine] / multimedia / mcicda.c
1 /*
2  * Sample MCI CDAUDIO Wine Driver for Linux
3  *
4  * Copyright 1994 Martin Ayotte
5  */
6
7 #include <stdlib.h>
8 #include <unistd.h>
9 #include <string.h>
10 #include <fcntl.h>
11 #include <sys/ioctl.h>
12 #include "windows.h"
13 #include "user.h"
14 #include "driver.h"
15 #include "mmsystem.h"
16 #include "debug.h"
17
18 #ifdef HAVE_LINUX_CDROM_H
19 # include <linux/cdrom.h>
20 #endif
21 #ifdef HAVE_MACHINE_SOUNDCARD_H
22 # include <machine/soundcard.h>
23 #endif
24 #ifdef HAVE_SYS_CDIO_H
25 # include <sys/cdio.h>
26 #endif
27
28 #ifdef __FreeBSD__
29 # define CDAUDIO_DEV "/dev/rcd0c"
30 #else
31 # define CDAUDIO_DEV "/dev/cdrom"
32 #endif
33
34 #ifdef SOUND_VERSION
35 # define IOCTL(a,b,c)           ioctl(a,b,&c)
36 #else
37 # define IOCTL(a,b,c)           (c = ioctl(a,b,c) )
38 #endif
39
40 #define MAX_CDAUDIODRV          (1)
41 #define MAX_CDAUDIO_TRACKS      256
42
43 #define CDFRAMES_PERSEC         75
44 #define CDFRAMES_PERMIN         4500
45 #define SECONDS_PERMIN          60
46
47 #if defined(linux) || defined(__FreeBSD__)
48 typedef struct {
49     int     nUseCount;          /* Incremented for each shared open */
50     BOOL16  fShareable;         /* TRUE if first open was shareable */
51     WORD    wNotifyDeviceID;    /* MCI device ID with a pending notification */
52     HANDLE16 hCallback;          /* Callback handle for pending notification */
53         MCI_OPEN_PARMS16 openParms;
54         DWORD   dwTimeFormat;
55         int             unixdev;
56 #ifdef linux
57         struct cdrom_subchnl    sc;
58 #elif __FreeBSD__
59         struct cd_sub_channel_info      sc;
60 #endif
61         int             mode;
62         UINT16  nCurTrack;
63         DWORD   dwCurFrame;
64         UINT16  nTracks;
65         DWORD   dwTotalLen;
66         LPDWORD lpdwTrackLen;
67         LPDWORD lpdwTrackPos;
68         DWORD   dwFirstOffset;
69         } LINUX_CDAUDIO;
70
71 static LINUX_CDAUDIO    CDADev[MAX_CDAUDIODRV];
72 #endif
73
74
75 /*-----------------------------------------------------------------------*/
76
77
78 /**************************************************************************
79 *                               CDAUDIO_GetNumberOfTracks               [internal]
80 */
81 static UINT16 CDAUDIO_GetNumberOfTracks(UINT16 wDevID)
82 {
83 #if defined(linux) || defined(__FreeBSD__)
84 #ifdef linux
85         struct cdrom_tochdr     hdr;
86 #elif __FreeBSD__
87         struct ioc_toc_header   hdr;
88 #endif
89
90         if (CDADev[wDevID].nTracks == 0) {
91                 if (ioctl(CDADev[wDevID].unixdev,
92 #ifdef linux
93                           CDROMREADTOCHDR
94 #elif __FreeBSD__
95                           CDIOREADTOCHEADER
96 #endif
97                           , &hdr)) {
98                         WARN(cdaudio, "(%04X) -- Error occured !\n", 
99                                      wDevID);
100                         return (WORD)-1;
101                         }
102 #ifdef linux
103                 CDADev[wDevID].nTracks = hdr.cdth_trk1;
104 #elif __FreeBSD__
105                 CDADev[wDevID].nTracks = hdr.ending_track - hdr.starting_track + 1;
106 #endif
107                 }
108         return CDADev[wDevID].nTracks;
109 #else
110         return (WORD)-1;
111 #endif
112 }
113
114
115 /**************************************************************************
116 *                               CDAUDIO_GetTracksInfo                   [internal]
117 */
118 static BOOL32 CDAUDIO_GetTracksInfo(UINT16 wDevID)
119 {
120 #if defined(linux) || defined(__FreeBSD__)
121         int             i, length;
122         int             start, last_start = 0;
123         int             total_length = 0;
124 #ifdef linux
125         struct cdrom_tocentry   entry;
126 #elif __FreeBSD__
127         struct ioc_read_toc_entry       entry;
128         struct cd_toc_entry             toc_buffer;
129 #endif
130
131         if (CDADev[wDevID].nTracks == 0) {
132                 if (CDAUDIO_GetNumberOfTracks(wDevID) == (WORD)-1) return FALSE;
133                 }
134         TRACE(cdaudio,"nTracks=%u\n", 
135                 CDADev[wDevID].nTracks);
136         if (CDADev[wDevID].lpdwTrackLen != NULL) 
137                 free(CDADev[wDevID].lpdwTrackLen);
138         CDADev[wDevID].lpdwTrackLen = (LPDWORD)malloc(
139                 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
140         if (CDADev[wDevID].lpdwTrackPos != NULL) 
141                 free(CDADev[wDevID].lpdwTrackPos);
142         CDADev[wDevID].lpdwTrackPos = (LPDWORD)malloc(
143                 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
144         if (CDADev[wDevID].lpdwTrackLen == NULL ||
145                 CDADev[wDevID].lpdwTrackPos == NULL) {
146                         WARN(cdaudio, "error allocating track table !\n");
147                 return FALSE;
148                 }
149         memset(CDADev[wDevID].lpdwTrackLen, 0, 
150                 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
151         memset(CDADev[wDevID].lpdwTrackPos, 0, 
152                 (CDADev[wDevID].nTracks + 1) * sizeof(DWORD));
153         for (i = 0; i <= CDADev[wDevID].nTracks; i++) {
154                 if (i == CDADev[wDevID].nTracks)
155 #ifdef linux
156                         entry.cdte_track = CDROM_LEADOUT;
157 #elif __FreeBSD__
158 #define LEADOUT 0xaa
159                         entry.starting_track = LEADOUT; /* XXX */
160 #endif
161                 else
162 #ifdef linux
163                         entry.cdte_track = i + 1;
164 #elif __FreeBSD__
165                         entry.starting_track = i + 1;
166 #endif
167 #ifdef linux
168                 entry.cdte_format = CDROM_MSF;
169 #elif __FreeBSD__
170                 bzero((char *)&toc_buffer, sizeof(toc_buffer));
171                 entry.address_format = CD_MSF_FORMAT;
172                 entry.data_len = sizeof(toc_buffer);
173                 entry.data = &toc_buffer;
174 #endif
175                 if (ioctl(CDADev[wDevID].unixdev, 
176 #ifdef linux
177                           CDROMREADTOCENTRY
178 #elif __FreeBSD__
179                           CDIOREADTOCENTRYS
180 #endif
181                           , &entry)) {
182                         WARN(cdaudio, "error read entry\n");
183                         return FALSE;
184                         }
185 #ifdef linux
186                 start = CDFRAMES_PERSEC * (SECONDS_PERMIN * 
187                         entry.cdte_addr.msf.minute + entry.cdte_addr.msf.second) + 
188                         entry.cdte_addr.msf.frame;
189 #elif __FreeBSD__
190                 start = CDFRAMES_PERSEC * (SECONDS_PERMIN *
191                         toc_buffer.addr.msf.minute + toc_buffer.addr.msf.second) +
192                         toc_buffer.addr.msf.frame;
193 #endif
194                 if (i == 0) {
195                         last_start = start;
196                         CDADev[wDevID].dwFirstOffset = start;
197                         TRACE(cdaudio, "dwFirstOffset=%u\n", 
198                                 start);
199                         }
200                 else {
201                         length = start - last_start;
202                         last_start = start;
203                         start = last_start - length;
204                         total_length += length;
205                         CDADev[wDevID].lpdwTrackLen[i - 1] = length;
206                         CDADev[wDevID].lpdwTrackPos[i - 1] = start;
207                         TRACE(cdaudio, "track #%u start=%u len=%u\n",
208                                      i, start, length);
209                         }
210                 }
211         CDADev[wDevID].dwTotalLen = total_length;
212         TRACE(cdaudio,"total_len=%u\n", 
213                 total_length);
214         return TRUE;
215 #else
216         return FALSE;
217 #endif
218 }
219
220
221 /**************************************************************************
222 *                               CDAUDIO_mciOpen                 [internal]
223 */
224 static DWORD CDAUDIO_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS16 lpParms)
225 {
226 #if defined(linux) || defined(__FreeBSD__)
227         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
228                                         wDevID, dwFlags, lpParms);
229         if (lpParms == NULL) return MCIERR_INTERNAL;
230
231         if (CDADev[wDevID].nUseCount > 0) {
232                 /* The driver already open on this channel */
233                 /* If the driver was opened shareable before and this open specifies */
234                 /* shareable then increment the use count */
235                 if (CDADev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
236                         ++CDADev[wDevID].nUseCount;
237                 else
238                         return MCIERR_MUST_USE_SHAREABLE;
239                 }
240         else {
241                 CDADev[wDevID].nUseCount = 1;
242                 CDADev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
243                 }
244     if (dwFlags & MCI_OPEN_ELEMENT) {
245                 TRACE(cdaudio,"MCI_OPEN_ELEMENT !\n");
246 /*              return MCIERR_NO_ELEMENT_ALLOWED; */
247                 }
248         memcpy(&CDADev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS16));
249         CDADev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
250         CDADev[wDevID].unixdev = open (CDAUDIO_DEV, O_RDONLY, 0);
251         if (CDADev[wDevID].unixdev == -1) {
252                 WARN(cdaudio,"can't open '%s' !\n", CDAUDIO_DEV);
253                 return MCIERR_HARDWARE;
254                 }
255         CDADev[wDevID].mode = 0;
256         CDADev[wDevID].dwTimeFormat = MCI_FORMAT_TMSF;
257         CDADev[wDevID].nCurTrack = 0;
258         CDADev[wDevID].nTracks = 0;
259         CDADev[wDevID].dwTotalLen = 0;
260         CDADev[wDevID].dwFirstOffset = 0;
261         CDADev[wDevID].lpdwTrackLen = NULL;
262         CDADev[wDevID].lpdwTrackPos = NULL;
263         if (!CDAUDIO_GetTracksInfo(wDevID)) {
264                 WARN(cdaudio,"error reading TracksInfo !\n");
265 /*              return MCIERR_INTERNAL; */
266                 }
267
268 /*
269    Moved to mmsystem.c mciOpen routine
270
271         if (dwFlags & MCI_NOTIFY) {
272                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
273                         lpParms->dwCallback);
274                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
275                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
276                 }
277 */
278         return 0;
279 #else
280         return MCIERR_HARDWARE;
281 #endif
282 }
283
284 /**************************************************************************
285 *                               CDAUDIO_mciClose                [internal]
286 */
287 static DWORD CDAUDIO_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
288 {
289 #if defined(linux) || defined(__FreeBSD__)
290         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
291                 wDevID, dwParam, lpParms);
292         if (CDADev[wDevID].lpdwTrackLen != NULL) free(CDADev[wDevID].lpdwTrackLen);
293         if (CDADev[wDevID].lpdwTrackPos != NULL) free(CDADev[wDevID].lpdwTrackPos);
294         close(CDADev[wDevID].unixdev);
295 #endif
296         return 0;
297 }
298
299 /**************************************************************************
300 *                               CDAUDIO_mciGetDevCaps   [internal]
301 */
302 static DWORD CDAUDIO_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags, 
303                                                 LPMCI_GETDEVCAPS_PARMS lpParms)
304 {
305 #if defined(linux) || defined(__FreeBSD__)
306         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
307                 wDevID, dwFlags, lpParms);
308         if (lpParms == NULL) return MCIERR_INTERNAL;
309         if (dwFlags & MCI_GETDEVCAPS_ITEM) {
310                 TRACE(cdaudio, "MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n",
311                              lpParms->dwItem);
312                 switch(lpParms->dwItem) {
313                         case MCI_GETDEVCAPS_CAN_RECORD:
314                                 lpParms->dwReturn = FALSE;
315                                 break;
316                         case MCI_GETDEVCAPS_HAS_AUDIO:
317                                 lpParms->dwReturn = TRUE;
318                                 break;
319                         case MCI_GETDEVCAPS_HAS_VIDEO:
320                                 lpParms->dwReturn = FALSE;
321                                 break;
322                         case MCI_GETDEVCAPS_DEVICE_TYPE:
323                                 lpParms->dwReturn = MCI_DEVTYPE_CD_AUDIO;
324                                 break;
325                         case MCI_GETDEVCAPS_USES_FILES:
326                                 lpParms->dwReturn = FALSE;
327                                 break;
328                         case MCI_GETDEVCAPS_COMPOUND_DEVICE:
329                                 lpParms->dwReturn = FALSE;
330                                 break;
331                         case MCI_GETDEVCAPS_CAN_EJECT:
332                                 lpParms->dwReturn = TRUE;
333                                 break;
334                         case MCI_GETDEVCAPS_CAN_PLAY:
335                                 lpParms->dwReturn = TRUE;
336                                 break;
337                         case MCI_GETDEVCAPS_CAN_SAVE:
338                                 lpParms->dwReturn = FALSE;
339                                 break;
340                         default:
341                                 return MCIERR_UNRECOGNIZED_COMMAND;
342                         }
343                 }
344         TRACE(cdaudio, "lpParms->dwReturn=%08lX;\n", 
345                 lpParms->dwReturn);
346         return 0;
347 #else
348         return MCIERR_INTERNAL;
349 #endif
350 }
351
352 /**************************************************************************
353 *                               CDAUDIO_mciInfo                 [internal]
354 */
355 static DWORD CDAUDIO_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
356 {
357 #if defined(linux) || defined(__FreeBSD__)
358         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
359                 wDevID, dwFlags, lpParms);
360         if (lpParms == NULL) return MCIERR_INTERNAL;
361         lpParms->lpstrReturn = NULL;
362         switch(dwFlags) {
363                 case MCI_INFO_PRODUCT:
364                         lpParms->lpstrReturn = "Linux CDROM 0.5";
365                         break;
366                 default:
367                         return MCIERR_UNRECOGNIZED_COMMAND;
368                 }
369         if (lpParms->lpstrReturn != NULL)
370                 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
371         else
372                 lpParms->dwRetSize = 0;
373         return 0;
374 #else
375         return MCIERR_INTERNAL;
376 #endif
377 }
378
379
380 /**************************************************************************
381 *                               CDAUDIO_CalcFrame                       [internal]
382 */
383 static DWORD CDAUDIO_CalcFrame(UINT16 wDevID, DWORD dwFormatType, DWORD dwTime)
384 {
385         DWORD   dwFrame = 0;
386 #if defined(linux) || defined(__FreeBSD__)
387         UINT16  wTrack;
388     
389         TRACE(cdaudio,"(%04X, %08lX, %lu);\n", 
390                 wDevID, dwFormatType, dwTime);
391     
392         switch (dwFormatType) {
393                 case MCI_FORMAT_MILLISECONDS:
394                         dwFrame = dwTime * CDFRAMES_PERSEC / 1000;
395                         TRACE(cdaudio, "MILLISECONDS %lu\n", 
396                                 dwFrame);
397                         break;
398                 case MCI_FORMAT_MSF:
399                         TRACE(cdaudio, "MSF %02u:%02u:%02u\n",
400                                 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), 
401                                 MCI_MSF_FRAME(dwTime));
402                         dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
403                         dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
404                         dwFrame += MCI_MSF_FRAME(dwTime);
405                         break;
406                 default:
407                         /* unknown format ! force TMSF ! ... */
408                         dwFormatType = MCI_FORMAT_TMSF;
409                 case MCI_FORMAT_TMSF:
410                         wTrack = MCI_TMSF_TRACK(dwTime);
411                         TRACE(cdaudio, "MSF %02u-%02u:%02u:%02u\n",
412                                         MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime), 
413                                         MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
414                         TRACE(cdaudio, "TMSF trackpos[%u]=%lu\n",
415                                 wTrack, CDADev[wDevID].lpdwTrackPos[wTrack - 1]);
416                         dwFrame = CDADev[wDevID].lpdwTrackPos[wTrack - 1];
417                         dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
418                         dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
419                         dwFrame += MCI_TMSF_FRAME(dwTime);
420                         break;
421                 }
422 #endif
423         return dwFrame;
424 }
425
426
427 /**************************************************************************
428 *                               CDAUDIO_GetCDStatus                             [internal]
429 */
430 static BOOL32 CDAUDIO_GetCDStatus(UINT16 wDevID)
431 {
432 #if defined(linux) || defined(__FreeBSD__)
433         int             oldmode = CDADev[wDevID].mode;
434 #ifdef __FreeBSD__
435         struct ioc_read_subchannel      read_sc;
436
437         read_sc.address_format = CD_MSF_FORMAT;
438         read_sc.data_format    = CD_CURRENT_POSITION;
439         read_sc.track          = 0;
440         read_sc.data_len       = sizeof(CDADev[wDevID].sc);
441         read_sc.data           = (struct cd_sub_channel_info *)&CDADev[wDevID].sc;
442 #elif linux
443         CDADev[wDevID].sc.cdsc_format = CDROM_MSF;
444 #endif
445         if (ioctl(CDADev[wDevID].unixdev,
446 #ifdef linux
447                   CDROMSUBCHNL, &CDADev[wDevID].sc
448 #elif __FreeBSD__
449                   CDIOCREADSUBCHANNEL, &read_sc
450 #endif
451                   )) {
452                 TRACE(cdaudio,"opened or no_media !\n");
453                 CDADev[wDevID].mode = MCI_MODE_NOT_READY;
454                 return TRUE;
455                 }
456         switch (
457 #ifdef linux
458                 CDADev[wDevID].sc.cdsc_audiostatus
459 #elif __FreeBSD__
460                 CDADev[wDevID].sc.header.audio_status
461 #endif
462                 ) {
463 #ifdef linux
464                 case CDROM_AUDIO_INVALID:
465 #elif __FreeBSD__
466                 case CD_AS_AUDIO_INVALID:
467 #endif
468                         WARN(cdaudio, "device doesn't support status, returning NOT_READY.\n");
469 #ifdef linux
470                         CDADev[wDevID].mode = MCI_MODE_NOT_READY;
471 #elif __FreeBSD__
472                         CDADev[wDevID].mode = MCI_MODE_STOP;
473 #endif
474                         break;
475 #ifdef linux
476                 case CDROM_AUDIO_NO_STATUS: 
477 #elif __FreeBSD__
478                 case CD_AS_NO_STATUS:
479 #endif
480                         CDADev[wDevID].mode = MCI_MODE_STOP;
481                         TRACE(cdaudio,"MCI_MODE_STOP !\n");
482                         break;
483 #ifdef linux
484                 case CDROM_AUDIO_PLAY: 
485 #elif __FreeBSD__
486                 case CD_AS_PLAY_IN_PROGRESS:
487 #endif
488                         CDADev[wDevID].mode = MCI_MODE_PLAY;
489                         TRACE(cdaudio,"MCI_MODE_PLAY !\n");
490                         break;
491 #ifdef linux
492                 case CDROM_AUDIO_PAUSED:
493 #elif __FreeBSD__
494                 case CD_AS_PLAY_PAUSED:
495 #endif
496                         CDADev[wDevID].mode = MCI_MODE_PAUSE;
497                         TRACE(cdaudio,"MCI_MODE_PAUSE !\n");
498                         break;
499                 default:
500 #ifdef linux
501                         TRACE(cdaudio,"status=%02X !\n",
502                                      CDADev[wDevID].sc.cdsc_audiostatus);
503 #elif __FreeBSD__
504                         TRACE(cdaudio,"status=%02X !\n",
505                                      CDADev[wDevID].sc.header.audio_status);
506 #endif
507                 }
508 #ifdef linux
509         CDADev[wDevID].nCurTrack = CDADev[wDevID].sc.cdsc_trk;
510         CDADev[wDevID].dwCurFrame = 
511                 CDFRAMES_PERMIN * CDADev[wDevID].sc.cdsc_absaddr.msf.minute +
512                 CDFRAMES_PERSEC * CDADev[wDevID].sc.cdsc_absaddr.msf.second +
513                 CDADev[wDevID].sc.cdsc_absaddr.msf.frame;
514 #elif __FreeBSD__
515         CDADev[wDevID].nCurTrack = CDADev[wDevID].sc.what.position.track_number;
516         CDADev[wDevID].dwCurFrame = 
517                 CDFRAMES_PERMIN * CDADev[wDevID].sc.what.position.absaddr.msf.minute +
518                 CDFRAMES_PERSEC * CDADev[wDevID].sc.what.position.absaddr.msf.second +
519                 CDADev[wDevID].sc.what.position.absaddr.msf.frame;
520 #endif
521 #ifdef linux
522         TRACE(cdaudio,"%02u-%02u:%02u:%02u \n",
523                      CDADev[wDevID].sc.cdsc_trk,
524                      CDADev[wDevID].sc.cdsc_absaddr.msf.minute,
525                      CDADev[wDevID].sc.cdsc_absaddr.msf.second,
526                      CDADev[wDevID].sc.cdsc_absaddr.msf.frame);
527 #elif __FreeBSD__
528         TRACE(cdaudio,"%02u-%02u:%02u:%02u \n",
529                      CDADev[wDevID].sc.what.position.track_number,
530                      CDADev[wDevID].sc.what.position.absaddr.msf.minute,
531                      CDADev[wDevID].sc.what.position.absaddr.msf.second,
532                      CDADev[wDevID].sc.what.position.absaddr.msf.frame);
533 #endif
534                         
535         if (oldmode != CDADev[wDevID].mode && oldmode == MCI_MODE_OPEN) {
536                 if (!CDAUDIO_GetTracksInfo(wDevID)) {
537                   WARN(cdaudio, "error updating TracksInfo !\n");
538                         return MCIERR_INTERNAL;
539                         }
540                 }
541         return TRUE;
542 #else
543         return FALSE;
544 #endif
545 }
546
547
548 /**************************************************************************
549 *                               CDAUDIO_CalcTime                        [internal]
550 */
551 static DWORD CDAUDIO_CalcTime(UINT16 wDevID, DWORD dwFormatType, DWORD dwFrame)
552 {
553         DWORD   dwTime = 0;
554 #if defined(linux) || defined(__FreeBSD__)
555         UINT16  wTrack;
556         UINT16  wMinutes;
557         UINT16  wSeconds;
558         UINT16  wFrames;
559
560         TRACE(cdaudio,"(%04X, %08lX, %lu);\n", 
561                 wDevID, dwFormatType, dwFrame);
562
563         switch (dwFormatType) {
564                 case MCI_FORMAT_MILLISECONDS:
565                         dwTime = dwFrame / CDFRAMES_PERSEC * 1000;
566                         TRACE(cdaudio, "MILLISECONDS %lu\n", 
567                                 dwTime);
568                         break;
569                 case MCI_FORMAT_MSF:
570                         wMinutes = dwFrame / CDFRAMES_PERMIN;
571                         wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
572                         wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - 
573                                                                 CDFRAMES_PERSEC * wSeconds;
574                         dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
575                         TRACE(cdaudio,"MSF %02u:%02u:%02u -> dwTime=%lu\n",
576                                                                 wMinutes, wSeconds, wFrames, dwTime);
577                         break;
578                 default:
579                         /* unknown format ! force TMSF ! ... */
580                         dwFormatType = MCI_FORMAT_TMSF;
581                 case MCI_FORMAT_TMSF:
582                         for (wTrack = 0; wTrack < CDADev[wDevID].nTracks; wTrack++) {
583 /*                              dwTime += CDADev[wDevID].lpdwTrackLen[wTrack - 1];
584                                 TRACE(cdaudio, "Adding trk#%u curpos=%u \n", dwTime);
585                                 if (dwTime >= dwFrame) break; */
586                                 if (CDADev[wDevID].lpdwTrackPos[wTrack - 1] >= dwFrame) break;
587                                 }
588                         wMinutes = dwFrame / CDFRAMES_PERMIN;
589                         wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
590                         wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - 
591                                                                 CDFRAMES_PERSEC * wSeconds;
592                         dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
593                         TRACE(cdaudio, "%02u-%02u:%02u:%02u\n",
594                                         wTrack, wMinutes, wSeconds, wFrames);
595                         break;
596                 }
597 #endif
598         return dwTime;
599 }
600
601
602 /**************************************************************************
603 *                               CDAUDIO_mciStatus               [internal]
604 */
605 static DWORD CDAUDIO_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
606 {
607 #if defined(linux) || defined(__FreeBSD__)
608         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
609                 wDevID, dwFlags, lpParms);
610         if (lpParms == NULL) return MCIERR_INTERNAL;
611         if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED;
612         if (dwFlags & MCI_NOTIFY) {
613                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
614                         lpParms->dwCallback);
615                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
616                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
617                 }
618         if (dwFlags & MCI_STATUS_ITEM) {
619                 switch(lpParms->dwItem) {
620                         case MCI_STATUS_CURRENT_TRACK:
621                                 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
622                                 lpParms->dwReturn = CDADev[wDevID].nCurTrack;
623                                 TRACE(cdaudio,"CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
624                                 return 0;
625                         case MCI_STATUS_LENGTH:
626                                 if (CDADev[wDevID].nTracks == 0) {
627                                         if (!CDAUDIO_GetTracksInfo(wDevID)) {
628                                                 WARN(cdaudio, "error reading TracksInfo !\n");
629                                                 return MCIERR_INTERNAL;
630                                                 }
631                                         }
632                                 if (dwFlags & MCI_TRACK) {
633                                         TRACE(cdaudio,"MCI_TRACK #%lu LENGTH=??? !\n",
634                                                         lpParms->dwTrack);
635                                         if (lpParms->dwTrack > CDADev[wDevID].nTracks)
636                                                 return MCIERR_OUTOFRANGE;
637                                         lpParms->dwReturn = CDADev[wDevID].lpdwTrackLen[lpParms->dwTrack];
638                                         }
639                                 else
640                                         lpParms->dwReturn = CDADev[wDevID].dwTotalLen;
641                                 lpParms->dwReturn = CDAUDIO_CalcTime(wDevID, 
642                                         CDADev[wDevID].dwTimeFormat, lpParms->dwReturn);
643                                 TRACE(cdaudio,"LENGTH=%lu !\n", lpParms->dwReturn);
644                                 return 0;
645                         case MCI_STATUS_MODE:
646                                 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
647                                 lpParms->dwReturn = CDADev[wDevID].mode;
648                                 TRACE(cdaudio,"MCI_STATUS_MODE=%08lX !\n",
649                                                                                                 lpParms->dwReturn);
650                                 return 0;
651                         case MCI_STATUS_MEDIA_PRESENT:
652                                 lpParms->dwReturn = (CDADev[wDevID].nTracks > 0) ? TRUE : FALSE;
653                                 if (lpParms->dwReturn == FALSE)
654                                         TRACE(cdaudio,"MEDIA_NOT_PRESENT !\n");
655                                 else
656                                         TRACE(cdaudio,"MCI_STATUS_MEDIA_PRESENT !\n");
657                                 return 0;
658                         case MCI_STATUS_NUMBER_OF_TRACKS:
659                                 lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(wDevID);
660                                 TRACE(cdaudio,"MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n",
661                                                                                                         lpParms->dwReturn);
662                                 if (lpParms->dwReturn == (WORD)-1) return MCIERR_INTERNAL;
663                                 return 0;
664                         case MCI_STATUS_POSITION:
665                                 if (!CDAUDIO_GetCDStatus(wDevID)) return MCIERR_INTERNAL;
666                                 lpParms->dwReturn = CDADev[wDevID].dwCurFrame;
667                                 if (dwFlags & MCI_STATUS_START) {
668                                         lpParms->dwReturn = CDADev[wDevID].dwFirstOffset;
669                                         TRACE(cdaudio,"get MCI_STATUS_START !\n");
670                                         }
671                                 if (dwFlags & MCI_TRACK) {
672                                         if (lpParms->dwTrack > CDADev[wDevID].nTracks)
673                                                 return MCIERR_OUTOFRANGE;
674                                         lpParms->dwReturn = CDADev[wDevID].lpdwTrackPos[lpParms->dwTrack - 1];
675                                         TRACE(cdaudio,"get MCI_TRACK #%lu !\n", lpParms->dwTrack);
676                                         }
677                                 lpParms->dwReturn = CDAUDIO_CalcTime(wDevID,
678                                         CDADev[wDevID].dwTimeFormat, lpParms->dwReturn);
679                                         TRACE(cdaudio,"MCI_STATUS_POSITION=%08lX !\n",
680                                                                                                                 lpParms->dwReturn);
681                                 return 0;
682                         case MCI_STATUS_READY:
683                                 TRACE(cdaudio,"MCI_STATUS_READY !\n");
684                                 lpParms->dwReturn = TRUE;
685                                 return 0;
686                         case MCI_STATUS_TIME_FORMAT:
687                                 TRACE(cdaudio,"MCI_STATUS_TIME_FORMAT !\n");
688                                 lpParms->dwReturn = CDADev[wDevID].dwTimeFormat;
689                                 return 0;
690                         default:
691                                 WARN(cdaudio, "unknown command %08lX !\n", lpParms->dwItem);
692                                 return MCIERR_UNRECOGNIZED_COMMAND;
693                         }
694                 }
695         WARN(cdaudio, "not MCI_STATUS_ITEM !\n");
696         return 0;
697 #else
698         return MMSYSERR_NOTENABLED;
699 #endif
700 }
701
702
703 /**************************************************************************
704 *                               CDAUDIO_mciPlay                 [internal]
705 */
706 static DWORD CDAUDIO_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
707 {
708 #if defined(linux) || defined(__FreeBSD__)
709         int     start, end;
710 #ifdef linux
711         struct  cdrom_msf       msf;
712 #elif __FreeBSD__
713         struct  ioc_play_msf    msf;
714 #endif
715
716         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
717                 wDevID, dwFlags, lpParms);
718         if (lpParms == NULL) return MCIERR_INTERNAL;
719         if (CDADev[wDevID].unixdev == 0) return MMSYSERR_NOTENABLED;
720         start = 0;              end = CDADev[wDevID].dwTotalLen;
721         CDADev[wDevID].nCurTrack = 1;
722         if (dwFlags & MCI_FROM) {
723                 start = CDAUDIO_CalcFrame(wDevID, 
724                         CDADev[wDevID].dwTimeFormat, lpParms->dwFrom); 
725         TRACE(cdaudio,"MCI_FROM=%08lX -> %u \n",
726                                 lpParms->dwFrom, start);
727                 }
728         if (dwFlags & MCI_TO) {
729                 end = CDAUDIO_CalcFrame(wDevID, 
730                         CDADev[wDevID].dwTimeFormat, lpParms->dwTo);
731                 TRACE(cdaudio, "MCI_TO=%08lX -> %u \n",
732                         lpParms->dwTo, end);
733                 }
734         start += CDADev[wDevID].dwFirstOffset;  
735         end += CDADev[wDevID].dwFirstOffset;
736 #ifdef linux
737         msf.cdmsf_min0 = start / CDFRAMES_PERMIN;
738         msf.cdmsf_sec0 = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
739         msf.cdmsf_frame0 = start % CDFRAMES_PERSEC;
740         msf.cdmsf_min1 = end / CDFRAMES_PERMIN;
741         msf.cdmsf_sec1 = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
742         msf.cdmsf_frame1 = end % CDFRAMES_PERSEC;
743 #elif __FreeBSD__
744         msf.start_m     = start / CDFRAMES_PERMIN;
745         msf.start_s     = (start % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
746         msf.start_f     = start % CDFRAMES_PERSEC;
747         msf.end_m       = end / CDFRAMES_PERMIN;
748         msf.end_s       = (end % CDFRAMES_PERMIN) / CDFRAMES_PERSEC;
749         msf.end_f       = end % CDFRAMES_PERSEC;
750 #endif
751         if (ioctl(CDADev[wDevID].unixdev,
752 #ifdef linux
753                   CDROMSTART
754 #elif __FreeBSD__
755                   CDIOCSTART
756 #endif
757                   )) {
758                 WARN(cdaudio, "motor doesn't start !\n");
759                 return MCIERR_HARDWARE;
760                 }
761         if (ioctl(CDADev[wDevID].unixdev, 
762 #ifdef linux
763                   CDROMPLAYMSF
764 #elif __FreeBSD__
765                   CDIOCPLAYMSF
766 #endif
767                   , &msf)) {
768                 WARN(cdaudio, "device doesn't play !\n");
769                 return MCIERR_HARDWARE;
770                 }
771 #ifdef linux
772         TRACE(cdaudio,"msf = %d:%d:%d %d:%d:%d\n",
773                 msf.cdmsf_min0, msf.cdmsf_sec0, msf.cdmsf_frame0,
774                 msf.cdmsf_min1, msf.cdmsf_sec1, msf.cdmsf_frame1);
775 #elif __FreeBSD__
776         TRACE(cdaudio,"msf = %d:%d:%d %d:%d:%d\n",
777                 msf.start_m, msf.start_s, msf.start_f,
778                 msf.end_m,   msf.end_s,   msf.end_f);
779 #endif
780         CDADev[wDevID].mode = MCI_MODE_PLAY;
781         if (dwFlags & MCI_NOTIFY) {
782                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
783                         lpParms->dwCallback);
784 /*
785                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
786                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
787 */
788                 }
789         return 0;
790 #else
791         return MCIERR_HARDWARE;
792 #endif
793 }
794
795 /**************************************************************************
796 *                               CDAUDIO_mciStop                 [internal]
797 */
798 static DWORD CDAUDIO_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
799 {
800 #if defined(linux) || defined(__FreeBSD__)
801         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
802                 wDevID, dwFlags, lpParms);
803         if (lpParms == NULL) return MCIERR_INTERNAL;
804         if (ioctl(CDADev[wDevID].unixdev,
805 #ifdef linux
806                   CDROMSTOP
807 #elif __FreeBSD__
808                   CDIOCSTOP
809 #endif
810                   )) return MCIERR_HARDWARE;
811         CDADev[wDevID].mode = MCI_MODE_STOP;
812         if (dwFlags & MCI_NOTIFY) {
813                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
814                         lpParms->dwCallback);
815                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
816                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
817                 }
818         return 0;
819 #else
820         return MCIERR_HARDWARE;
821 #endif
822 }
823
824 /**************************************************************************
825 *                               CDAUDIO_mciPause                [internal]
826 */
827 static DWORD CDAUDIO_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
828 {
829 #if defined(linux) || defined(__FreeBSD__)
830         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
831                 wDevID, dwFlags, lpParms);
832         if (lpParms == NULL) return MCIERR_INTERNAL;
833         if (ioctl(CDADev[wDevID].unixdev,
834 #ifdef linux
835                   CDROMPAUSE
836 #elif __FreeBSD__
837                   CDIOCPAUSE
838 #endif
839                   )) return MCIERR_HARDWARE;
840         CDADev[wDevID].mode = MCI_MODE_PAUSE;
841         if (dwFlags & MCI_NOTIFY) {
842         TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
843                 lpParms->dwCallback);
844                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
845                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
846                 }
847         return 0;
848 #else
849         return MCIERR_HARDWARE;
850 #endif
851 }
852
853 /**************************************************************************
854 *                               CDAUDIO_mciResume               [internal]
855 */
856 static DWORD CDAUDIO_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
857 {
858 #if defined(linux) || defined(__FreeBSD__)
859         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
860                 wDevID, dwFlags, lpParms);
861         if (lpParms == NULL) return MCIERR_INTERNAL;
862         if (ioctl(CDADev[wDevID].unixdev, 
863 #ifdef linux
864                   CDROMRESUME
865 #elif __FreeBSD__
866                   CDIOCRESUME
867 #endif
868                   )) return MCIERR_HARDWARE;
869         CDADev[wDevID].mode = MCI_MODE_STOP;
870         if (dwFlags & MCI_NOTIFY) {
871                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
872                         lpParms->dwCallback);
873                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
874                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
875                 }
876         return 0;
877 #else
878         return MCIERR_HARDWARE;
879 #endif
880 }
881
882 /**************************************************************************
883 *                               CDAUDIO_mciSeek                 [internal]
884 */
885 static DWORD CDAUDIO_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
886 {
887 #if defined(linux) || defined(__FreeBSD__)
888         DWORD   dwRet;
889         MCI_PLAY_PARMS PlayParms;
890         TRACE(cdaudio,"(%04X, %08lX, %p);\n", 
891                 wDevID, dwFlags, lpParms);
892         if (lpParms == NULL) return MCIERR_INTERNAL;
893         if (ioctl(CDADev[wDevID].unixdev,
894 #ifdef linux
895                   CDROMRESUME
896 #elif __FreeBSD__
897                   CDIOCRESUME
898 #endif
899                   )) {
900                 perror("ioctl CDROMRESUME");
901                 return MCIERR_HARDWARE;
902         }
903         CDADev[wDevID].mode = MCI_MODE_SEEK;
904         switch(dwFlags) {
905                 case MCI_SEEK_TO_START:
906                         PlayParms.dwFrom = 0;
907                         break;
908                 case MCI_SEEK_TO_END:
909                         PlayParms.dwFrom = CDADev[wDevID].dwTotalLen;
910                         break;
911                 case MCI_TO:
912                         PlayParms.dwFrom = lpParms->dwTo;
913                         break;
914                 }
915         dwRet = CDAUDIO_mciPlay(wDevID, MCI_WAIT | MCI_FROM, &PlayParms);
916         if (dwRet != 0) return dwRet;
917         dwRet = CDAUDIO_mciStop(wDevID, MCI_WAIT, (LPMCI_GENERIC_PARMS)&PlayParms);
918         if (dwFlags & MCI_NOTIFY) {
919                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
920                         lpParms->dwCallback);
921                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
922                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
923                 }
924         return dwRet;
925 #else
926         return MCIERR_HARDWARE;
927 #endif
928 }
929
930
931 /**************************************************************************
932 *                               CDAUDIO_mciSet                  [internal]
933 */
934 static DWORD CDAUDIO_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
935 {
936 #if defined(linux) || defined(__FreeBSD__)
937         TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
938         if (lpParms == NULL) return MCIERR_INTERNAL;
939 /*
940         TRACE(cdaudio,"dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
941         TRACE(cdaudio,"dwAudio=%08lX\n", lpParms->dwAudio);
942 */
943         if (dwFlags & MCI_SET_TIME_FORMAT) {
944                 switch (lpParms->dwTimeFormat) {
945                         case MCI_FORMAT_MILLISECONDS:
946                                 TRACE(cdaudio, "MCI_FORMAT_MILLISECONDS !\n");
947                                 break;
948                         case MCI_FORMAT_MSF:
949                                 TRACE(cdaudio,"MCI_FORMAT_MSF !\n");
950                                 break;
951                         case MCI_FORMAT_TMSF:
952                                 TRACE(cdaudio,"MCI_FORMAT_TMSF !\n");
953                                 break;
954                         default:
955                                 WARN(cdaudio, "bad time format !\n");
956                                 return MCIERR_BAD_TIME_FORMAT;
957                         }
958                 CDADev[wDevID].dwTimeFormat = lpParms->dwTimeFormat;
959                 }
960         if (dwFlags & MCI_SET_DOOR_OPEN) {
961                 TRACE(cdaudio, "MCI_SET_DOOR_OPEN !\n");
962 #ifdef __FreeBSD__
963                 if (ioctl(CDADev[wDevID].unixdev, CDIOCALLOW)) return MCIERR_HARDWARE;
964                 if (ioctl(CDADev[wDevID].unixdev, CDIOCEJECT)) return MCIERR_HARDWARE;
965                 if (ioctl(CDADev[wDevID].unixdev, CDIOCPREVENT)) return MCIERR_HARDWARE;
966 #elif linux
967                 if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
968 #endif
969                 CDADev[wDevID].nTracks = 0;
970                 }
971         if (dwFlags & MCI_SET_DOOR_CLOSED) {
972                 TRACE(cdaudio, "MCI_SET_DOOR_CLOSED !\n");
973 #ifdef __FreeBSD__
974                 if (ioctl(CDADev[wDevID].unixdev, CDIOCALLOW)) return MCIERR_HARDWARE;
975                 if (ioctl(CDADev[wDevID].unixdev, CDIOCCLOSE)) return MCIERR_HARDWARE;
976                 if (ioctl(CDADev[wDevID].unixdev, CDIOCPREVENT)) return MCIERR_HARDWARE;
977 #elif linux
978                 if (ioctl(CDADev[wDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
979                           /* XXX should it be ",1" ??? */
980 #endif
981                 CDADev[wDevID].nTracks = 0;
982                 }
983         if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
984         if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
985         if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
986         if (dwFlags & MCI_NOTIFY) {
987                 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", 
988                         lpParms->dwCallback);
989                 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback), 
990                         CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
991                 }
992         return 0;
993 #else
994         return MCIERR_HARDWARE;
995 #endif
996 }
997
998
999 /**************************************************************************
1000 *                               CDAUDIO_DriverProc              [sample driver]
1001 */
1002 LONG CDAUDIO_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg, 
1003                         DWORD dwParam1, DWORD dwParam2)
1004 {
1005 #if defined(linux) || defined(__FreeBSD__)
1006         switch(wMsg) {
1007                 case DRV_LOAD:
1008                         return 1;
1009                 case DRV_FREE:
1010                         return 1;
1011                 case DRV_OPEN:
1012                 case MCI_OPEN_DRIVER:
1013                 case MCI_OPEN:
1014                         return CDAUDIO_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(dwParam2)); 
1015                 case DRV_CLOSE:
1016                 case MCI_CLOSE_DRIVER:
1017                 case MCI_CLOSE:
1018                         return CDAUDIO_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1019                 case DRV_ENABLE:
1020                         return 1;
1021                 case DRV_DISABLE:
1022                         return 1;
1023                 case DRV_QUERYCONFIGURE:
1024                         return 1;
1025                 case DRV_CONFIGURE:
1026                         MessageBox16(0, "Sample MultiMedia Linux Driver !", 
1027                                                                 "MMLinux Driver", MB_OK);
1028                         return 1;
1029                 case DRV_INSTALL:
1030                         return DRVCNF_RESTART;
1031                 case DRV_REMOVE:
1032                         return DRVCNF_RESTART;
1033                 case MCI_GETDEVCAPS:
1034                         return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1, 
1035                                 (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1036                 case MCI_INFO:
1037                         return CDAUDIO_mciInfo(dwDevID, dwParam1, 
1038                                 (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1039                 case MCI_STATUS:
1040                         return CDAUDIO_mciStatus(dwDevID, dwParam1, 
1041                                 (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1042                 case MCI_SET:
1043                         return CDAUDIO_mciSet(dwDevID, dwParam1, 
1044                                 (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1045                 case MCI_PLAY:
1046                         return CDAUDIO_mciPlay(dwDevID, dwParam1, 
1047                                 (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1048                 case MCI_STOP:
1049                         return CDAUDIO_mciStop(dwDevID, dwParam1, 
1050                                 (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1051                 case MCI_PAUSE:
1052                         return CDAUDIO_mciPause(dwDevID, dwParam1, 
1053                                 (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1054                 case MCI_RESUME:
1055                         return CDAUDIO_mciResume(dwDevID, dwParam1, 
1056                                 (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1057                 case MCI_SEEK:
1058                         return CDAUDIO_mciSeek(dwDevID, dwParam1, 
1059                                 (LPMCI_SEEK_PARMS)PTR_SEG_TO_LIN(dwParam2));
1060                 case MCI_SET_DOOR_OPEN:
1061                         TRACE(cdaudio, "MCI_SET_DOOR_OPEN !\n");
1062 #ifdef __FreeBSD__
1063                         if (ioctl(CDADev[dwDevID].unixdev, CDIOCALLOW)) return MCIERR_HARDWARE;
1064                         if (ioctl(CDADev[dwDevID].unixdev, CDIOCEJECT)) return MCIERR_HARDWARE;
1065                         if (ioctl(CDADev[dwDevID].unixdev, CDIOCPREVENT)) return MCIERR_HARDWARE;
1066 #elif linux
1067                         if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT)) return MCIERR_HARDWARE;
1068 #endif
1069                         CDADev[dwDevID].nTracks = 0;
1070                         return 0;
1071                 case MCI_SET_DOOR_CLOSED:
1072                         TRACE(cdaudio,"MCI_SET_DOOR_CLOSED !\n");
1073 #ifdef __FreeBSD__
1074                         if (ioctl(CDADev[dwDevID].unixdev, CDIOCALLOW)) return MCIERR_HARDWARE;
1075                         if (ioctl(CDADev[dwDevID].unixdev, CDIOCCLOSE)) return MCIERR_HARDWARE;
1076                         if (ioctl(CDADev[dwDevID].unixdev, CDIOCPREVENT)) return MCIERR_HARDWARE;
1077 #elif linux
1078                         if (ioctl(CDADev[dwDevID].unixdev, CDROMEJECT, 1)) return MCIERR_HARDWARE;
1079 #endif
1080                         CDADev[dwDevID].nTracks = 0;
1081                         return 0;
1082                 default:
1083                         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1084                 }
1085 #else
1086         return MCIERR_HARDWARE;
1087 #endif
1088 }
1089
1090
1091 /*-----------------------------------------------------------------------*/