2 * Sample MCI CDAUDIO Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
6 static char Copyright[] = "Copyright Martin Ayotte, 1994";
9 #define BUILTIN_MMSYSTEM
12 #ifdef BUILTIN_MMSYSTEM
19 #include <sys/ioctl.h>
25 /* #define DEBUG_CDAUDIO */
29 #include <linux/soundcard.h>
30 #include <linux/cdrom.h>
33 #define SOUND_DEV "/dev/dsp"
34 #define CDAUDIO_DEV "/dev/sbpcd"
37 #define IOCTL(a,b,c) ioctl(a,b,&c)
39 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
42 #define MAX_CDAUDIODRV 2
43 #define MAX_CDAUDIO_TRACKS 256
45 #define CDFRAMES_PERSEC 75
46 #define CDFRAMES_PERMIN 4500
47 #define SECONDS_PERMIN 60
51 int nUseCount
; /* Incremented for each shared open */
52 BOOL fShareable
; /* TRUE if first open was shareable */
53 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
54 HANDLE hCallback
; /* Callback handle for pending notification */
55 MCI_OPEN_PARMS openParms
;
58 struct cdrom_subchnl sc
;
69 static LINUX_CDAUDIO CDADev
[MAX_CDAUDIODRV
];
72 UINT
CDAUDIO_GetNumberOfTracks(UINT wDevID
);
73 BOOL
CDAUDIO_GetTracksInfo(UINT wDevID
);
74 BOOL
CDAUDIO_GetCDStatus(UINT wDevID
);
75 DWORD
CDAUDIO_CalcTime(UINT wDevID
, DWORD dwFormatType
, DWORD dwFrame
);
78 /*-----------------------------------------------------------------------*/
81 /**************************************************************************
82 * CDAUDIO_mciOpen [internal]
84 DWORD
CDAUDIO_mciOpen(UINT wDevID
, DWORD dwFlags
, LPMCI_OPEN_PARMS lpParms
)
87 dprintf_cdaudio(stddeb
,"CDAUDIO_mciOpen(%04X, %08lX, %p);\n",
88 wDevID
, dwFlags
, lpParms
);
89 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
90 wDevID
= lpParms
->wDeviceID
;
91 if (CDADev
[wDevID
].nUseCount
> 0) {
92 /* The driver already open on this channel */
93 /* If the driver was opened shareable before and this open specifies */
94 /* shareable then increment the use count */
95 if (CDADev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
96 ++CDADev
[wDevID
].nUseCount
;
98 return MCIERR_MUST_USE_SHAREABLE
;
101 CDADev
[wDevID
].nUseCount
= 1;
102 CDADev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
104 if (dwFlags
& MCI_OPEN_ELEMENT
) {
105 dprintf_cdaudio(stddeb
,"CDAUDIO_mciOpen // MCI_OPEN_ELEMENT !\n");
106 /* return MCIERR_NO_ELEMENT_ALLOWED; */
108 memcpy(&CDADev
[wDevID
].openParms
, lpParms
, sizeof(MCI_OPEN_PARMS
));
109 CDADev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
110 CDADev
[wDevID
].unixdev
= open (CDAUDIO_DEV
, O_RDONLY
, 0);
111 if (CDADev
[wDevID
].unixdev
== -1) {
112 fprintf(stderr
,"CDAUDIO_mciOpen // can't open '%s' !\n", CDAUDIO_DEV
);
113 return MCIERR_HARDWARE
;
115 CDADev
[wDevID
].mode
= 0;
116 CDADev
[wDevID
].dwTimeFormat
= MCI_FORMAT_TMSF
;
117 CDADev
[wDevID
].nCurTrack
= 0;
118 CDADev
[wDevID
].nTracks
= 0;
119 CDADev
[wDevID
].dwTotalLen
= 0;
120 CDADev
[wDevID
].dwFirstOffset
= 0;
121 CDADev
[wDevID
].lpdwTrackLen
= NULL
;
122 CDADev
[wDevID
].lpdwTrackPos
= NULL
;
123 if (!CDAUDIO_GetTracksInfo(wDevID
)) {
124 fprintf(stderr
,"CDAUDIO_mciOpen // error reading TracksInfo !\n");
125 /* return MCIERR_INTERNAL; */
127 if (dwFlags
& MCI_NOTIFY
) {
128 dprintf_cdaudio(stddeb
,
129 "CDAUDIO_mciOpen // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
130 lpParms
->dwCallback
);
131 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
132 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
136 return MCIERR_HARDWARE
;
140 /**************************************************************************
141 * CDAUDIO_mciClose [internal]
143 DWORD
CDAUDIO_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
146 dprintf_cdaudio(stddeb
,"CDAUDIO_mciClose(%u, %08lX, %p);\n",
147 wDevID
, dwParam
, lpParms
);
148 if (CDADev
[wDevID
].lpdwTrackLen
!= NULL
) free(CDADev
[wDevID
].lpdwTrackLen
);
149 if (CDADev
[wDevID
].lpdwTrackPos
!= NULL
) free(CDADev
[wDevID
].lpdwTrackPos
);
150 close(CDADev
[wDevID
].unixdev
);
155 /**************************************************************************
156 * CDAUDIO_mciGetDevCaps [internal]
158 DWORD
CDAUDIO_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
159 LPMCI_GETDEVCAPS_PARMS lpParms
)
162 dprintf_cdaudio(stddeb
,"CDAUDIO_mciGetDevCaps(%u, %08lX, %p);\n",
163 wDevID
, dwFlags
, lpParms
);
164 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
165 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
166 dprintf_cdaudio(stddeb
,
167 "CDAUDIO_mciGetDevCaps // MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n",
169 switch(lpParms
->dwItem
) {
170 case MCI_GETDEVCAPS_CAN_RECORD
:
171 lpParms
->dwReturn
= FALSE
;
173 case MCI_GETDEVCAPS_HAS_AUDIO
:
174 lpParms
->dwReturn
= TRUE
;
176 case MCI_GETDEVCAPS_HAS_VIDEO
:
177 lpParms
->dwReturn
= FALSE
;
179 case MCI_GETDEVCAPS_DEVICE_TYPE
:
180 lpParms
->dwReturn
= MCI_DEVTYPE_CD_AUDIO
;
182 case MCI_GETDEVCAPS_USES_FILES
:
183 lpParms
->dwReturn
= FALSE
;
185 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
186 lpParms
->dwReturn
= FALSE
;
188 case MCI_GETDEVCAPS_CAN_EJECT
:
189 lpParms
->dwReturn
= TRUE
;
191 case MCI_GETDEVCAPS_CAN_PLAY
:
192 lpParms
->dwReturn
= TRUE
;
194 case MCI_GETDEVCAPS_CAN_SAVE
:
195 lpParms
->dwReturn
= FALSE
;
198 return MCIERR_UNRECOGNIZED_COMMAND
;
201 dprintf_cdaudio(stddeb
,
202 "CDAUDIO_mciGetDevCaps // lpParms->dwReturn=%08lX;\n",
206 return MCIERR_INTERNAL
;
210 /**************************************************************************
211 * CDAUDIO_mciInfo [internal]
213 DWORD
CDAUDIO_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
216 dprintf_cdaudio(stddeb
,"CDAUDIO_mciInfo(%u, %08lX, %p);\n",
217 wDevID
, dwFlags
, lpParms
);
218 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
219 lpParms
->lpstrReturn
= NULL
;
221 case MCI_INFO_PRODUCT
:
222 lpParms
->lpstrReturn
= "Linux CDROM 0.5";
225 return MCIERR_UNRECOGNIZED_COMMAND
;
227 if (lpParms
->lpstrReturn
!= NULL
)
228 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
230 lpParms
->dwRetSize
= 0;
233 return MCIERR_INTERNAL
;
237 /**************************************************************************
238 * CDAUDIO_mciStatus [internal]
240 DWORD
CDAUDIO_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
243 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus(%u, %08lX, %p);\n",
244 wDevID
, dwFlags
, lpParms
);
245 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
246 if (CDADev
[wDevID
].unixdev
== 0) return MMSYSERR_NOTENABLED
;
247 if (dwFlags
& MCI_NOTIFY
) {
248 dprintf_cdaudio(stddeb
,
249 "CDAUDIO_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
250 lpParms
->dwCallback
);
251 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
252 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
254 if (dwFlags
& MCI_STATUS_ITEM
) {
255 switch(lpParms
->dwItem
) {
256 case MCI_STATUS_CURRENT_TRACK
:
257 if (!CDAUDIO_GetCDStatus(wDevID
)) return MCIERR_INTERNAL
;
258 lpParms
->dwReturn
= CDADev
[wDevID
].nCurTrack
;
259 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // CURRENT_TRACK=%lu!\n", lpParms
->dwReturn
);
261 case MCI_STATUS_LENGTH
:
262 if (CDADev
[wDevID
].nTracks
== 0) {
263 if (!CDAUDIO_GetTracksInfo(wDevID
)) {
264 fprintf(stderr
,"CDAUDIO_mciStatus // error reading TracksInfo !\n");
265 return MCIERR_INTERNAL
;
268 if (dwFlags
& MCI_TRACK
) {
269 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_TRACK #%lu LENGTH=??? !\n",
271 if (lpParms
->dwTrack
> CDADev
[wDevID
].nTracks
)
272 return MCIERR_OUTOFRANGE
;
273 lpParms
->dwReturn
= CDADev
[wDevID
].lpdwTrackLen
[lpParms
->dwTrack
];
276 lpParms
->dwReturn
= CDADev
[wDevID
].dwTotalLen
;
277 lpParms
->dwReturn
= CDAUDIO_CalcTime(wDevID
,
278 CDADev
[wDevID
].dwTimeFormat
, lpParms
->dwReturn
);
279 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // LENGTH=%lu !\n", lpParms
->dwReturn
);
281 case MCI_STATUS_MODE
:
282 if (!CDAUDIO_GetCDStatus(wDevID
)) return MCIERR_INTERNAL
;
283 lpParms
->dwReturn
= CDADev
[wDevID
].mode
;
284 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_MODE=%08lX !\n",
287 case MCI_STATUS_MEDIA_PRESENT
:
288 lpParms
->dwReturn
= (CDADev
[wDevID
].nTracks
> 0) ? TRUE
: FALSE
;
289 if (lpParms
->dwReturn
== FALSE
)
290 fprintf(stderr
,"CDAUDIO_mciStatus // MEDIA_NOT_PRESENT !\n");
292 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
294 case MCI_STATUS_NUMBER_OF_TRACKS
:
295 lpParms
->dwReturn
= CDAUDIO_GetNumberOfTracks(wDevID
);
296 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n",
298 if (lpParms
->dwReturn
== (WORD
)-1) return MCIERR_INTERNAL
;
300 case MCI_STATUS_POSITION
:
301 if (!CDAUDIO_GetCDStatus(wDevID
)) return MCIERR_INTERNAL
;
302 lpParms
->dwReturn
= CDADev
[wDevID
].dwCurFrame
;
303 if (dwFlags
& MCI_STATUS_START
) {
304 lpParms
->dwReturn
= CDADev
[wDevID
].dwFirstOffset
;
305 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // get MCI_STATUS_START !\n");
307 if (dwFlags
& MCI_TRACK
) {
308 if (lpParms
->dwTrack
> CDADev
[wDevID
].nTracks
)
309 return MCIERR_OUTOFRANGE
;
310 lpParms
->dwReturn
= CDADev
[wDevID
].lpdwTrackPos
[lpParms
->dwTrack
- 1];
311 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // get MCI_TRACK #%lu !\n", lpParms
->dwTrack
);
313 lpParms
->dwReturn
= CDAUDIO_CalcTime(wDevID
,
314 CDADev
[wDevID
].dwTimeFormat
, lpParms
->dwReturn
);
315 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_POSITION=%08lX !\n",
318 case MCI_STATUS_READY
:
319 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_READY !\n");
320 lpParms
->dwReturn
= TRUE
;
322 case MCI_STATUS_TIME_FORMAT
:
323 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
324 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
327 fprintf(stderr
,"CDAUDIO_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
328 return MCIERR_UNRECOGNIZED_COMMAND
;
331 fprintf(stderr
,"CDAUDIO_mciStatus // not MCI_STATUS_ITEM !\n");
334 return MMSYSERR_NOTENABLED
;
339 /**************************************************************************
340 * CDAUDIO_CalcTime [internal]
342 DWORD
CDAUDIO_CalcTime(UINT wDevID
, DWORD dwFormatType
, DWORD dwFrame
)
350 dprintf_cdaudio(stddeb
,"CDAUDIO_CalcTime(%u, %08lX, %lu);\n",
351 wDevID
, dwFormatType
, dwFrame
);
353 switch (dwFormatType
) {
354 case MCI_FORMAT_MILLISECONDS
:
355 dwTime
= dwFrame
/ CDFRAMES_PERSEC
* 1000;
356 dprintf_cdaudio(stddeb
,
357 "CDAUDIO_CalcTime // MILLISECONDS %lu\n",
361 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
362 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
363 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
-
364 CDFRAMES_PERSEC
* wSeconds
;
365 dwTime
= MCI_MAKE_MSF(wMinutes
, wSeconds
, wFrames
);
366 dprintf_cdaudio(stddeb
,"CDAUDIO_CalcTime // MSF %02u:%02u:%02u -> dwTime=%lu\n",
367 wMinutes
, wSeconds
, wFrames
, dwTime
);
369 case MCI_FORMAT_TMSF
:
370 for (wTrack
= 0; wTrack
< CDADev
[wDevID
].nTracks
; wTrack
++) {
371 /* dwTime += CDADev[wDevID].lpdwTrackLen[wTrack - 1];
372 printf("Adding trk#%u curpos=%u \n", dwTime);
373 if (dwTime >= dwFrame) break; */
374 if (CDADev
[wDevID
].lpdwTrackPos
[wTrack
- 1] >= dwFrame
) break;
376 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
377 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
378 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
-
379 CDFRAMES_PERSEC
* wSeconds
;
380 dwTime
= MCI_MAKE_TMSF(wTrack
, wMinutes
, wSeconds
, wFrames
);
381 dprintf_cdaudio(stddeb
,
382 "CDAUDIO_CalcTime // %02u-%02u:%02u:%02u\n",
383 wTrack
, wMinutes
, wSeconds
, wFrames
);
386 /* unknown format ! force TMSF ! ... */
387 dwFormatType
= MCI_FORMAT_TMSF
;
395 /**************************************************************************
396 * CDAUDIO_CalcFrame [internal]
398 DWORD
CDAUDIO_CalcFrame(UINT wDevID
, DWORD dwFormatType
, DWORD dwTime
)
403 dprintf_cdaudio(stddeb
,"CDAUDIO_CalcFrame(%u, %08lX, %lu);\n",
404 wDevID
, dwFormatType
, dwTime
);
406 switch (dwFormatType
) {
407 case MCI_FORMAT_MILLISECONDS
:
408 dwFrame
= dwTime
* CDFRAMES_PERSEC
/ 1000;
409 dprintf_cdaudio(stddeb
,
410 "CDAUDIO_CalcFrame // MILLISECONDS %lu\n",
414 dprintf_cdaudio(stddeb
,
415 "CDAUDIO_CalcFrame // MSF %02u:%02u:%02u\n",
416 MCI_MSF_MINUTE(dwTime
), MCI_MSF_SECOND(dwTime
),
417 MCI_MSF_FRAME(dwTime
));
418 dwFrame
+= CDFRAMES_PERMIN
* MCI_MSF_MINUTE(dwTime
);
419 dwFrame
+= CDFRAMES_PERSEC
* MCI_MSF_SECOND(dwTime
);
420 dwFrame
+= MCI_MSF_FRAME(dwTime
);
422 case MCI_FORMAT_TMSF
:
423 wTrack
= MCI_TMSF_TRACK(dwTime
);
424 dprintf_cdaudio(stddeb
,
425 "CDAUDIO_CalcFrame // TMSF %02u-%02u:%02u:%02u\n",
426 MCI_TMSF_TRACK(dwTime
), MCI_TMSF_MINUTE(dwTime
),
427 MCI_TMSF_SECOND(dwTime
), MCI_TMSF_FRAME(dwTime
));
428 dprintf_cdaudio(stddeb
,
429 "CDAUDIO_CalcFrame // TMSF trackpos[%u]=%lu\n",
430 wTrack
, CDADev
[wDevID
].lpdwTrackPos
[wTrack
- 1]);
431 dwFrame
= CDADev
[wDevID
].lpdwTrackPos
[wTrack
- 1];
432 dwFrame
+= CDFRAMES_PERMIN
* MCI_TMSF_MINUTE(dwTime
);
433 dwFrame
+= CDFRAMES_PERSEC
* MCI_TMSF_SECOND(dwTime
);
434 dwFrame
+= MCI_TMSF_FRAME(dwTime
);
437 /* unknown format ! force TMSF ! ... */
438 dwFormatType
= MCI_FORMAT_TMSF
;
446 /**************************************************************************
447 * CDAUDIO_GetNumberOfTracks [internal]
449 UINT
CDAUDIO_GetNumberOfTracks(UINT wDevID
)
452 struct cdrom_tochdr hdr
;
453 if (CDADev
[wDevID
].nTracks
== 0) {
454 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMREADTOCHDR
, &hdr
)) {
456 "GetNumberOfTracks(%u) // Error occured !\n",
460 CDADev
[wDevID
].nTracks
= hdr
.cdth_trk1
;
462 return CDADev
[wDevID
].nTracks
;
468 /**************************************************************************
469 * CDAUDIO_GetTracksInfo [internal]
471 BOOL
CDAUDIO_GetTracksInfo(UINT wDevID
)
475 int start
, last_start
;
476 int total_length
= 0;
477 struct cdrom_tocentry entry
;
478 if (CDADev
[wDevID
].nTracks
== 0) {
479 if (CDAUDIO_GetNumberOfTracks(wDevID
) == (WORD
)-1) return FALSE
;
481 dprintf_cdaudio(stddeb
,"CDAUDIO_GetTracksInfo // nTracks=%u\n",
482 CDADev
[wDevID
].nTracks
);
483 if (CDADev
[wDevID
].lpdwTrackLen
!= NULL
)
484 free(CDADev
[wDevID
].lpdwTrackLen
);
485 CDADev
[wDevID
].lpdwTrackLen
= (LPDWORD
)malloc(
486 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
487 if (CDADev
[wDevID
].lpdwTrackPos
!= NULL
)
488 free(CDADev
[wDevID
].lpdwTrackPos
);
489 CDADev
[wDevID
].lpdwTrackPos
= (LPDWORD
)malloc(
490 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
491 if (CDADev
[wDevID
].lpdwTrackLen
== NULL
||
492 CDADev
[wDevID
].lpdwTrackPos
== NULL
) {
494 "CDAUDIO_GetTracksInfo // error allocating track table !\n");
497 memset(CDADev
[wDevID
].lpdwTrackLen
, 0,
498 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
499 memset(CDADev
[wDevID
].lpdwTrackPos
, 0,
500 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
501 for (i
= 0; i
<= CDADev
[wDevID
].nTracks
; i
++) {
502 if (i
== CDADev
[wDevID
].nTracks
)
503 entry
.cdte_track
= CDROM_LEADOUT
;
505 entry
.cdte_track
= i
+ 1;
506 entry
.cdte_format
= CDROM_MSF
;
507 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMREADTOCENTRY
, &entry
)) {
509 "CDAUDIO_GetTracksInfo // error read entry\n");
512 start
= CDFRAMES_PERSEC
* (SECONDS_PERMIN
*
513 entry
.cdte_addr
.msf
.minute
+ entry
.cdte_addr
.msf
.second
) +
514 entry
.cdte_addr
.msf
.frame
;
517 CDADev
[wDevID
].dwFirstOffset
= start
;
518 dprintf_cdaudio(stddeb
,
519 "CDAUDIO_GetTracksInfo // dwFirstOffset=%u\n",
523 length
= start
- last_start
;
525 start
= last_start
- length
;
526 total_length
+= length
;
527 CDADev
[wDevID
].lpdwTrackLen
[i
- 1] = length
;
528 CDADev
[wDevID
].lpdwTrackPos
[i
- 1] = start
;
529 dprintf_cdaudio(stddeb
,
530 "CDAUDIO_GetTracksInfo // track #%u start=%u len=%u\n",
534 CDADev
[wDevID
].dwTotalLen
= total_length
;
535 dprintf_cdaudio(stddeb
,"CDAUDIO_GetTracksInfo // total_len=%u\n",
545 /**************************************************************************
546 * CDAUDIO_GetCDStatus [internal]
548 BOOL
CDAUDIO_GetCDStatus(UINT wDevID
)
551 int oldmode
= CDADev
[wDevID
].mode
;
552 CDADev
[wDevID
].sc
.cdsc_format
= CDROM_MSF
;
553 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMSUBCHNL
, &CDADev
[wDevID
].sc
)) {
554 fprintf(stderr
,"CDAUDIO_GetCDStatus // opened or no_media !\n");
555 CDADev
[wDevID
].mode
= MCI_MODE_NOT_READY
;
558 switch (CDADev
[wDevID
].sc
.cdsc_audiostatus
) {
559 case CDROM_AUDIO_INVALID
:
560 fprintf(stderr
,"CDAUDIO_GetCDStatus // device doesn't support status !\n");
562 case CDROM_AUDIO_NO_STATUS
:
563 CDADev
[wDevID
].mode
= MCI_MODE_STOP
;
564 dprintf_cdaudio(stddeb
,"CDAUDIO_GetCDStatus // MCI_MODE_STOP !\n");
566 case CDROM_AUDIO_PLAY
:
567 CDADev
[wDevID
].mode
= MCI_MODE_PLAY
;
568 dprintf_cdaudio(stddeb
,"CDAUDIO_GetCDStatus // MCI_MODE_PLAY !\n");
570 case CDROM_AUDIO_PAUSED
:
571 CDADev
[wDevID
].mode
= MCI_MODE_PAUSE
;
572 dprintf_cdaudio(stddeb
,"CDAUDIO_GetCDStatus // MCI_MODE_PAUSE !\n");
575 dprintf_cdaudio(stddeb
,"CDAUDIO_GetCDStatus // status=%02X !\n",
576 CDADev
[wDevID
].sc
.cdsc_audiostatus
);
578 CDADev
[wDevID
].nCurTrack
= CDADev
[wDevID
].sc
.cdsc_trk
;
579 CDADev
[wDevID
].dwCurFrame
=
580 CDFRAMES_PERMIN
* CDADev
[wDevID
].sc
.cdsc_absaddr
.msf
.minute
+
581 CDFRAMES_PERSEC
* CDADev
[wDevID
].sc
.cdsc_absaddr
.msf
.second
+
582 CDADev
[wDevID
].sc
.cdsc_absaddr
.msf
.frame
;
583 dprintf_cdaudio(stddeb
,"CDAUDIO_GetCDStatus // %02u-%02u:%02u:%02u \n",
584 CDADev
[wDevID
].sc
.cdsc_trk
,
585 CDADev
[wDevID
].sc
.cdsc_absaddr
.msf
.minute
,
586 CDADev
[wDevID
].sc
.cdsc_absaddr
.msf
.second
,
587 CDADev
[wDevID
].sc
.cdsc_absaddr
.msf
.frame
);
588 if (oldmode
!= CDADev
[wDevID
].mode
&& oldmode
== MCI_MODE_OPEN
) {
589 if (!CDAUDIO_GetTracksInfo(wDevID
)) {
590 fprintf(stderr
,"CDAUDIO_GetCDStatus // error updating TracksInfo !\n");
591 return MCIERR_INTERNAL
;
600 /**************************************************************************
601 * CDAUDIO_mciPlay [internal]
603 DWORD
CDAUDIO_mciPlay(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
607 struct cdrom_msf msf
;
608 dprintf_cdaudio(stddeb
,"CDAUDIO_mciPlay(%u, %08lX, %p);\n",
609 wDevID
, dwFlags
, lpParms
);
610 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
611 if (CDADev
[wDevID
].unixdev
== 0) return MMSYSERR_NOTENABLED
;
612 start
= 0; end
= CDADev
[wDevID
].dwTotalLen
;
613 CDADev
[wDevID
].nCurTrack
= 1;
614 if (dwFlags
& MCI_FROM
) {
615 start
= CDAUDIO_CalcFrame(wDevID
,
616 CDADev
[wDevID
].dwTimeFormat
, lpParms
->dwFrom
);
617 dprintf_cdaudio(stddeb
,"CDAUDIO_mciPlay // MCI_FROM=%08lX -> %u \n",
618 lpParms
->dwFrom
, start
);
620 if (dwFlags
& MCI_TO
) {
621 end
= CDAUDIO_CalcFrame(wDevID
,
622 CDADev
[wDevID
].dwTimeFormat
, lpParms
->dwTo
);
623 dprintf_cdaudio(stddeb
,
624 "CDAUDIO_mciPlay // MCI_TO=%08lX -> %u \n",
627 start
+= CDADev
[wDevID
].dwFirstOffset
;
628 end
+= CDADev
[wDevID
].dwFirstOffset
;
629 msf
.cdmsf_min0
= start
/ CDFRAMES_PERMIN
;
630 msf
.cdmsf_sec0
= (start
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
631 msf
.cdmsf_frame0
= start
% CDFRAMES_PERSEC
;
632 msf
.cdmsf_min1
= end
/ CDFRAMES_PERMIN
;
633 msf
.cdmsf_sec1
= (end
% CDFRAMES_PERMIN
) / CDFRAMES_PERSEC
;
634 msf
.cdmsf_frame1
= end
% CDFRAMES_PERSEC
;
635 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMSTART
)) {
636 fprintf(stderr
,"CDAUDIO_mciPlay // motor doesn't start !\n");
637 return MCIERR_HARDWARE
;
639 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMPLAYMSF
, &msf
)) {
640 fprintf(stderr
,"CDAUDIO_mciPlay // device doesn't play !\n");
641 return MCIERR_HARDWARE
;
643 dprintf_cdaudio(stddeb
,"CDAUDIO_mciPlay // msf = %d:%d:%d %d:%d:%d\n",
644 msf
.cdmsf_min0
, msf
.cdmsf_sec0
, msf
.cdmsf_frame0
,
645 msf
.cdmsf_min1
, msf
.cdmsf_sec1
, msf
.cdmsf_frame1
);
646 CDADev
[wDevID
].mode
= MCI_MODE_PLAY
;
647 if (dwFlags
& MCI_NOTIFY
) {
648 dprintf_cdaudio(stddeb
,
649 "CDAUDIO_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
650 lpParms
->dwCallback
);
652 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
653 CDADev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
658 return MCIERR_HARDWARE
;
662 /**************************************************************************
663 * CDAUDIO_mciStop [internal]
665 DWORD
CDAUDIO_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
668 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStop(%u, %08lX, %p);\n",
669 wDevID
, dwFlags
, lpParms
);
670 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
671 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMSTOP
)) return MCIERR_HARDWARE
;
672 CDADev
[wDevID
].mode
= MCI_MODE_STOP
;
673 if (dwFlags
& MCI_NOTIFY
) {
674 dprintf_cdaudio(stddeb
,
675 "CDAUDIO_mciStop // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
676 lpParms
->dwCallback
);
677 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
678 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
682 return MCIERR_HARDWARE
;
686 /**************************************************************************
687 * CDAUDIO_mciPause [internal]
689 DWORD
CDAUDIO_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
692 dprintf_cdaudio(stddeb
,"CDAUDIO_mciPause(%u, %08lX, %p);\n",
693 wDevID
, dwFlags
, lpParms
);
694 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
695 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMPAUSE
)) return MCIERR_HARDWARE
;
696 CDADev
[wDevID
].mode
= MCI_MODE_PAUSE
;
697 if (dwFlags
& MCI_NOTIFY
) {
698 dprintf_cdaudio(stddeb
,
699 "CDAUDIO_mciPause // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
700 lpParms
->dwCallback
);
701 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
702 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
706 return MCIERR_HARDWARE
;
710 /**************************************************************************
711 * CDAUDIO_mciResume [internal]
713 DWORD
CDAUDIO_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
716 dprintf_cdaudio(stddeb
,"CDAUDIO_mciResume(%u, %08lX, %p);\n",
717 wDevID
, dwFlags
, lpParms
);
718 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
719 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMRESUME
)) return MCIERR_HARDWARE
;
720 CDADev
[wDevID
].mode
= MCI_MODE_STOP
;
721 if (dwFlags
& MCI_NOTIFY
) {
722 dprintf_cdaudio(stddeb
,
723 "CDAUDIO_mciResume // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
724 lpParms
->dwCallback
);
725 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
726 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
730 return MCIERR_HARDWARE
;
734 /**************************************************************************
735 * CDAUDIO_mciSeek [internal]
737 DWORD
CDAUDIO_mciSeek(UINT wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
)
741 MCI_PLAY_PARMS PlayParms
;
742 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSeek(%u, %08lX, %p);\n",
743 wDevID
, dwFlags
, lpParms
);
744 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
745 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMRESUME
)) return MCIERR_HARDWARE
;
746 CDADev
[wDevID
].mode
= MCI_MODE_SEEK
;
748 case MCI_SEEK_TO_START
:
749 PlayParms
.dwFrom
= 0;
751 case MCI_SEEK_TO_END
:
752 PlayParms
.dwFrom
= CDADev
[wDevID
].dwTotalLen
;
755 PlayParms
.dwFrom
= lpParms
->dwTo
;
758 dwRet
= CDAUDIO_mciPlay(wDevID
, MCI_WAIT
| MCI_FROM
, &PlayParms
);
759 if (dwRet
!= 0) return dwRet
;
760 dwRet
= CDAUDIO_mciStop(wDevID
, MCI_WAIT
, (LPMCI_GENERIC_PARMS
)&PlayParms
);
761 if (dwFlags
& MCI_NOTIFY
) {
762 dprintf_cdaudio(stddeb
,
763 "CDAUDIO_mciSeek // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
764 lpParms
->dwCallback
);
765 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
766 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
770 return MCIERR_HARDWARE
;
775 /**************************************************************************
776 * CDAUDIO_mciSet [internal]
778 DWORD
CDAUDIO_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
781 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSet(%u, %08lX, %p);\n",
782 wDevID
, dwFlags
, lpParms
);
783 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
785 printf("CDAUDIO_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
786 printf("CDAUDIO_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
788 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
789 switch (lpParms
->dwTimeFormat
) {
790 case MCI_FORMAT_MILLISECONDS
:
791 dprintf_cdaudio(stddeb
,
792 "CDAUDIO_mciSet // MCI_FORMAT_MILLISECONDS !\n");
795 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSet // MCI_FORMAT_MSF !\n");
797 case MCI_FORMAT_TMSF
:
798 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSet // MCI_FORMAT_TMSF !\n");
801 fprintf(stderr
,"CDAUDIO_mciSet // bad time format !\n");
802 return MCIERR_BAD_TIME_FORMAT
;
804 CDADev
[wDevID
].dwTimeFormat
= lpParms
->dwTimeFormat
;
806 if (dwFlags
& MCI_SET_DOOR_OPEN
) {
807 dprintf_cdaudio(stddeb
,
808 "CDAUDIO_mciSet // MCI_SET_DOOR_OPEN !\n");
809 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMEJECT
)) return MCIERR_HARDWARE
;
810 CDADev
[wDevID
].nTracks
= 0;
812 if (dwFlags
& MCI_SET_DOOR_CLOSED
) {
813 dprintf_cdaudio(stddeb
,
814 "CDAUDIO_mciSet // MCI_SET_DOOR_CLOSED !\n");
815 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMEJECT
)) return MCIERR_HARDWARE
;
816 CDADev
[wDevID
].nTracks
= 0;
818 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
819 if (dwFlags
& MCI_SET_ON
) return MCIERR_UNSUPPORTED_FUNCTION
;
820 if (dwFlags
& MCI_SET_OFF
) return MCIERR_UNSUPPORTED_FUNCTION
;
821 if (dwFlags
& MCI_NOTIFY
) {
822 dprintf_cdaudio(stddeb
,
823 "CDAUDIO_mciSet // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
824 lpParms
->dwCallback
);
825 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
826 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
830 return MCIERR_HARDWARE
;
835 /**************************************************************************
836 * CDAUDIO_DriverProc [sample driver]
838 LRESULT
CDAUDIO_DriverProc(DWORD dwDevID
, HDRVR hDriv
, WORD wMsg
,
839 DWORD dwParam1
, DWORD dwParam2
)
848 case MCI_OPEN_DRIVER
:
850 return CDAUDIO_mciOpen(dwDevID
, dwParam1
, (LPMCI_OPEN_PARMS
)dwParam2
);
852 case MCI_CLOSE_DRIVER
:
854 return CDAUDIO_mciClose(dwDevID
, dwParam1
,
855 (LPMCI_GENERIC_PARMS
)dwParam2
);
860 case DRV_QUERYCONFIGURE
:
863 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
864 "MMLinux Driver", MB_OK
);
867 return (LRESULT
)DRVCNF_RESTART
;
869 return (LRESULT
)DRVCNF_RESTART
;
871 return CDAUDIO_mciGetDevCaps(dwDevID
, dwParam1
,
872 (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
874 return CDAUDIO_mciInfo(dwDevID
, dwParam1
,
875 (LPMCI_INFO_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
877 return CDAUDIO_mciStatus(dwDevID
, dwParam1
,
878 (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
880 return CDAUDIO_mciSet(dwDevID
, dwParam1
,
881 (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
883 return CDAUDIO_mciPlay(dwDevID
, dwParam1
,
884 (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
886 return CDAUDIO_mciStop(dwDevID
, dwParam1
,
887 (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
889 return CDAUDIO_mciPause(dwDevID
, dwParam1
,
890 (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
892 return CDAUDIO_mciResume(dwDevID
, dwParam1
,
893 (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
895 return CDAUDIO_mciSeek(dwDevID
, dwParam1
,
896 (LPMCI_SEEK_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
897 case MCI_SET_DOOR_OPEN
:
898 dprintf_cdaudio(stddeb
,
899 "CDAUDIO_DriverProc // MCI_SET_DOOR_OPEN !\n");
900 if (ioctl(CDADev
[dwDevID
].unixdev
, CDROMEJECT
)) return MCIERR_HARDWARE
;
901 CDADev
[dwDevID
].nTracks
= 0;
903 case MCI_SET_DOOR_CLOSED
:
904 dprintf_cdaudio(stddeb
,"CDAUDIO_DriverProc // MCI_SET_DOOR_CLOSED !\n");
905 if (ioctl(CDADev
[dwDevID
].unixdev
, CDROMEJECT
, 1)) return MCIERR_HARDWARE
;
906 CDADev
[dwDevID
].nTracks
= 0;
909 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
912 return MCIERR_HARDWARE
;
917 /*-----------------------------------------------------------------------*/
919 #endif /* #ifdef BUILTIN_MMSYSTEM */