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
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(mcicda);
23 int nUseCount; /* Incremented for each shared open */
24 BOOL fShareable; /* TRUE if first open was shareable */
25 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
26 HANDLE hCallback; /* Callback handle for pending notification */
32 /*-----------------------------------------------------------------------*/
34 /**************************************************************************
35 * MCICDA_drvOpen [internal]
37 static DWORD MCICDA_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
39 WINE_MCICDAUDIO* wmcda = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCICDAUDIO));
44 wmcda->wDevID = modp->wDeviceID;
45 mciSetDriverData(wmcda->wDevID, (DWORD)wmcda);
46 modp->wCustomCommandTable = MCI_NO_COMMAND_TABLE;
47 modp->wType = MCI_DEVTYPE_CD_AUDIO;
48 return modp->wDeviceID;
51 /**************************************************************************
52 * MCICDA_drvClose [internal]
54 static DWORD MCICDA_drvClose(DWORD dwDevID)
56 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(dwDevID);
59 HeapFree(GetProcessHeap(), 0, wmcda);
60 mciSetDriverData(dwDevID, 0);
65 /**************************************************************************
66 * MCICDA_GetOpenDrv [internal]
68 static WINE_MCICDAUDIO* MCICDA_GetOpenDrv(UINT wDevID)
70 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
72 if (wmcda == NULL || wmcda->nUseCount == 0 || wmcda->wcda.unixdev <= 0) {
73 WARN("Invalid wDevID=%u\n", wDevID);
79 /**************************************************************************
80 * MCICDA_Mode [internal]
82 static int MCICDA_Mode(int wcdaMode)
85 case WINE_CDA_DONTKNOW: return MCI_MODE_STOP;
86 case WINE_CDA_NOTREADY: return MCI_MODE_STOP;
87 case WINE_CDA_OPEN: return MCI_MODE_OPEN;
88 case WINE_CDA_PLAY: return MCI_MODE_PLAY;
89 case WINE_CDA_STOP: return MCI_MODE_STOP;
90 case WINE_CDA_PAUSE: return MCI_MODE_PAUSE;
92 FIXME("Unknown mode %04x\n", wcdaMode);
97 /**************************************************************************
98 * MCICDA_GetError [internal]
100 static int MCICDA_GetError(WINE_MCICDAUDIO* wmcda)
102 switch (wmcda->wcda.cdaMode) {
103 case WINE_CDA_DONTKNOW:
104 case WINE_CDA_NOTREADY: return MCIERR_DEVICE_NOT_READY;
105 case WINE_CDA_OPEN: return MCIERR_DEVICE_OPEN;
108 case WINE_CDA_PAUSE: break;
110 FIXME("Unknown mode %04x\n", wmcda->wcda.cdaMode);
112 return MCIERR_DRIVER_INTERNAL;
115 /**************************************************************************
116 * MCICDA_CalcFrame [internal]
118 static DWORD MCICDA_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
123 TRACE("(%p, %08lX, %lu);\n", wmcda, wmcda->dwTimeFormat, dwTime);
125 switch (wmcda->dwTimeFormat) {
126 case MCI_FORMAT_MILLISECONDS:
127 dwFrame = ((dwTime - 1) * CDFRAMES_PERSEC + 500) / 1000;
128 TRACE("MILLISECONDS %lu\n", dwFrame);
131 TRACE("MSF %02u:%02u:%02u\n",
132 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), MCI_MSF_FRAME(dwTime));
133 dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
134 dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
135 dwFrame += MCI_MSF_FRAME(dwTime);
137 case MCI_FORMAT_TMSF:
138 default: /* unknown format ! force TMSF ! ... */
139 wTrack = MCI_TMSF_TRACK(dwTime);
140 TRACE("MSF %02u-%02u:%02u:%02u\n",
141 MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
142 MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
143 TRACE("TMSF trackpos[%u]=%lu\n",
144 wTrack, wmcda->wcda.lpdwTrackPos[wTrack - 1]);
145 dwFrame = wmcda->wcda.lpdwTrackPos[wTrack - 1];
146 dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
147 dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
148 dwFrame += MCI_TMSF_FRAME(dwTime);
154 /**************************************************************************
155 * MCICDA_CalcTime [internal]
157 static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame,
166 TRACE("(%p, %08lX, %lu);\n", wmcda, tf, dwFrame);
169 case MCI_FORMAT_MILLISECONDS:
170 dwTime = (dwFrame * 1000) / CDFRAMES_PERSEC + 1;
171 TRACE("MILLISECONDS %lu\n", dwTime);
175 wMinutes = dwFrame / CDFRAMES_PERMIN;
176 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
177 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
178 dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
179 TRACE("MSF %02u:%02u:%02u -> dwTime=%lu\n",
180 wMinutes, wSeconds, wFrames, dwTime);
181 *lpRet = MCI_COLONIZED3_RETURN;
183 case MCI_FORMAT_TMSF:
184 default: /* unknown format ! force TMSF ! ... */
185 if (dwFrame < wmcda->wcda.dwFirstFrame || dwFrame > wmcda->wcda.dwLastFrame) {
186 ERR("Out of range value %lu [%lu,%lu]\n",
187 dwFrame, wmcda->wcda.dwFirstFrame, wmcda->wcda.dwLastFrame);
191 for (wTrack = 1; wTrack < wmcda->wcda.nTracks; wTrack++) {
192 if (wmcda->wcda.lpdwTrackPos[wTrack] > dwFrame)
195 dwFrame -= wmcda->wcda.lpdwTrackPos[wTrack - 1];
196 wMinutes = dwFrame / CDFRAMES_PERMIN;
197 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
198 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
199 dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
200 TRACE("%02u-%02u:%02u:%02u\n", wTrack, wMinutes, wSeconds, wFrames);
201 *lpRet = MCI_COLONIZED4_RETURN;
207 static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms);
208 static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
210 /**************************************************************************
211 * MCICDA_Open [internal]
213 static DWORD MCICDA_Open(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
216 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
217 MCI_SEEK_PARMS seekParms;
219 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
221 if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
222 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
224 dwDeviceID = lpOpenParms->wDeviceID;
226 if (wmcda->nUseCount > 0) {
227 /* The driver is already open on this channel */
228 /* If the driver was opened shareable before and this open specifies */
229 /* shareable then increment the use count */
230 if (wmcda->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
233 return MCIERR_MUST_USE_SHAREABLE;
235 wmcda->nUseCount = 1;
236 wmcda->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
238 if (dwFlags & MCI_OPEN_ELEMENT) {
239 if (dwFlags & MCI_OPEN_ELEMENT_ID) {
240 WARN("MCI_OPEN_ELEMENT_ID %8lx ! Abort", (DWORD)lpOpenParms->lpstrElementName);
241 return MCIERR_NO_ELEMENT_ALLOWED;
243 WARN("MCI_OPEN_ELEMENT %s ignored\n",lpOpenParms->lpstrElementName);
244 /*return MCIERR_NO_ELEMENT_ALLOWED;
245 bon 19991106 allows cdplayer.exe to run*/
248 wmcda->wNotifyDeviceID = dwDeviceID;
249 if (CDROM_Open(&wmcda->wcda, -1) == -1) {
251 return MCIERR_HARDWARE;
253 wmcda->mciMode = MCI_MODE_STOP;
254 wmcda->dwTimeFormat = MCI_FORMAT_MSF;
255 if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
256 WARN("error reading TracksInfo !\n");
257 return MCIERR_INTERNAL;
260 MCICDA_Seek(wDevID, MCI_SEEK_TO_START, &seekParms);
265 /**************************************************************************
266 * MCICDA_Close [internal]
268 static DWORD MCICDA_Close(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
270 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
272 TRACE("(%04X, %08lX, %p);\n", wDevID, dwParam, lpParms);
274 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
276 if (wmcda->nUseCount == 1) {
277 CDROM_Close(&wmcda->wcda);
283 /**************************************************************************
284 * MCICDA_GetDevCaps [internal]
286 static DWORD MCICDA_GetDevCaps(UINT wDevID, DWORD dwFlags,
287 LPMCI_GETDEVCAPS_PARMS lpParms)
291 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
293 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
295 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
296 TRACE("MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms->dwItem);
298 switch (lpParms->dwItem) {
299 case MCI_GETDEVCAPS_CAN_RECORD:
300 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
301 ret = MCI_RESOURCE_RETURNED;
303 case MCI_GETDEVCAPS_HAS_AUDIO:
304 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
305 ret = MCI_RESOURCE_RETURNED;
307 case MCI_GETDEVCAPS_HAS_VIDEO:
308 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
309 ret = MCI_RESOURCE_RETURNED;
311 case MCI_GETDEVCAPS_DEVICE_TYPE:
312 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_CD_AUDIO, MCI_DEVTYPE_CD_AUDIO);
313 ret = MCI_RESOURCE_RETURNED;
315 case MCI_GETDEVCAPS_USES_FILES:
316 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
317 ret = MCI_RESOURCE_RETURNED;
319 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
320 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
321 ret = MCI_RESOURCE_RETURNED;
323 case MCI_GETDEVCAPS_CAN_EJECT:
324 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
325 ret = MCI_RESOURCE_RETURNED;
327 case MCI_GETDEVCAPS_CAN_PLAY:
328 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
329 ret = MCI_RESOURCE_RETURNED;
331 case MCI_GETDEVCAPS_CAN_SAVE:
332 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
333 ret = MCI_RESOURCE_RETURNED;
336 ERR("Unsupported %lx devCaps item\n", lpParms->dwItem);
337 return MCIERR_UNRECOGNIZED_COMMAND;
340 TRACE("No GetDevCaps-Item !\n");
341 return MCIERR_UNRECOGNIZED_COMMAND;
343 TRACE("lpParms->dwReturn=%08lX;\n", lpParms->dwReturn);
347 /**************************************************************************
348 * MCICDA_Info [internal]
350 static DWORD MCICDA_Info(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
353 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
357 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
359 if (lpParms == NULL || lpParms->lpstrReturn == NULL)
360 return MCIERR_NULL_PARAMETER_BLOCK;
361 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
363 TRACE("buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
365 if (dwFlags & MCI_INFO_PRODUCT) {
366 str = "Wine's audio CD";
367 } else if (dwFlags & MCI_INFO_MEDIA_UPC) {
368 ret = MCIERR_NO_IDENTITY;
369 } else if (dwFlags & MCI_INFO_MEDIA_IDENTITY) {
372 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) {
373 return MCICDA_GetError(wmcda);
376 res = CDROM_Audio_GetSerial(&wmcda->wcda);
377 if (wmcda->wcda.nTracks <= 2) {
378 /* there are some other values added when # of tracks < 3
379 * for most Audio CD it will do without
381 FIXME("Value is not correct !! "
382 "Please report with full audio CD information (-debugmsg +cdrom,mcicda)\n");
384 sprintf(buffer, "%lu", res);
387 WARN("Don't know this info command (%lu)\n", dwFlags);
388 ret = MCIERR_UNRECOGNIZED_COMMAND;
391 if (lpParms->dwRetSize <= strlen(str)) {
392 lstrcpynA(lpParms->lpstrReturn, str, lpParms->dwRetSize - 1);
393 ret = MCIERR_PARAM_OVERFLOW;
395 strcpy(lpParms->lpstrReturn, str);
398 *lpParms->lpstrReturn = 0;
400 TRACE("=> %s (%ld)\n", lpParms->lpstrReturn, ret);
404 /**************************************************************************
405 * MCICDA_Status [internal]
407 static DWORD MCICDA_Status(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
409 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
412 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
414 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
415 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
417 if (dwFlags & MCI_NOTIFY) {
418 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
419 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
420 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
422 if (dwFlags & MCI_STATUS_ITEM) {
423 switch (lpParms->dwItem) {
424 case MCI_STATUS_CURRENT_TRACK:
425 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) {
426 return MCICDA_GetError(wmcda);
428 lpParms->dwReturn = wmcda->wcda.nCurTrack;
429 TRACE("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
431 case MCI_STATUS_LENGTH:
432 if (wmcda->wcda.nTracks == 0) {
433 if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
434 WARN("error reading TracksInfo !\n");
435 return MCICDA_GetError(wmcda);
438 if (dwFlags & MCI_TRACK) {
439 TRACE("MCI_TRACK #%lu LENGTH=??? !\n", lpParms->dwTrack);
440 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
441 return MCIERR_OUTOFRANGE;
442 lpParms->dwReturn = wmcda->wcda.lpdwTrackLen[lpParms->dwTrack - 1];
443 /* Windows returns one frame less than the total track length for the
444 last track on the CD. See CDDB HOWTO. Verified on Win95OSR2. */
445 if (lpParms->dwTrack == wmcda->wcda.nTracks)
448 /* Sum of the lengths of all of the tracks. Inherits the
449 'off by one frame' behavior from the length of the last track.
450 See above comment. */
451 lpParms->dwReturn = wmcda->wcda.dwLastFrame - wmcda->wcda.dwFirstFrame - 1;
453 lpParms->dwReturn = MCICDA_CalcTime(wmcda,
454 (wmcda->dwTimeFormat == MCI_FORMAT_TMSF)
455 ? MCI_FORMAT_MSF : wmcda->dwTimeFormat,
458 TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
460 case MCI_STATUS_MODE:
461 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda))
462 return MCICDA_GetError(wmcda);
463 lpParms->dwReturn = MCICDA_Mode(wmcda->wcda.cdaMode);
464 if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
465 TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
466 lpParms->dwReturn = MAKEMCIRESOURCE(lpParms->dwReturn, lpParms->dwReturn);
467 ret = MCI_RESOURCE_RETURNED;
469 case MCI_STATUS_MEDIA_PRESENT:
470 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda))
471 return MCICDA_GetError(wmcda);
472 lpParms->dwReturn = (wmcda->wcda.nTracks == 0) ?
473 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
474 TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms->dwReturn) ? 'Y' : 'N');
475 ret = MCI_RESOURCE_RETURNED;
477 case MCI_STATUS_NUMBER_OF_TRACKS:
478 lpParms->dwReturn = CDROM_Audio_GetNumberOfTracks(&wmcda->wcda);
479 TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
480 if (lpParms->dwReturn == (WORD)-1)
481 return MCICDA_GetError(wmcda);
483 case MCI_STATUS_POSITION:
484 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda))
485 return MCICDA_GetError(wmcda);
486 lpParms->dwReturn = wmcda->wcda.dwCurFrame;
487 if (dwFlags & MCI_STATUS_START) {
488 lpParms->dwReturn = wmcda->wcda.dwFirstFrame;
489 TRACE("get MCI_STATUS_START !\n");
491 if (dwFlags & MCI_TRACK) {
492 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
493 return MCIERR_OUTOFRANGE;
494 lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
495 TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
497 lpParms->dwReturn = MCICDA_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
498 TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
500 case MCI_STATUS_READY:
501 TRACE("MCI_STATUS_READY !\n");
502 lpParms->dwReturn = (wmcda->wcda.cdaMode == WINE_CDA_DONTKNOW ||
503 wmcda->wcda.cdaMode == WINE_CDA_NOTREADY) ?
504 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
505 TRACE("MCI_STATUS_READY=%u!\n", LOWORD(lpParms->dwReturn));
506 ret = MCI_RESOURCE_RETURNED;
508 case MCI_STATUS_TIME_FORMAT:
509 lpParms->dwReturn = MAKEMCIRESOURCE(wmcda->dwTimeFormat, wmcda->dwTimeFormat);
510 TRACE("MCI_STATUS_TIME_FORMAT=%08x!\n", LOWORD(lpParms->dwReturn));
511 ret = MCI_RESOURCE_RETURNED;
513 case 4001: /* FIXME: for bogus FullCD */
514 case MCI_CDA_STATUS_TYPE_TRACK:
515 if (!(dwFlags & MCI_TRACK))
516 ret = MCIERR_MISSING_PARAMETER;
517 else if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
518 ret = MCIERR_OUTOFRANGE;
520 lpParms->dwReturn = (wmcda->wcda.lpbTrackFlags[lpParms->dwTrack - 1] &
521 CDROM_DATA_TRACK) ? MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
522 TRACE("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
525 FIXME("unknown command %08lX !\n", lpParms->dwItem);
526 return MCIERR_UNRECOGNIZED_COMMAND;
529 WARN("not MCI_STATUS_ITEM !\n");
534 /**************************************************************************
535 * MCICDA_Play [internal]
537 static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
540 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
543 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
545 if (lpParms == NULL) {
546 ret = MCIERR_NULL_PARAMETER_BLOCK;
547 } else if (wmcda == NULL) {
548 ret = MCIERR_INVALID_DEVICE_ID;
550 if (wmcda->wcda.nTracks == 0) {
551 if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
552 WARN("error reading TracksInfo !\n");
553 return MCIERR_DRIVER_INTERNAL;
556 wmcda->wcda.nCurTrack = 1;
557 if (dwFlags & MCI_FROM) {
558 start = MCICDA_CalcFrame(wmcda, lpParms->dwFrom);
559 TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
561 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) return MCIERR_DRIVER_INTERNAL;
562 start = wmcda->wcda.dwCurFrame;
564 if (dwFlags & MCI_TO) {
565 end = MCICDA_CalcFrame(wmcda, lpParms->dwTo);
566 TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
568 end = wmcda->wcda.dwLastFrame;
571 if (CDROM_Audio_Play(&wmcda->wcda, start, end) == -1)
572 return MCIERR_HARDWARE;
573 wmcda->mciMode = MCI_MODE_PLAY;
574 if (dwFlags & MCI_NOTIFY) {
575 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
577 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
578 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
585 /**************************************************************************
586 * MCICDA_Stop [internal]
588 static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
590 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
592 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
594 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
596 if (CDROM_Audio_Stop(&wmcda->wcda) == -1)
597 return MCIERR_HARDWARE;
599 wmcda->mciMode = MCI_MODE_STOP;
600 if (lpParms && (dwFlags & MCI_NOTIFY)) {
601 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
602 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
603 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
608 /**************************************************************************
609 * MCICDA_Pause [internal]
611 static DWORD MCICDA_Pause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
613 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
615 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
617 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
619 if (CDROM_Audio_Pause(&wmcda->wcda, 1) == -1)
620 return MCIERR_HARDWARE;
621 wmcda->mciMode = MCI_MODE_PAUSE;
622 if (lpParms && (dwFlags & MCI_NOTIFY)) {
623 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
624 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
625 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
630 /**************************************************************************
631 * MCICDA_Resume [internal]
633 static DWORD MCICDA_Resume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
635 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
637 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
639 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
641 if (CDROM_Audio_Pause(&wmcda->wcda, 0) == -1)
642 return MCIERR_HARDWARE;
643 wmcda->mciMode = MCI_MODE_STOP;
644 if (lpParms && (dwFlags & MCI_NOTIFY)) {
645 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
646 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
647 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
652 /**************************************************************************
653 * MCICDA_Seek [internal]
655 static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
658 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
660 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
662 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
663 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
665 wmcda->mciMode = MCI_MODE_SEEK;
666 switch (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)) {
667 case MCI_SEEK_TO_START:
668 TRACE("Seeking to start\n");
669 at = wmcda->wcda.dwFirstFrame;
671 case MCI_SEEK_TO_END:
672 TRACE("Seeking to end\n");
673 at = wmcda->wcda.dwLastFrame;
676 TRACE("Seeking to %lu\n", lpParms->dwTo);
680 TRACE("Seeking to ??=%lu\n", dwFlags);
681 return MCIERR_UNSUPPORTED_FUNCTION;
683 if (CDROM_Audio_Seek(&wmcda->wcda, at) == -1) {
684 return MCIERR_HARDWARE;
686 if (dwFlags & MCI_NOTIFY) {
687 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
688 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
689 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
694 /**************************************************************************
695 * MCICDA_SetDoor [internal]
697 static DWORD MCICDA_SetDoor(UINT wDevID, int open)
699 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
701 TRACE("(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
703 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
705 if (CDROM_SetDoor(&wmcda->wcda, open) == -1)
706 return MCIERR_HARDWARE;
707 wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
711 /**************************************************************************
712 * MCICDA_Set [internal]
714 static DWORD MCICDA_Set(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
716 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
718 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
720 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
721 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
723 TRACE("dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
724 TRACE("dwAudio=%08lX\n", lpParms->dwAudio);
726 if (dwFlags & MCI_SET_TIME_FORMAT) {
727 switch (lpParms->dwTimeFormat) {
728 case MCI_FORMAT_MILLISECONDS:
729 TRACE("MCI_FORMAT_MILLISECONDS !\n");
732 TRACE("MCI_FORMAT_MSF !\n");
734 case MCI_FORMAT_TMSF:
735 TRACE("MCI_FORMAT_TMSF !\n");
738 WARN("bad time format !\n");
739 return MCIERR_BAD_TIME_FORMAT;
741 wmcda->dwTimeFormat = lpParms->dwTimeFormat;
743 if (dwFlags & MCI_SET_DOOR_OPEN) {
744 MCICDA_SetDoor(wDevID, TRUE);
746 if (dwFlags & MCI_SET_DOOR_CLOSED) {
747 MCICDA_SetDoor(wDevID, FALSE);
749 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
750 if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
751 if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
752 if (dwFlags & MCI_NOTIFY) {
753 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n",
754 lpParms->dwCallback);
755 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
756 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
761 /**************************************************************************
762 * MCICDA_DriverProc [exported]
764 LONG CALLBACK MCICDA_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
765 DWORD dwParam1, DWORD dwParam2)
768 case DRV_LOAD: return 1;
769 case DRV_FREE: return 1;
770 case DRV_OPEN: return MCICDA_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
771 case DRV_CLOSE: return MCICDA_drvClose(dwDevID);
772 case DRV_ENABLE: return 1;
773 case DRV_DISABLE: return 1;
774 case DRV_QUERYCONFIGURE: return 1;
775 case DRV_CONFIGURE: MessageBoxA(0, "MCI audio CD driver !", "Wine Driver", MB_OK); return 1;
776 case DRV_INSTALL: return DRVCNF_RESTART;
777 case DRV_REMOVE: return DRVCNF_RESTART;
779 case MCI_OPEN_DRIVER: return MCICDA_Open(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
780 case MCI_CLOSE_DRIVER: return MCICDA_Close(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
781 case MCI_GETDEVCAPS: return MCICDA_GetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
782 case MCI_INFO: return MCICDA_Info(dwDevID, dwParam1, (LPMCI_INFO_PARMSA)dwParam2);
783 case MCI_STATUS: return MCICDA_Status(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
784 case MCI_SET: return MCICDA_Set(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
785 case MCI_PLAY: return MCICDA_Play(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
786 case MCI_STOP: return MCICDA_Stop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
787 case MCI_PAUSE: return MCICDA_Pause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
788 case MCI_RESUME: return MCICDA_Resume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
789 case MCI_SEEK: return MCICDA_Seek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
790 /* FIXME: I wonder if those two next items are really called ? */
791 case MCI_SET_DOOR_OPEN: FIXME("MCI_SET_DOOR_OPEN called. Please report this.\n");
792 return MCICDA_SetDoor(dwDevID, TRUE);
793 case MCI_SET_DOOR_CLOSED: FIXME("MCI_SET_DOOR_CLOSED called. Please report this.\n");
794 return MCICDA_SetDoor(dwDevID, FALSE);
795 /* commands that should be supported */
811 FIXME("Unsupported yet command [%lu]\n", wMsg);
813 /* commands that should report an error */
815 TRACE("Unsupported command [%lu]\n", wMsg);
819 ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
822 TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
823 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
825 return MCIERR_UNRECOGNIZED_COMMAND;
828 /*-----------------------------------------------------------------------*/