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(DWORD dwFlags
, LPMCI_OPEN_PARMS lpParms
)
88 dprintf_cdaudio(stddeb
,"CDAUDIO_mciOpen(%08lX, %p);\n",
90 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
91 wDevID
= lpParms
->wDeviceID
;
92 if (CDADev
[wDevID
].nUseCount
> 0) {
93 /* The driver already open on this channel */
94 /* If the driver was opened shareable before and this open specifies */
95 /* shareable then increment the use count */
96 if (CDADev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
97 ++CDADev
[wDevID
].nUseCount
;
99 return MCIERR_MUST_USE_SHAREABLE
;
102 CDADev
[wDevID
].nUseCount
= 1;
103 CDADev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
105 if (dwFlags
& MCI_OPEN_ELEMENT
) {
106 dprintf_cdaudio(stddeb
,"CDAUDIO_mciOpen // MCI_OPEN_ELEMENT !\n");
107 /* return MCIERR_NO_ELEMENT_ALLOWED; */
109 memcpy(&CDADev
[wDevID
].openParms
, lpParms
, sizeof(MCI_OPEN_PARMS
));
110 CDADev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
111 CDADev
[wDevID
].unixdev
= open (CDAUDIO_DEV
, O_RDONLY
, 0);
112 if (CDADev
[wDevID
].unixdev
== -1) {
113 fprintf(stderr
,"CDAUDIO_mciOpen // can't open '%s' !\n", CDAUDIO_DEV
);
114 return MCIERR_HARDWARE
;
116 CDADev
[wDevID
].mode
= 0;
117 CDADev
[wDevID
].dwTimeFormat
= MCI_FORMAT_TMSF
;
118 CDADev
[wDevID
].nCurTrack
= 0;
119 CDADev
[wDevID
].nTracks
= 0;
120 CDADev
[wDevID
].dwTotalLen
= 0;
121 CDADev
[wDevID
].dwFirstOffset
= 0;
122 CDADev
[wDevID
].lpdwTrackLen
= NULL
;
123 CDADev
[wDevID
].lpdwTrackPos
= NULL
;
124 if (!CDAUDIO_GetTracksInfo(wDevID
)) {
125 fprintf(stderr
,"CDAUDIO_mciOpen // error reading TracksInfo !\n");
126 /* return MCIERR_INTERNAL; */
128 if (dwFlags
& MCI_NOTIFY
) {
129 dprintf_cdaudio(stddeb
,
130 "CDAUDIO_mciOpen // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
131 lpParms
->dwCallback
);
132 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
133 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
137 return MCIERR_HARDWARE
;
141 /**************************************************************************
142 * CDAUDIO_mciClose [internal]
144 DWORD
CDAUDIO_mciClose(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
147 dprintf_cdaudio(stddeb
,"CDAUDIO_mciClose(%u, %08lX, %p);\n",
148 wDevID
, dwParam
, lpParms
);
149 if (CDADev
[wDevID
].lpdwTrackLen
!= NULL
) free(CDADev
[wDevID
].lpdwTrackLen
);
150 if (CDADev
[wDevID
].lpdwTrackPos
!= NULL
) free(CDADev
[wDevID
].lpdwTrackPos
);
151 close(CDADev
[wDevID
].unixdev
);
156 /**************************************************************************
157 * CDAUDIO_mciGetDevCaps [internal]
159 DWORD
CDAUDIO_mciGetDevCaps(UINT wDevID
, DWORD dwFlags
,
160 LPMCI_GETDEVCAPS_PARMS lpParms
)
163 dprintf_cdaudio(stddeb
,"CDAUDIO_mciGetDevCaps(%u, %08lX, %p);\n",
164 wDevID
, dwFlags
, lpParms
);
165 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
166 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
167 dprintf_cdaudio(stddeb
,
168 "CDAUDIO_mciGetDevCaps // MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n",
170 switch(lpParms
->dwItem
) {
171 case MCI_GETDEVCAPS_CAN_RECORD
:
172 lpParms
->dwReturn
= FALSE
;
174 case MCI_GETDEVCAPS_HAS_AUDIO
:
175 lpParms
->dwReturn
= TRUE
;
177 case MCI_GETDEVCAPS_HAS_VIDEO
:
178 lpParms
->dwReturn
= FALSE
;
180 case MCI_GETDEVCAPS_DEVICE_TYPE
:
181 lpParms
->dwReturn
= MCI_DEVTYPE_CD_AUDIO
;
183 case MCI_GETDEVCAPS_USES_FILES
:
184 lpParms
->dwReturn
= FALSE
;
186 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
187 lpParms
->dwReturn
= FALSE
;
189 case MCI_GETDEVCAPS_CAN_EJECT
:
190 lpParms
->dwReturn
= TRUE
;
192 case MCI_GETDEVCAPS_CAN_PLAY
:
193 lpParms
->dwReturn
= TRUE
;
195 case MCI_GETDEVCAPS_CAN_SAVE
:
196 lpParms
->dwReturn
= FALSE
;
199 return MCIERR_UNRECOGNIZED_COMMAND
;
202 dprintf_cdaudio(stddeb
,
203 "CDAUDIO_mciGetDevCaps // lpParms->dwReturn=%08lX;\n",
207 return MCIERR_INTERNAL
;
211 /**************************************************************************
212 * CDAUDIO_mciInfo [internal]
214 DWORD
CDAUDIO_mciInfo(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS lpParms
)
217 dprintf_cdaudio(stddeb
,"CDAUDIO_mciInfo(%u, %08lX, %p);\n",
218 wDevID
, dwFlags
, lpParms
);
219 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
220 lpParms
->lpstrReturn
= NULL
;
222 case MCI_INFO_PRODUCT
:
223 lpParms
->lpstrReturn
= "Linux CDROM 0.5";
226 return MCIERR_UNRECOGNIZED_COMMAND
;
228 if (lpParms
->lpstrReturn
!= NULL
)
229 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
231 lpParms
->dwRetSize
= 0;
234 return MCIERR_INTERNAL
;
238 /**************************************************************************
239 * CDAUDIO_mciStatus [internal]
241 DWORD
CDAUDIO_mciStatus(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
244 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus(%u, %08lX, %p);\n",
245 wDevID
, dwFlags
, lpParms
);
246 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
247 if (CDADev
[wDevID
].unixdev
== 0) return MMSYSERR_NOTENABLED
;
248 if (dwFlags
& MCI_NOTIFY
) {
249 dprintf_cdaudio(stddeb
,
250 "CDAUDIO_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
251 lpParms
->dwCallback
);
252 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
253 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
255 if (dwFlags
& MCI_STATUS_ITEM
) {
256 switch(lpParms
->dwItem
) {
257 case MCI_STATUS_CURRENT_TRACK
:
258 if (!CDAUDIO_GetCDStatus(wDevID
)) return MCIERR_INTERNAL
;
259 lpParms
->dwReturn
= CDADev
[wDevID
].nCurTrack
;
260 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // CURRENT_TRACK=%lu!\n", lpParms
->dwReturn
);
262 case MCI_STATUS_LENGTH
:
263 if (CDADev
[wDevID
].nTracks
== 0) {
264 if (!CDAUDIO_GetTracksInfo(wDevID
)) {
265 fprintf(stderr
,"CDAUDIO_mciStatus // error reading TracksInfo !\n");
266 return MCIERR_INTERNAL
;
269 if (dwFlags
& MCI_TRACK
) {
270 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_TRACK #%lu LENGTH=??? !\n",
272 if (lpParms
->dwTrack
> CDADev
[wDevID
].nTracks
)
273 return MCIERR_OUTOFRANGE
;
274 lpParms
->dwReturn
= CDADev
[wDevID
].lpdwTrackLen
[lpParms
->dwTrack
];
277 lpParms
->dwReturn
= CDADev
[wDevID
].dwTotalLen
;
278 lpParms
->dwReturn
= CDAUDIO_CalcTime(wDevID
,
279 CDADev
[wDevID
].dwTimeFormat
, lpParms
->dwReturn
);
280 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // LENGTH=%lu !\n", lpParms
->dwReturn
);
282 case MCI_STATUS_MODE
:
283 if (!CDAUDIO_GetCDStatus(wDevID
)) return MCIERR_INTERNAL
;
284 lpParms
->dwReturn
= CDADev
[wDevID
].mode
;
285 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_MODE=%08lX !\n",
288 case MCI_STATUS_MEDIA_PRESENT
:
289 lpParms
->dwReturn
= (CDADev
[wDevID
].nTracks
> 0) ? TRUE
: FALSE
;
290 if (lpParms
->dwReturn
== FALSE
)
291 fprintf(stderr
,"CDAUDIO_mciStatus // MEDIA_NOT_PRESENT !\n");
293 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
295 case MCI_STATUS_NUMBER_OF_TRACKS
:
296 lpParms
->dwReturn
= CDAUDIO_GetNumberOfTracks(wDevID
);
297 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n",
299 if (lpParms
->dwReturn
== (WORD
)-1) return MCIERR_INTERNAL
;
301 case MCI_STATUS_POSITION
:
302 if (!CDAUDIO_GetCDStatus(wDevID
)) return MCIERR_INTERNAL
;
303 lpParms
->dwReturn
= CDADev
[wDevID
].dwCurFrame
;
304 if (dwFlags
& MCI_STATUS_START
) {
305 lpParms
->dwReturn
= CDADev
[wDevID
].dwFirstOffset
;
306 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // get MCI_STATUS_START !\n");
308 if (dwFlags
& MCI_TRACK
) {
309 if (lpParms
->dwTrack
> CDADev
[wDevID
].nTracks
)
310 return MCIERR_OUTOFRANGE
;
311 lpParms
->dwReturn
= CDADev
[wDevID
].lpdwTrackPos
[lpParms
->dwTrack
- 1];
312 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // get MCI_TRACK #%lu !\n", lpParms
->dwTrack
);
314 lpParms
->dwReturn
= CDAUDIO_CalcTime(wDevID
,
315 CDADev
[wDevID
].dwTimeFormat
, lpParms
->dwReturn
);
316 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_POSITION=%08lX !\n",
319 case MCI_STATUS_READY
:
320 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_READY !\n");
321 lpParms
->dwReturn
= TRUE
;
323 case MCI_STATUS_TIME_FORMAT
:
324 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
325 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
328 fprintf(stderr
,"CDAUDIO_mciStatus // unknown command %08lX !\n", lpParms
->dwItem
);
329 return MCIERR_UNRECOGNIZED_COMMAND
;
332 fprintf(stderr
,"CDAUDIO_mciStatus // not MCI_STATUS_ITEM !\n");
335 return MMSYSERR_NOTENABLED
;
340 /**************************************************************************
341 * CDAUDIO_CalcTime [internal]
343 DWORD
CDAUDIO_CalcTime(UINT wDevID
, DWORD dwFormatType
, DWORD dwFrame
)
351 dprintf_cdaudio(stddeb
,"CDAUDIO_CalcTime(%u, %08lX, %lu);\n",
352 wDevID
, dwFormatType
, dwFrame
);
354 switch (dwFormatType
) {
355 case MCI_FORMAT_MILLISECONDS
:
356 dwTime
= dwFrame
/ CDFRAMES_PERSEC
* 1000;
357 dprintf_cdaudio(stddeb
,
358 "CDAUDIO_CalcTime // MILLISECONDS %lu\n",
362 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
363 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
364 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
-
365 CDFRAMES_PERSEC
* wSeconds
;
366 dwTime
= MCI_MAKE_MSF(wMinutes
, wSeconds
, wFrames
);
367 dprintf_cdaudio(stddeb
,"CDAUDIO_CalcTime // MSF %02u:%02u:%02u -> dwTime=%lu\n",
368 wMinutes
, wSeconds
, wFrames
, dwTime
);
370 case MCI_FORMAT_TMSF
:
371 for (wTrack
= 0; wTrack
< CDADev
[wDevID
].nTracks
; wTrack
++) {
372 /* dwTime += CDADev[wDevID].lpdwTrackLen[wTrack - 1];
373 printf("Adding trk#%u curpos=%u \n", dwTime);
374 if (dwTime >= dwFrame) break; */
375 if (CDADev
[wDevID
].lpdwTrackPos
[wTrack
- 1] >= dwFrame
) break;
377 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
378 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
379 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
-
380 CDFRAMES_PERSEC
* wSeconds
;
381 dwTime
= MCI_MAKE_TMSF(wTrack
, wMinutes
, wSeconds
, wFrames
);
382 dprintf_cdaudio(stddeb
,
383 "CDAUDIO_CalcTime // %02u-%02u:%02u:%02u\n",
384 wTrack
, wMinutes
, wSeconds
, wFrames
);
387 /* unknown format ! force TMSF ! ... */
388 dwFormatType
= MCI_FORMAT_TMSF
;
396 /**************************************************************************
397 * CDAUDIO_CalcFrame [internal]
399 DWORD
CDAUDIO_CalcFrame(UINT wDevID
, DWORD dwFormatType
, DWORD dwTime
)
404 dprintf_cdaudio(stddeb
,"CDAUDIO_CalcFrame(%u, %08lX, %lu);\n",
405 wDevID
, dwFormatType
, dwTime
);
407 switch (dwFormatType
) {
408 case MCI_FORMAT_MILLISECONDS
:
409 dwFrame
= dwTime
* CDFRAMES_PERSEC
/ 1000;
410 dprintf_cdaudio(stddeb
,
411 "CDAUDIO_CalcFrame // MILLISECONDS %lu\n",
415 dprintf_cdaudio(stddeb
,
416 "CDAUDIO_CalcFrame // MSF %02u:%02u:%02u\n",
417 MCI_MSF_MINUTE(dwTime
), MCI_MSF_SECOND(dwTime
),
418 MCI_MSF_FRAME(dwTime
));
419 dwFrame
+= CDFRAMES_PERMIN
* MCI_MSF_MINUTE(dwTime
);
420 dwFrame
+= CDFRAMES_PERSEC
* MCI_MSF_SECOND(dwTime
);
421 dwFrame
+= MCI_MSF_FRAME(dwTime
);
423 case MCI_FORMAT_TMSF
:
424 wTrack
= MCI_TMSF_TRACK(dwTime
);
425 dprintf_cdaudio(stddeb
,
426 "CDAUDIO_CalcFrame // TMSF %02u-%02u:%02u:%02u\n",
427 MCI_TMSF_TRACK(dwTime
), MCI_TMSF_MINUTE(dwTime
),
428 MCI_TMSF_SECOND(dwTime
), MCI_TMSF_FRAME(dwTime
));
429 dprintf_cdaudio(stddeb
,
430 "CDAUDIO_CalcFrame // TMSF trackpos[%u]=%lu\n",
431 wTrack
, CDADev
[wDevID
].lpdwTrackPos
[wTrack
- 1]);
432 dwFrame
= CDADev
[wDevID
].lpdwTrackPos
[wTrack
- 1];
433 dwFrame
+= CDFRAMES_PERMIN
* MCI_TMSF_MINUTE(dwTime
);
434 dwFrame
+= CDFRAMES_PERSEC
* MCI_TMSF_SECOND(dwTime
);
435 dwFrame
+= MCI_TMSF_FRAME(dwTime
);
438 /* unknown format ! force TMSF ! ... */
439 dwFormatType
= MCI_FORMAT_TMSF
;
447 /**************************************************************************
448 * CDAUDIO_GetNumberOfTracks [internal]
450 UINT
CDAUDIO_GetNumberOfTracks(UINT wDevID
)
453 struct cdrom_tochdr hdr
;
454 if (CDADev
[wDevID
].nTracks
== 0) {
455 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMREADTOCHDR
, &hdr
)) {
457 "GetNumberOfTracks(%u) // Error occured !\n",
461 CDADev
[wDevID
].nTracks
= hdr
.cdth_trk1
;
463 return CDADev
[wDevID
].nTracks
;
469 /**************************************************************************
470 * CDAUDIO_GetTracksInfo [internal]
472 BOOL
CDAUDIO_GetTracksInfo(UINT wDevID
)
476 int start
, last_start
;
477 int total_length
= 0;
478 struct cdrom_tocentry entry
;
479 if (CDADev
[wDevID
].nTracks
== 0) {
480 if (CDAUDIO_GetNumberOfTracks(wDevID
) == (WORD
)-1) return FALSE
;
482 dprintf_cdaudio(stddeb
,"CDAUDIO_GetTracksInfo // nTracks=%u\n",
483 CDADev
[wDevID
].nTracks
);
484 if (CDADev
[wDevID
].lpdwTrackLen
!= NULL
)
485 free(CDADev
[wDevID
].lpdwTrackLen
);
486 CDADev
[wDevID
].lpdwTrackLen
= (LPDWORD
)malloc(
487 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
488 if (CDADev
[wDevID
].lpdwTrackPos
!= NULL
)
489 free(CDADev
[wDevID
].lpdwTrackPos
);
490 CDADev
[wDevID
].lpdwTrackPos
= (LPDWORD
)malloc(
491 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
492 if (CDADev
[wDevID
].lpdwTrackLen
== NULL
||
493 CDADev
[wDevID
].lpdwTrackPos
== NULL
) {
495 "CDAUDIO_GetTracksInfo // error allocating track table !\n");
498 memset(CDADev
[wDevID
].lpdwTrackLen
, 0,
499 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
500 memset(CDADev
[wDevID
].lpdwTrackPos
, 0,
501 (CDADev
[wDevID
].nTracks
+ 1) * sizeof(DWORD
));
502 for (i
= 0; i
<= CDADev
[wDevID
].nTracks
; i
++) {
503 if (i
== CDADev
[wDevID
].nTracks
)
504 entry
.cdte_track
= CDROM_LEADOUT
;
506 entry
.cdte_track
= i
+ 1;
507 entry
.cdte_format
= CDROM_MSF
;
508 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMREADTOCENTRY
, &entry
)) {
510 "CDAUDIO_GetTracksInfo // error read entry\n");
513 start
= CDFRAMES_PERSEC
* (SECONDS_PERMIN
*
514 entry
.cdte_addr
.msf
.minute
+ entry
.cdte_addr
.msf
.second
) +
515 entry
.cdte_addr
.msf
.frame
;
517 CDADev
[wDevID
].dwFirstOffset
= last_start
= 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
);
651 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
652 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
656 return MCIERR_HARDWARE
;
660 /**************************************************************************
661 * CDAUDIO_mciStop [internal]
663 DWORD
CDAUDIO_mciStop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
666 dprintf_cdaudio(stddeb
,"CDAUDIO_mciStop(%u, %08lX, %p);\n",
667 wDevID
, dwFlags
, lpParms
);
668 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
669 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMSTOP
)) return MCIERR_HARDWARE
;
670 CDADev
[wDevID
].mode
= MCI_MODE_STOP
;
671 if (dwFlags
& MCI_NOTIFY
) {
672 dprintf_cdaudio(stddeb
,
673 "CDAUDIO_mciStop // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
674 lpParms
->dwCallback
);
675 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
676 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
680 return MCIERR_HARDWARE
;
684 /**************************************************************************
685 * CDAUDIO_mciPause [internal]
687 DWORD
CDAUDIO_mciPause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
690 dprintf_cdaudio(stddeb
,"CDAUDIO_mciPause(%u, %08lX, %p);\n",
691 wDevID
, dwFlags
, lpParms
);
692 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
693 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMPAUSE
)) return MCIERR_HARDWARE
;
694 CDADev
[wDevID
].mode
= MCI_MODE_PAUSE
;
695 if (dwFlags
& MCI_NOTIFY
) {
696 dprintf_cdaudio(stddeb
,
697 "CDAUDIO_mciPause // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
698 lpParms
->dwCallback
);
699 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
700 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
704 return MCIERR_HARDWARE
;
708 /**************************************************************************
709 * CDAUDIO_mciResume [internal]
711 DWORD
CDAUDIO_mciResume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
714 dprintf_cdaudio(stddeb
,"CDAUDIO_mciResume(%u, %08lX, %p);\n",
715 wDevID
, dwFlags
, lpParms
);
716 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
717 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMRESUME
)) return MCIERR_HARDWARE
;
718 CDADev
[wDevID
].mode
= MCI_MODE_STOP
;
719 if (dwFlags
& MCI_NOTIFY
) {
720 dprintf_cdaudio(stddeb
,
721 "CDAUDIO_mciResume // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
722 lpParms
->dwCallback
);
723 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
724 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
728 return MCIERR_HARDWARE
;
732 /**************************************************************************
733 * CDAUDIO_mciSeek [internal]
735 DWORD
CDAUDIO_mciSeek(UINT wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
)
739 MCI_PLAY_PARMS PlayParms
;
740 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSeek(%u, %08lX, %p);\n",
741 wDevID
, dwFlags
, lpParms
);
742 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
743 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMRESUME
)) return MCIERR_HARDWARE
;
744 CDADev
[wDevID
].mode
= MCI_MODE_SEEK
;
746 case MCI_SEEK_TO_START
:
747 PlayParms
.dwFrom
= 0;
749 case MCI_SEEK_TO_END
:
750 PlayParms
.dwFrom
= CDADev
[wDevID
].dwTotalLen
;
753 PlayParms
.dwFrom
= lpParms
->dwTo
;
756 dwRet
= CDAUDIO_mciPlay(wDevID
, MCI_WAIT
| MCI_FROM
, &PlayParms
);
757 if (dwRet
!= 0) return dwRet
;
758 dwRet
= CDAUDIO_mciStop(wDevID
, MCI_WAIT
, (LPMCI_GENERIC_PARMS
)&PlayParms
);
759 if (dwFlags
& MCI_NOTIFY
) {
760 dprintf_cdaudio(stddeb
,
761 "CDAUDIO_mciSeek // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
762 lpParms
->dwCallback
);
763 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
764 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
768 return MCIERR_HARDWARE
;
773 /**************************************************************************
774 * CDAUDIO_mciSet [internal]
776 DWORD
CDAUDIO_mciSet(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
779 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSet(%u, %08lX, %p);\n",
780 wDevID
, dwFlags
, lpParms
);
781 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
783 printf("CDAUDIO_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
784 printf("CDAUDIO_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
786 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
787 switch (lpParms
->dwTimeFormat
) {
788 case MCI_FORMAT_MILLISECONDS
:
789 dprintf_cdaudio(stddeb
,
790 "CDAUDIO_mciSet // MCI_FORMAT_MILLISECONDS !\n");
793 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSet // MCI_FORMAT_MSF !\n");
795 case MCI_FORMAT_TMSF
:
796 dprintf_cdaudio(stddeb
,"CDAUDIO_mciSet // MCI_FORMAT_TMSF !\n");
799 fprintf(stderr
,"CDAUDIO_mciSet // bad time format !\n");
800 return MCIERR_BAD_TIME_FORMAT
;
802 CDADev
[wDevID
].dwTimeFormat
= lpParms
->dwTimeFormat
;
804 if (dwFlags
& MCI_SET_DOOR_OPEN
) {
805 dprintf_cdaudio(stddeb
,
806 "CDAUDIO_mciSet // MCI_SET_DOOR_OPEN !\n");
807 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMEJECT
)) return MCIERR_HARDWARE
;
808 CDADev
[wDevID
].nTracks
= 0;
810 if (dwFlags
& MCI_SET_DOOR_CLOSED
) {
811 dprintf_cdaudio(stddeb
,
812 "CDAUDIO_mciSet // MCI_SET_DOOR_CLOSED !\n");
813 if (ioctl(CDADev
[wDevID
].unixdev
, CDROMEJECT
)) return MCIERR_HARDWARE
;
814 CDADev
[wDevID
].nTracks
= 0;
816 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
817 if (dwFlags
& MCI_SET_ON
) return MCIERR_UNSUPPORTED_FUNCTION
;
818 if (dwFlags
& MCI_SET_OFF
) return MCIERR_UNSUPPORTED_FUNCTION
;
819 if (dwFlags
& MCI_NOTIFY
) {
820 dprintf_cdaudio(stddeb
,
821 "CDAUDIO_mciSet // MCI_NOTIFY_SUCCESSFUL %08lX !\n",
822 lpParms
->dwCallback
);
823 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
824 CDADev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
828 return MCIERR_HARDWARE
;
833 /**************************************************************************
834 * CDAUDIO_DriverProc [sample driver]
836 LRESULT
CDAUDIO_DriverProc(DWORD dwDevID
, HDRVR hDriv
, WORD wMsg
,
837 DWORD dwParam1
, DWORD dwParam2
)
846 case MCI_OPEN_DRIVER
:
848 return CDAUDIO_mciOpen(dwParam1
, (LPMCI_OPEN_PARMS
)dwParam2
);
850 case MCI_CLOSE_DRIVER
:
852 return CDAUDIO_mciClose(dwDevID
, dwParam1
,
853 (LPMCI_GENERIC_PARMS
)dwParam2
);
858 case DRV_QUERYCONFIGURE
:
861 MessageBox((HWND
)NULL
, "Sample MultiMedia Linux Driver !",
862 "MMLinux Driver", MB_OK
);
865 return (LRESULT
)DRVCNF_RESTART
;
867 return (LRESULT
)DRVCNF_RESTART
;
869 return CDAUDIO_mciGetDevCaps(dwDevID
, dwParam1
,
870 (LPMCI_GETDEVCAPS_PARMS
)dwParam2
);
872 return CDAUDIO_mciInfo(dwDevID
, dwParam1
,
873 (LPMCI_INFO_PARMS
)dwParam2
);
875 return CDAUDIO_mciStatus(dwDevID
, dwParam1
,
876 (LPMCI_STATUS_PARMS
)dwParam2
);
878 return CDAUDIO_mciSet(dwDevID
, dwParam1
,
879 (LPMCI_SET_PARMS
)dwParam2
);
881 return CDAUDIO_mciPlay(dwDevID
, dwParam1
,
882 (LPMCI_PLAY_PARMS
)dwParam2
);
884 return CDAUDIO_mciStop(dwDevID
, dwParam1
,
885 (LPMCI_GENERIC_PARMS
)dwParam2
);
887 return CDAUDIO_mciPause(dwDevID
, dwParam1
,
888 (LPMCI_GENERIC_PARMS
)dwParam2
);
890 return CDAUDIO_mciResume(dwDevID
, dwParam1
,
891 (LPMCI_GENERIC_PARMS
)dwParam2
);
893 return CDAUDIO_mciSeek(dwDevID
, dwParam1
,
894 (LPMCI_SEEK_PARMS
)dwParam2
);
895 case MCI_SET_DOOR_OPEN
:
896 dprintf_cdaudio(stddeb
,
897 "CDAUDIO_DriverProc // MCI_SET_DOOR_OPEN !\n");
898 if (ioctl(CDADev
[dwDevID
].unixdev
, CDROMEJECT
)) return MCIERR_HARDWARE
;
899 CDADev
[dwDevID
].nTracks
= 0;
901 case MCI_SET_DOOR_CLOSED
:
902 dprintf_cdaudio(stddeb
,"CDAUDIO_DriverProc // MCI_SET_DOOR_CLOSED !\n");
903 if (ioctl(CDADev
[dwDevID
].unixdev
, CDROMEJECT
, 1)) return MCIERR_HARDWARE
;
904 CDADev
[dwDevID
].nTracks
= 0;
907 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
910 return MCIERR_HARDWARE
;
915 /*-----------------------------------------------------------------------*/
917 #endif /* #ifdef BUILTIN_MMSYSTEM */