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 /*-----------------------------------------------------------------------*/