1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * MCI driver for audio CD (MCICDA)
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1998-99 Eric Pouech
7 * Copyright 2000 Andreas Mohr
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(mcicda
);
24 int nUseCount
; /* Incremented for each shared open */
25 BOOL fShareable
; /* TRUE if first open was shareable */
26 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
27 HANDLE hCallback
; /* Callback handle for pending notification */
33 /*-----------------------------------------------------------------------*/
35 /**************************************************************************
36 * MCICDA_drvOpen [internal]
38 static DWORD
MCICDA_drvOpen(LPSTR str
, LPMCI_OPEN_DRIVER_PARMSA modp
)
40 WINE_MCICDAUDIO
* wmcda
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WINE_MCICDAUDIO
));
45 wmcda
->wDevID
= modp
->wDeviceID
;
46 mciSetDriverData(wmcda
->wDevID
, (DWORD
)wmcda
);
47 modp
->wCustomCommandTable
= MCI_NO_COMMAND_TABLE
;
48 modp
->wType
= MCI_DEVTYPE_CD_AUDIO
;
49 return modp
->wDeviceID
;
52 /**************************************************************************
53 * MCICDA_drvClose [internal]
55 static DWORD
MCICDA_drvClose(DWORD dwDevID
)
57 WINE_MCICDAUDIO
* wmcda
= (WINE_MCICDAUDIO
*)mciGetDriverData(dwDevID
);
60 HeapFree(GetProcessHeap(), 0, wmcda
);
61 mciSetDriverData(dwDevID
, 0);
66 /**************************************************************************
67 * MCICDA_GetOpenDrv [internal]
69 static WINE_MCICDAUDIO
* MCICDA_GetOpenDrv(UINT wDevID
)
71 WINE_MCICDAUDIO
* wmcda
= (WINE_MCICDAUDIO
*)mciGetDriverData(wDevID
);
73 if (wmcda
== NULL
|| wmcda
->nUseCount
== 0 || wmcda
->wcda
.unixdev
<= 0) {
74 WARN("Invalid wDevID=%u\n", wDevID
);
80 /**************************************************************************
81 * MCICDA_Mode [internal]
83 static int MCICDA_Mode(int wcdaMode
)
86 case WINE_CDA_DONTKNOW
: return MCI_MODE_STOP
;
87 case WINE_CDA_NOTREADY
: return MCI_MODE_STOP
;
88 case WINE_CDA_OPEN
: return MCI_MODE_OPEN
;
89 case WINE_CDA_PLAY
: return MCI_MODE_PLAY
;
90 case WINE_CDA_STOP
: return MCI_MODE_STOP
;
91 case WINE_CDA_PAUSE
: return MCI_MODE_PAUSE
;
93 FIXME("Unknown mode %04x\n", wcdaMode
);
98 /**************************************************************************
99 * MCICDA_GetError [internal]
101 static int MCICDA_GetError(WINE_MCICDAUDIO
* wmcda
)
103 switch (wmcda
->wcda
.cdaMode
) {
104 case WINE_CDA_DONTKNOW
:
105 case WINE_CDA_NOTREADY
: return MCIERR_DEVICE_NOT_READY
;
106 case WINE_CDA_OPEN
: return MCIERR_DEVICE_OPEN
;
109 case WINE_CDA_PAUSE
: break;
111 FIXME("Unknown mode %04x\n", wmcda
->wcda
.cdaMode
);
113 return MCIERR_DRIVER_INTERNAL
;
116 /**************************************************************************
117 * MCICDA_CalcFrame [internal]
119 static DWORD
MCICDA_CalcFrame(WINE_MCICDAUDIO
* wmcda
, DWORD dwTime
)
124 TRACE("(%p, %08lX, %lu);\n", wmcda
, wmcda
->dwTimeFormat
, dwTime
);
126 switch (wmcda
->dwTimeFormat
) {
127 case MCI_FORMAT_MILLISECONDS
:
128 dwFrame
= ((dwTime
- 1) * CDFRAMES_PERSEC
+ 500) / 1000;
129 TRACE("MILLISECONDS %lu\n", dwFrame
);
132 TRACE("MSF %02u:%02u:%02u\n",
133 MCI_MSF_MINUTE(dwTime
), MCI_MSF_SECOND(dwTime
), MCI_MSF_FRAME(dwTime
));
134 dwFrame
+= CDFRAMES_PERMIN
* MCI_MSF_MINUTE(dwTime
);
135 dwFrame
+= CDFRAMES_PERSEC
* MCI_MSF_SECOND(dwTime
);
136 dwFrame
+= MCI_MSF_FRAME(dwTime
);
138 case MCI_FORMAT_TMSF
:
139 default: /* unknown format ! force TMSF ! ... */
140 wTrack
= MCI_TMSF_TRACK(dwTime
);
141 TRACE("MSF %02u-%02u:%02u:%02u\n",
142 MCI_TMSF_TRACK(dwTime
), MCI_TMSF_MINUTE(dwTime
),
143 MCI_TMSF_SECOND(dwTime
), MCI_TMSF_FRAME(dwTime
));
144 TRACE("TMSF trackpos[%u]=%lu\n",
145 wTrack
, wmcda
->wcda
.lpdwTrackPos
[wTrack
- 1]);
146 dwFrame
= wmcda
->wcda
.lpdwTrackPos
[wTrack
- 1];
147 dwFrame
+= CDFRAMES_PERMIN
* MCI_TMSF_MINUTE(dwTime
);
148 dwFrame
+= CDFRAMES_PERSEC
* MCI_TMSF_SECOND(dwTime
);
149 dwFrame
+= MCI_TMSF_FRAME(dwTime
);
155 /**************************************************************************
156 * MCICDA_CalcTime [internal]
158 static DWORD
MCICDA_CalcTime(WINE_MCICDAUDIO
* wmcda
, DWORD tf
, DWORD dwFrame
,
167 TRACE("(%p, %08lX, %lu);\n", wmcda
, tf
, dwFrame
);
170 case MCI_FORMAT_MILLISECONDS
:
171 dwTime
= (dwFrame
* 1000) / CDFRAMES_PERSEC
+ 1;
172 TRACE("MILLISECONDS %lu\n", dwTime
);
176 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
177 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
178 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
- CDFRAMES_PERSEC
* wSeconds
;
179 dwTime
= MCI_MAKE_MSF(wMinutes
, wSeconds
, wFrames
);
180 TRACE("MSF %02u:%02u:%02u -> dwTime=%lu\n",
181 wMinutes
, wSeconds
, wFrames
, dwTime
);
182 *lpRet
= MCI_COLONIZED3_RETURN
;
184 case MCI_FORMAT_TMSF
:
185 default: /* unknown format ! force TMSF ! ... */
186 if (dwFrame
< wmcda
->wcda
.dwFirstFrame
|| dwFrame
> wmcda
->wcda
.dwLastFrame
) {
187 ERR("Out of range value %lu [%lu,%lu]\n",
188 dwFrame
, wmcda
->wcda
.dwFirstFrame
, wmcda
->wcda
.dwLastFrame
);
192 for (wTrack
= 1; wTrack
< wmcda
->wcda
.nTracks
; wTrack
++) {
193 if (wmcda
->wcda
.lpdwTrackPos
[wTrack
] > dwFrame
)
196 dwFrame
-= wmcda
->wcda
.lpdwTrackPos
[wTrack
- 1];
197 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
198 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
199 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
- CDFRAMES_PERSEC
* wSeconds
;
200 dwTime
= MCI_MAKE_TMSF(wTrack
, wMinutes
, wSeconds
, wFrames
);
201 TRACE("%02u-%02u:%02u:%02u\n", wTrack
, wMinutes
, wSeconds
, wFrames
);
202 *lpRet
= MCI_COLONIZED4_RETURN
;
208 static DWORD
MCICDA_Seek(UINT wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
);
209 static DWORD
MCICDA_Stop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
211 /**************************************************************************
212 * MCICDA_Open [internal]
214 static DWORD
MCICDA_Open(UINT wDevID
, DWORD dwFlags
, LPMCI_OPEN_PARMSA lpOpenParms
)
217 WINE_MCICDAUDIO
* wmcda
= (WINE_MCICDAUDIO
*)mciGetDriverData(wDevID
);
218 MCI_SEEK_PARMS seekParms
;
220 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpOpenParms
);
222 if (lpOpenParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
223 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
225 dwDeviceID
= lpOpenParms
->wDeviceID
;
227 if (wmcda
->nUseCount
> 0) {
228 /* The driver is already open on this channel */
229 /* If the driver was opened shareable before and this open specifies */
230 /* shareable then increment the use count */
231 if (wmcda
->fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
234 return MCIERR_MUST_USE_SHAREABLE
;
236 wmcda
->nUseCount
= 1;
237 wmcda
->fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
239 if (dwFlags
& MCI_OPEN_ELEMENT
) {
240 if (dwFlags
& MCI_OPEN_ELEMENT_ID
) {
241 WARN("MCI_OPEN_ELEMENT_ID %8lx ! Abort", (DWORD
)lpOpenParms
->lpstrElementName
);
242 return MCIERR_NO_ELEMENT_ALLOWED
;
244 WARN("MCI_OPEN_ELEMENT %s ignored\n",lpOpenParms
->lpstrElementName
);
245 /*return MCIERR_NO_ELEMENT_ALLOWED;
246 bon 19991106 allows cdplayer.exe to run*/
249 wmcda
->wNotifyDeviceID
= dwDeviceID
;
250 if (CDROM_Open(&wmcda
->wcda
, -1) == -1) {
252 return MCIERR_HARDWARE
;
254 wmcda
->mciMode
= MCI_MODE_STOP
;
255 wmcda
->dwTimeFormat
= MCI_FORMAT_MSF
;
256 if (!CDROM_Audio_GetTracksInfo(&wmcda
->wcda
)) {
257 WARN("error reading TracksInfo !\n");
258 return MCIERR_INTERNAL
;
261 MCICDA_Seek(wDevID
, MCI_SEEK_TO_START
, &seekParms
);
266 /**************************************************************************
267 * MCICDA_Close [internal]
269 static DWORD
MCICDA_Close(UINT wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
271 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
273 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
275 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
277 if (wmcda
->nUseCount
== 1) {
278 CDROM_Close(&wmcda
->wcda
);
284 /**************************************************************************
285 * MCICDA_GetDevCaps [internal]
287 static DWORD
MCICDA_GetDevCaps(UINT wDevID
, DWORD dwFlags
,
288 LPMCI_GETDEVCAPS_PARMS lpParms
)
292 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
294 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
296 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
297 TRACE("MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms
->dwItem
);
299 switch (lpParms
->dwItem
) {
300 case MCI_GETDEVCAPS_CAN_RECORD
:
301 lpParms
->dwReturn
= MAKEMCIRESOURCE(FALSE
, MCI_FALSE
);
302 ret
= MCI_RESOURCE_RETURNED
;
304 case MCI_GETDEVCAPS_HAS_AUDIO
:
305 lpParms
->dwReturn
= MAKEMCIRESOURCE(TRUE
, MCI_TRUE
);
306 ret
= MCI_RESOURCE_RETURNED
;
308 case MCI_GETDEVCAPS_HAS_VIDEO
:
309 lpParms
->dwReturn
= MAKEMCIRESOURCE(FALSE
, MCI_FALSE
);
310 ret
= MCI_RESOURCE_RETURNED
;
312 case MCI_GETDEVCAPS_DEVICE_TYPE
:
313 lpParms
->dwReturn
= MAKEMCIRESOURCE(MCI_DEVTYPE_CD_AUDIO
, MCI_DEVTYPE_CD_AUDIO
);
314 ret
= MCI_RESOURCE_RETURNED
;
316 case MCI_GETDEVCAPS_USES_FILES
:
317 lpParms
->dwReturn
= MAKEMCIRESOURCE(FALSE
, MCI_FALSE
);
318 ret
= MCI_RESOURCE_RETURNED
;
320 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
321 lpParms
->dwReturn
= MAKEMCIRESOURCE(FALSE
, MCI_FALSE
);
322 ret
= MCI_RESOURCE_RETURNED
;
324 case MCI_GETDEVCAPS_CAN_EJECT
:
325 lpParms
->dwReturn
= MAKEMCIRESOURCE(TRUE
, MCI_TRUE
);
326 ret
= MCI_RESOURCE_RETURNED
;
328 case MCI_GETDEVCAPS_CAN_PLAY
:
329 lpParms
->dwReturn
= MAKEMCIRESOURCE(TRUE
, MCI_TRUE
);
330 ret
= MCI_RESOURCE_RETURNED
;
332 case MCI_GETDEVCAPS_CAN_SAVE
:
333 lpParms
->dwReturn
= MAKEMCIRESOURCE(FALSE
, MCI_FALSE
);
334 ret
= MCI_RESOURCE_RETURNED
;
337 ERR("Unsupported %lx devCaps item\n", lpParms
->dwItem
);
338 return MCIERR_UNRECOGNIZED_COMMAND
;
341 TRACE("No GetDevCaps-Item !\n");
342 return MCIERR_UNRECOGNIZED_COMMAND
;
344 TRACE("lpParms->dwReturn=%08lX;\n", lpParms
->dwReturn
);
348 /**************************************************************************
349 * MCICDA_Info [internal]
351 static DWORD
MCICDA_Info(UINT wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMSA lpParms
)
354 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
358 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
360 if (lpParms
== NULL
|| lpParms
->lpstrReturn
== NULL
)
361 return MCIERR_NULL_PARAMETER_BLOCK
;
362 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
364 TRACE("buf=%p, len=%lu\n", lpParms
->lpstrReturn
, lpParms
->dwRetSize
);
366 if (dwFlags
& MCI_INFO_PRODUCT
) {
367 str
= "Wine's audio CD";
368 } else if (dwFlags
& MCI_INFO_MEDIA_UPC
) {
369 ret
= MCIERR_NO_IDENTITY
;
370 } else if (dwFlags
& MCI_INFO_MEDIA_IDENTITY
) {
373 if (!CDROM_Audio_GetCDStatus(&wmcda
->wcda
)) {
374 return MCICDA_GetError(wmcda
);
377 res
= CDROM_Audio_GetSerial(&wmcda
->wcda
);
378 if (wmcda
->wcda
.nTracks
<= 2) {
379 /* there are some other values added when # of tracks < 3
380 * for most Audio CD it will do without
382 FIXME("Value is not correct !! "
383 "Please report with full audio CD information (-debugmsg +cdrom,mcicda)\n");
385 sprintf(buffer
, "%lu", res
);
388 WARN("Don't know this info command (%lu)\n", dwFlags
);
389 ret
= MCIERR_UNRECOGNIZED_COMMAND
;
392 if (lpParms
->dwRetSize
<= strlen(str
)) {
393 lstrcpynA(lpParms
->lpstrReturn
, str
, lpParms
->dwRetSize
- 1);
394 ret
= MCIERR_PARAM_OVERFLOW
;
396 strcpy(lpParms
->lpstrReturn
, str
);
399 *lpParms
->lpstrReturn
= 0;
401 TRACE("=> %s (%ld)\n", lpParms
->lpstrReturn
, ret
);
405 /**************************************************************************
406 * MCICDA_Status [internal]
408 static DWORD
MCICDA_Status(UINT wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
410 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
413 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
415 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
416 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
418 if (dwFlags
& MCI_NOTIFY
) {
419 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
420 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
421 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
423 if (dwFlags
& MCI_STATUS_ITEM
) {
424 switch (lpParms
->dwItem
) {
425 case MCI_STATUS_CURRENT_TRACK
:
426 if (!CDROM_Audio_GetCDStatus(&wmcda
->wcda
)) {
427 return MCICDA_GetError(wmcda
);
429 lpParms
->dwReturn
= wmcda
->wcda
.nCurTrack
;
430 TRACE("CURRENT_TRACK=%lu!\n", lpParms
->dwReturn
);
432 case MCI_STATUS_LENGTH
:
433 if (wmcda
->wcda
.nTracks
== 0) {
434 if (!CDROM_Audio_GetTracksInfo(&wmcda
->wcda
)) {
435 WARN("error reading TracksInfo !\n");
436 return MCICDA_GetError(wmcda
);
439 if (dwFlags
& MCI_TRACK
) {
440 TRACE("MCI_TRACK #%lu LENGTH=??? !\n", lpParms
->dwTrack
);
441 if (lpParms
->dwTrack
> wmcda
->wcda
.nTracks
|| lpParms
->dwTrack
== 0)
442 return MCIERR_OUTOFRANGE
;
443 lpParms
->dwReturn
= wmcda
->wcda
.lpdwTrackLen
[lpParms
->dwTrack
- 1];
445 lpParms
->dwReturn
= wmcda
->wcda
.dwLastFrame
;
447 lpParms
->dwReturn
= MCICDA_CalcTime(wmcda
,
448 (wmcda
->dwTimeFormat
== MCI_FORMAT_TMSF
)
449 ? MCI_FORMAT_MSF
: wmcda
->dwTimeFormat
,
452 TRACE("LENGTH=%lu !\n", lpParms
->dwReturn
);
454 case MCI_STATUS_MODE
:
455 if (!CDROM_Audio_GetCDStatus(&wmcda
->wcda
))
456 return MCICDA_GetError(wmcda
);
457 lpParms
->dwReturn
= MCICDA_Mode(wmcda
->wcda
.cdaMode
);
458 if (!lpParms
->dwReturn
) lpParms
->dwReturn
= wmcda
->mciMode
;
459 TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms
->dwReturn
);
460 lpParms
->dwReturn
= MAKEMCIRESOURCE(lpParms
->dwReturn
, lpParms
->dwReturn
);
461 ret
= MCI_RESOURCE_RETURNED
;
463 case MCI_STATUS_MEDIA_PRESENT
:
464 if (!CDROM_Audio_GetCDStatus(&wmcda
->wcda
))
465 return MCICDA_GetError(wmcda
);
466 lpParms
->dwReturn
= (wmcda
->wcda
.nTracks
== 0) ?
467 MAKEMCIRESOURCE(FALSE
, MCI_FALSE
) : MAKEMCIRESOURCE(TRUE
, MCI_TRUE
);
468 TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms
->dwReturn
) ? 'Y' : 'N');
469 ret
= MCI_RESOURCE_RETURNED
;
471 case MCI_STATUS_NUMBER_OF_TRACKS
:
472 lpParms
->dwReturn
= CDROM_Audio_GetNumberOfTracks(&wmcda
->wcda
);
473 TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms
->dwReturn
);
474 if (lpParms
->dwReturn
== (WORD
)-1)
475 return MCICDA_GetError(wmcda
);
477 case MCI_STATUS_POSITION
:
478 if (!CDROM_Audio_GetCDStatus(&wmcda
->wcda
))
479 return MCICDA_GetError(wmcda
);
480 lpParms
->dwReturn
= wmcda
->wcda
.dwCurFrame
;
481 if (dwFlags
& MCI_STATUS_START
) {
482 lpParms
->dwReturn
= wmcda
->wcda
.dwFirstFrame
;
483 TRACE("get MCI_STATUS_START !\n");
485 if (dwFlags
& MCI_TRACK
) {
486 if (lpParms
->dwTrack
> wmcda
->wcda
.nTracks
|| lpParms
->dwTrack
== 0)
487 return MCIERR_OUTOFRANGE
;
488 lpParms
->dwReturn
= wmcda
->wcda
.lpdwTrackPos
[lpParms
->dwTrack
- 1];
489 TRACE("get MCI_TRACK #%lu !\n", lpParms
->dwTrack
);
491 lpParms
->dwReturn
= MCICDA_CalcTime(wmcda
, wmcda
->dwTimeFormat
, lpParms
->dwReturn
, &ret
);
492 TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms
->dwReturn
);
494 case MCI_STATUS_READY
:
495 TRACE("MCI_STATUS_READY !\n");
496 lpParms
->dwReturn
= (wmcda
->wcda
.cdaMode
== WINE_CDA_DONTKNOW
||
497 wmcda
->wcda
.cdaMode
== WINE_CDA_NOTREADY
) ?
498 MAKEMCIRESOURCE(FALSE
, MCI_FALSE
) : MAKEMCIRESOURCE(TRUE
, MCI_TRUE
);
499 TRACE("MCI_STATUS_READY=%u!\n", LOWORD(lpParms
->dwReturn
));
500 ret
= MCI_RESOURCE_RETURNED
;
502 case MCI_STATUS_TIME_FORMAT
:
503 lpParms
->dwReturn
= MAKEMCIRESOURCE(wmcda
->dwTimeFormat
, wmcda
->dwTimeFormat
);
504 TRACE("MCI_STATUS_TIME_FORMAT=%08x!\n", LOWORD(lpParms
->dwReturn
));
505 ret
= MCI_RESOURCE_RETURNED
;
507 case 4001: /* FIXME: for boggus FullCD */
508 case MCI_CDA_STATUS_TYPE_TRACK
:
509 if (!(dwFlags
& MCI_TRACK
))
510 ret
= MCIERR_MISSING_PARAMETER
;
511 else if (lpParms
->dwTrack
> wmcda
->wcda
.nTracks
|| lpParms
->dwTrack
== 0)
512 ret
= MCIERR_OUTOFRANGE
;
514 lpParms
->dwReturn
= (wmcda
->wcda
.lpbTrackFlags
[lpParms
->dwTrack
- 1] &
515 CDROM_DATA_TRACK
) ? MCI_CDA_TRACK_OTHER
: MCI_CDA_TRACK_AUDIO
;
516 TRACE("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms
->dwTrack
, lpParms
->dwReturn
);
519 FIXME("unknown command %08lX !\n", lpParms
->dwItem
);
520 return MCIERR_UNRECOGNIZED_COMMAND
;
523 WARN("not MCI_STATUS_ITEM !\n");
528 /**************************************************************************
529 * MCICDA_Play [internal]
531 static DWORD
MCICDA_Play(UINT wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
534 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
537 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
539 if (lpParms
== NULL
) {
540 ret
= MCIERR_NULL_PARAMETER_BLOCK
;
541 } else if (wmcda
== NULL
) {
542 ret
= MCIERR_INVALID_DEVICE_ID
;
544 if (wmcda
->wcda
.nTracks
== 0) {
545 if (!CDROM_Audio_GetTracksInfo(&wmcda
->wcda
)) {
546 WARN("error reading TracksInfo !\n");
547 return MCIERR_DRIVER_INTERNAL
;
550 wmcda
->wcda
.nCurTrack
= 1;
551 if (dwFlags
& MCI_FROM
) {
552 start
= MCICDA_CalcFrame(wmcda
, lpParms
->dwFrom
);
553 TRACE("MCI_FROM=%08lX -> %u \n", lpParms
->dwFrom
, start
);
555 if (!CDROM_Audio_GetCDStatus(&wmcda
->wcda
)) return MCIERR_DRIVER_INTERNAL
;
556 start
= wmcda
->wcda
.dwCurFrame
;
558 if (dwFlags
& MCI_TO
) {
559 end
= MCICDA_CalcFrame(wmcda
, lpParms
->dwTo
);
560 TRACE("MCI_TO=%08lX -> %u \n", lpParms
->dwTo
, end
);
562 end
= wmcda
->wcda
.dwLastFrame
;
565 if (CDROM_Audio_Play(&wmcda
->wcda
, start
, end
) == -1)
566 return MCIERR_HARDWARE
;
567 wmcda
->mciMode
= MCI_MODE_PLAY
;
568 if (dwFlags
& MCI_NOTIFY
) {
569 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
571 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
572 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
579 /**************************************************************************
580 * MCICDA_Stop [internal]
582 static DWORD
MCICDA_Stop(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
584 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
586 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
588 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
590 if (CDROM_Audio_Stop(&wmcda
->wcda
) == -1)
591 return MCIERR_HARDWARE
;
593 wmcda
->mciMode
= MCI_MODE_STOP
;
594 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
595 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
596 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
597 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
602 /**************************************************************************
603 * MCICDA_Pause [internal]
605 static DWORD
MCICDA_Pause(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
607 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
609 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
611 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
613 if (CDROM_Audio_Pause(&wmcda
->wcda
, 1) == -1)
614 return MCIERR_HARDWARE
;
615 wmcda
->mciMode
= MCI_MODE_PAUSE
;
616 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
617 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
618 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
619 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
624 /**************************************************************************
625 * MCICDA_Resume [internal]
627 static DWORD
MCICDA_Resume(UINT wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
629 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
631 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
633 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
635 if (CDROM_Audio_Pause(&wmcda
->wcda
, 0) == -1)
636 return MCIERR_HARDWARE
;
637 wmcda
->mciMode
= MCI_MODE_STOP
;
638 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
639 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
640 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
641 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
646 /**************************************************************************
647 * MCICDA_Seek [internal]
649 static DWORD
MCICDA_Seek(UINT wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
)
652 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
654 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
656 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
657 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
659 wmcda
->mciMode
= MCI_MODE_SEEK
;
660 switch (dwFlags
& ~(MCI_NOTIFY
|MCI_WAIT
)) {
661 case MCI_SEEK_TO_START
:
662 TRACE("Seeking to start\n");
663 at
= wmcda
->wcda
.dwFirstFrame
;
665 case MCI_SEEK_TO_END
:
666 TRACE("Seeking to end\n");
667 at
= wmcda
->wcda
.dwLastFrame
;
670 TRACE("Seeking to %lu\n", lpParms
->dwTo
);
674 TRACE("Seeking to ??=%lu\n", dwFlags
);
675 return MCIERR_UNSUPPORTED_FUNCTION
;
677 if (CDROM_Audio_Seek(&wmcda
->wcda
, at
) == -1) {
678 return MCIERR_HARDWARE
;
680 if (dwFlags
& MCI_NOTIFY
) {
681 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
682 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
683 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
688 /**************************************************************************
689 * MCICDA_SetDoor [internal]
691 static DWORD
MCICDA_SetDoor(UINT wDevID
, int open
)
693 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
695 TRACE("(%04x, %s) !\n", wDevID
, (open
) ? "OPEN" : "CLOSE");
697 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
699 if (CDROM_SetDoor(&wmcda
->wcda
, open
) == -1)
700 return MCIERR_HARDWARE
;
701 wmcda
->mciMode
= (open
) ? MCI_MODE_OPEN
: MCI_MODE_STOP
;
705 /**************************************************************************
706 * MCICDA_Set [internal]
708 static DWORD
MCICDA_Set(UINT wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
710 WINE_MCICDAUDIO
* wmcda
= MCICDA_GetOpenDrv(wDevID
);
712 TRACE("(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
714 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
715 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;;
717 TRACE("dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
718 TRACE("dwAudio=%08lX\n", lpParms->dwAudio);
720 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
721 switch (lpParms
->dwTimeFormat
) {
722 case MCI_FORMAT_MILLISECONDS
:
723 TRACE("MCI_FORMAT_MILLISECONDS !\n");
726 TRACE("MCI_FORMAT_MSF !\n");
728 case MCI_FORMAT_TMSF
:
729 TRACE("MCI_FORMAT_TMSF !\n");
732 WARN("bad time format !\n");
733 return MCIERR_BAD_TIME_FORMAT
;
735 wmcda
->dwTimeFormat
= lpParms
->dwTimeFormat
;
737 if (dwFlags
& MCI_SET_DOOR_OPEN
) {
738 MCICDA_SetDoor(wDevID
, TRUE
);
740 if (dwFlags
& MCI_SET_DOOR_CLOSED
) {
741 MCICDA_SetDoor(wDevID
, FALSE
);
743 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
744 if (dwFlags
& MCI_SET_ON
) return MCIERR_UNSUPPORTED_FUNCTION
;
745 if (dwFlags
& MCI_SET_OFF
) return MCIERR_UNSUPPORTED_FUNCTION
;
746 if (dwFlags
& MCI_NOTIFY
) {
747 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n",
748 lpParms
->dwCallback
);
749 mciDriverNotify((HWND
)LOWORD(lpParms
->dwCallback
),
750 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
755 /**************************************************************************
756 * MCICDA_DriverProc [exported]
758 LONG CALLBACK
MCICDA_DriverProc(DWORD dwDevID
, HDRVR hDriv
, DWORD wMsg
,
759 DWORD dwParam1
, DWORD dwParam2
)
762 case DRV_LOAD
: return 1;
763 case DRV_FREE
: return 1;
764 case DRV_OPEN
: return MCICDA_drvOpen((LPSTR
)dwParam1
, (LPMCI_OPEN_DRIVER_PARMSA
)dwParam2
);
765 case DRV_CLOSE
: return MCICDA_drvClose(dwDevID
);
766 case DRV_ENABLE
: return 1;
767 case DRV_DISABLE
: return 1;
768 case DRV_QUERYCONFIGURE
: return 1;
769 case DRV_CONFIGURE
: MessageBoxA(0, "MCI audio CD driver !", "Wine Driver", MB_OK
); return 1;
770 case DRV_INSTALL
: return DRVCNF_RESTART
;
771 case DRV_REMOVE
: return DRVCNF_RESTART
;
773 case MCI_OPEN_DRIVER
: return MCICDA_Open(dwDevID
, dwParam1
, (LPMCI_OPEN_PARMSA
)dwParam2
);
774 case MCI_CLOSE_DRIVER
: return MCICDA_Close(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
775 case MCI_GETDEVCAPS
: return MCICDA_GetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)dwParam2
);
776 case MCI_INFO
: return MCICDA_Info(dwDevID
, dwParam1
, (LPMCI_INFO_PARMSA
)dwParam2
);
777 case MCI_STATUS
: return MCICDA_Status(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)dwParam2
);
778 case MCI_SET
: return MCICDA_Set(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)dwParam2
);
779 case MCI_PLAY
: return MCICDA_Play(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)dwParam2
);
780 case MCI_STOP
: return MCICDA_Stop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
781 case MCI_PAUSE
: return MCICDA_Pause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
782 case MCI_RESUME
: return MCICDA_Resume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
783 case MCI_SEEK
: return MCICDA_Seek(dwDevID
, dwParam1
, (LPMCI_SEEK_PARMS
)dwParam2
);
784 /* FIXME: I wonder if those two next items are really called ? */
785 case MCI_SET_DOOR_OPEN
: FIXME("MCI_SET_DOOR_OPEN called. Please report this.\n");
786 return MCICDA_SetDoor(dwDevID
, TRUE
);
787 case MCI_SET_DOOR_CLOSED
: FIXME("MCI_SET_DOOR_CLOSED called. Please report this.\n");
788 return MCICDA_SetDoor(dwDevID
, FALSE
);
789 /* commands that should be supported */
805 FIXME("Unsupported yet command [%lu]\n", wMsg
);
807 /* commands that should report an error */
809 TRACE("Unsupported command [%lu]\n", wMsg
);
813 ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
816 TRACE("Sending msg [%lu] to default driver proc\n", wMsg
);
817 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
819 return MCIERR_UNRECOGNIZED_COMMAND
;
822 /*-----------------------------------------------------------------------*/