1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * Sample MCI CDAUDIO Wine Driver for Linux
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1998-99 Eric Pouech
12 #include "multimedia.h"
16 DEFAULT_DEBUG_CHANNEL(cdaudio)
20 int nUseCount; /* Incremented for each shared open */
21 BOOL16 fShareable; /* TRUE if first open was shareable */
22 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
23 HANDLE16 hCallback; /* Callback handle for pending notification */
24 MCI_OPEN_PARMS16 openParms;
30 #define MAX_CDAUDIODRV (1)
31 static WINE_MCICDAUDIO CDADev[MAX_CDAUDIODRV];
33 /*-----------------------------------------------------------------------*/
35 /**************************************************************************
36 * CDAUDIO_drvGetDrv [internal]
38 static WINE_MCICDAUDIO* CDAUDIO_drvGetDrv(UINT16 wDevID)
42 for (i = 0; i < MAX_CDAUDIODRV; i++) {
43 if (CDADev[i].wDevID == wDevID) {
50 /**************************************************************************
51 * CDAUDIO_drvOpen [internal]
53 static DWORD CDAUDIO_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
57 for (i = 0; i < MAX_CDAUDIODRV; i++) {
58 if (CDADev[i].wDevID == 0) {
59 CDADev[i].wDevID = modp->wDeviceID;
60 modp->wCustomCommandTable = -1;
61 modp->wType = MCI_DEVTYPE_CD_AUDIO;
62 return modp->wDeviceID;
68 /**************************************************************************
69 * CDAUDIO_drvClose [internal]
71 static DWORD CDAUDIO_drvClose(DWORD dwDevID)
73 WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(dwDevID);
82 /**************************************************************************
83 * CDAUDIO_mciGetOpenDrv [internal]
85 static WINE_MCICDAUDIO* CDAUDIO_mciGetOpenDrv(UINT16 wDevID)
87 WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(wDevID);
89 if (wmcda == NULL || wmcda->nUseCount == 0 || wmcda->wcda.unixdev <= 0) {
90 WARN(cdaudio, "Invalid wDevID=%u\n", wDevID);
96 /**************************************************************************
97 * CDAUDIO_mciMode [internal]
99 static int CDAUDIO_mciMode(int wcdaMode)
102 case WINE_CDA_DONTKNOW: return MCI_MODE_STOP;
103 case WINE_CDA_NOTREADY: return MCI_MODE_STOP;
104 case WINE_CDA_OPEN: return MCI_MODE_OPEN;
105 case WINE_CDA_PLAY: return MCI_MODE_PLAY;
106 case WINE_CDA_STOP: return MCI_MODE_STOP;
107 case WINE_CDA_PAUSE: return MCI_MODE_PAUSE;
109 FIXME(cdaudio, "Unknown mode %04x\n", wcdaMode);
111 return MCI_MODE_STOP;
114 /**************************************************************************
115 * CDAUDIO_mciGetError [internal]
117 static int CDAUDIO_mciGetError(WINE_MCICDAUDIO* wmcda)
119 switch (wmcda->wcda.cdaMode) {
120 case WINE_CDA_DONTKNOW:
121 case WINE_CDA_NOTREADY: return MCIERR_DEVICE_NOT_READY;
122 case WINE_CDA_OPEN: return MCIERR_DEVICE_OPEN;
125 case WINE_CDA_PAUSE: break;
127 FIXME(cdaudio, "Unknown mode %04x\n", wmcda->wcda.cdaMode);
129 return MCIERR_DRIVER_INTERNAL;
132 /**************************************************************************
133 * CDAUDIO_CalcFrame [internal]
135 static DWORD CDAUDIO_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
140 TRACE(cdaudio,"(%p, %08lX, %lu);\n", wmcda, wmcda->dwTimeFormat, dwTime);
142 switch (wmcda->dwTimeFormat) {
143 case MCI_FORMAT_MILLISECONDS:
144 dwFrame = (dwTime * CDFRAMES_PERSEC) / 1000;
145 TRACE(cdaudio, "MILLISECONDS %lu\n", dwFrame);
148 TRACE(cdaudio, "MSF %02u:%02u:%02u\n",
149 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), MCI_MSF_FRAME(dwTime));
150 dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
151 dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
152 dwFrame += MCI_MSF_FRAME(dwTime);
154 case MCI_FORMAT_TMSF:
156 /* unknown format ! force TMSF ! ... */
157 wTrack = MCI_TMSF_TRACK(dwTime);
158 TRACE(cdaudio, "MSF %02u-%02u:%02u:%02u\n",
159 MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
160 MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
161 TRACE(cdaudio, "TMSF trackpos[%u]=%lu\n",
162 wTrack, wmcda->wcda.lpdwTrackPos[wTrack - 1]);
163 dwFrame = wmcda->wcda.lpdwTrackPos[wTrack - 1];
164 dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
165 dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
166 dwFrame += MCI_TMSF_FRAME(dwTime);
172 /**************************************************************************
173 * CDAUDIO_CalcTime [internal]
175 static DWORD CDAUDIO_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD dwFrame)
183 TRACE(cdaudio,"(%p, %08lX, %lu);\n", wmcda, wmcda->dwTimeFormat, dwFrame);
185 switch (wmcda->dwTimeFormat) {
186 case MCI_FORMAT_MILLISECONDS:
187 dwTime = (dwFrame * 1000) / CDFRAMES_PERSEC;
188 TRACE(cdaudio, "MILLISECONDS %lu\n", dwTime);
191 wMinutes = dwFrame / CDFRAMES_PERMIN;
192 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
193 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
194 dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
195 TRACE(cdaudio,"MSF %02u:%02u:%02u -> dwTime=%lu\n",wMinutes, wSeconds, wFrames, dwTime);
197 case MCI_FORMAT_TMSF:
199 /* unknown format ! force TMSF ! ... */
200 for (wTrack = 0; wTrack < wmcda->wcda.nTracks; wTrack++) {
201 /* dwTime += wmcda->lpdwTrackLen[wTrack - 1];
202 TRACE(cdaudio, "Adding trk#%u curpos=%u \n", dwTime);
203 if (dwTime >= dwFrame) break; */
204 if (wmcda->wcda.lpdwTrackPos[wTrack - 1] >= dwFrame) break;
206 wMinutes = dwFrame / CDFRAMES_PERMIN;
207 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
208 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
209 dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
210 TRACE(cdaudio, "%02u-%02u:%02u:%02u\n", wTrack, wMinutes, wSeconds, wFrames);
216 static DWORD CDAUDIO_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms);
217 static DWORD CDAUDIO_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
219 /**************************************************************************
220 * CDAUDIO_mciOpen [internal]
222 static DWORD CDAUDIO_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
225 WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(wDevID);
226 MCI_SEEK_PARMS seekParms;
228 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
230 if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
231 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
233 dwDeviceID = lpOpenParms->wDeviceID;
235 if (wmcda->nUseCount > 0) {
236 /* The driver is already open on this channel */
237 /* If the driver was opened shareable before and this open specifies */
238 /* shareable then increment the use count */
239 if (wmcda->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
242 return MCIERR_MUST_USE_SHAREABLE;
244 wmcda->nUseCount = 1;
245 wmcda->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
247 if (dwFlags & MCI_OPEN_ELEMENT) {
248 TRACE(cdaudio,"MCI_OPEN_ELEMENT !\n");
249 /* return MCIERR_NO_ELEMENT_ALLOWED; */
252 wmcda->openParms.dwCallback = lpOpenParms->dwCallback;
253 wmcda->openParms.wDeviceID = (WORD)lpOpenParms->wDeviceID;
254 wmcda->openParms.wReserved0 = 0; /*????*/
255 wmcda->openParms.lpstrDeviceType = lpOpenParms->lpstrDeviceType;
256 wmcda->openParms.lpstrElementName = lpOpenParms->lpstrElementName;
257 wmcda->openParms.lpstrAlias = lpOpenParms->lpstrAlias;
259 wmcda->wNotifyDeviceID = dwDeviceID;
260 if (CDAUDIO_Open(&wmcda->wcda) == -1) {
262 return MCIERR_HARDWARE;
264 wmcda->mciMode = MCI_MODE_STOP;
265 wmcda->dwTimeFormat = MCI_FORMAT_TMSF;
266 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
267 WARN(cdaudio,"error reading TracksInfo !\n");
268 /* return MCIERR_INTERNAL; */
271 CDAUDIO_mciSeek(wDevID, MCI_SEEK_TO_START, &seekParms);
276 /**************************************************************************
277 * CDAUDIO_mciClose [internal]
279 static DWORD CDAUDIO_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
281 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
283 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwParam, lpParms);
285 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
287 if (wmcda->nUseCount == 1) {
288 /* FIXME: I don't think we have to stop CD on exit
289 * CDAUDIO_mciStop(wDevID, 0, NULL);
291 CDAUDIO_Close(&wmcda->wcda);
297 /**************************************************************************
298 * CDAUDIO_mciGetDevCaps [internal]
300 static DWORD CDAUDIO_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
301 LPMCI_GETDEVCAPS_PARMS lpParms)
303 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
305 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
307 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
308 TRACE(cdaudio, "MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms->dwItem);
310 switch(lpParms->dwItem) {
311 case MCI_GETDEVCAPS_CAN_RECORD:
312 lpParms->dwReturn = FALSE;
314 case MCI_GETDEVCAPS_HAS_AUDIO:
315 lpParms->dwReturn = TRUE;
317 case MCI_GETDEVCAPS_HAS_VIDEO:
318 lpParms->dwReturn = FALSE;
320 case MCI_GETDEVCAPS_DEVICE_TYPE:
321 lpParms->dwReturn = MCI_DEVTYPE_CD_AUDIO;
323 case MCI_GETDEVCAPS_USES_FILES:
324 lpParms->dwReturn = FALSE;
326 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
327 lpParms->dwReturn = FALSE;
329 case MCI_GETDEVCAPS_CAN_EJECT:
330 lpParms->dwReturn = TRUE;
332 case MCI_GETDEVCAPS_CAN_PLAY:
333 lpParms->dwReturn = TRUE;
335 case MCI_GETDEVCAPS_CAN_SAVE:
336 lpParms->dwReturn = FALSE;
339 return MCIERR_UNRECOGNIZED_COMMAND;
342 TRACE(cdaudio, "lpParms->dwReturn=%08lX;\n", lpParms->dwReturn);
346 /**************************************************************************
347 * CDAUDIO_mciInfo [internal]
349 static DWORD CDAUDIO_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
353 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
355 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
357 if (lpParms == NULL || lpParms->lpstrReturn == NULL) {
358 ret = MCIERR_NULL_PARAMETER_BLOCK;
359 } else if (wmcda == NULL) {
360 ret = MCIERR_INVALID_DEVICE_ID;
362 TRACE(cdaudio, "buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
365 case MCI_INFO_PRODUCT:
366 str = "Wine's audio CD";
369 WARN(cdaudio, "Don't know this info command (%lu)\n", dwFlags);
370 ret = MCIERR_UNRECOGNIZED_COMMAND;
374 ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, str);
376 lpParms->lpstrReturn[0] = 0;
382 /**************************************************************************
383 * CDAUDIO_mciStatus [internal]
385 static DWORD CDAUDIO_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
387 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
390 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
392 if (lpParms == NULL) {
393 ret = MCIERR_NULL_PARAMETER_BLOCK;
394 } else if (wmcda == NULL) {
395 ret = MCIERR_INVALID_DEVICE_ID;
397 if (dwFlags & MCI_NOTIFY) {
398 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
399 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
400 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
402 if (dwFlags & MCI_STATUS_ITEM) {
403 switch (lpParms->dwItem) {
404 case MCI_STATUS_CURRENT_TRACK:
405 if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) {
406 return CDAUDIO_mciGetError(wmcda);
408 lpParms->dwReturn = wmcda->wcda.nCurTrack;
409 TRACE(cdaudio,"CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
411 case MCI_STATUS_LENGTH:
412 if (wmcda->wcda.nTracks == 0) {
413 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
414 WARN(cdaudio, "error reading TracksInfo !\n");
415 return CDAUDIO_mciGetError(wmcda);
418 if (dwFlags & MCI_TRACK) {
419 TRACE(cdaudio,"MCI_TRACK #%lu LENGTH=??? !\n", lpParms->dwTrack);
420 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
421 return MCIERR_OUTOFRANGE;
422 lpParms->dwReturn = wmcda->wcda.lpdwTrackLen[lpParms->dwTrack - 1];
424 lpParms->dwReturn = wmcda->wcda.dwTotalLen;
426 lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, lpParms->dwReturn);
427 TRACE(cdaudio,"LENGTH=%lu !\n", lpParms->dwReturn);
429 case MCI_STATUS_MODE:
430 if (!CDAUDIO_GetCDStatus(&wmcda->wcda))
431 return CDAUDIO_mciGetError(wmcda);
432 lpParms->dwReturn = CDAUDIO_mciMode(wmcda->wcda.cdaMode);
433 if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
434 TRACE(cdaudio,"MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
436 case MCI_STATUS_MEDIA_PRESENT:
437 if (!CDAUDIO_GetCDStatus(&wmcda->wcda))
438 return CDAUDIO_mciGetError(wmcda);
439 lpParms->dwReturn = (wmcda->wcda.nTracks > 0) ? TRUE : FALSE;
440 TRACE(cdaudio,"MCI_STATUS_MEDIA_PRESENT =%s!\n", lpParms->dwReturn ? "Y" : "N");
442 case MCI_STATUS_NUMBER_OF_TRACKS:
443 lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(&wmcda->wcda);
444 TRACE(cdaudio,"MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
445 if (lpParms->dwReturn == (WORD)-1)
446 return CDAUDIO_mciGetError(wmcda);
448 case MCI_STATUS_POSITION:
449 if (!CDAUDIO_GetCDStatus(&wmcda->wcda))
450 return CDAUDIO_mciGetError(wmcda);
451 lpParms->dwReturn = wmcda->wcda.dwCurFrame;
452 if (dwFlags & MCI_STATUS_START) {
453 lpParms->dwReturn = wmcda->wcda.dwFirstOffset;
454 TRACE(cdaudio,"get MCI_STATUS_START !\n");
456 if (dwFlags & MCI_TRACK) {
457 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
458 return MCIERR_OUTOFRANGE;
459 lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
460 TRACE(cdaudio,"get MCI_TRACK #%lu !\n", lpParms->dwTrack);
462 lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, lpParms->dwReturn);
463 TRACE(cdaudio,"MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
465 case MCI_STATUS_READY:
466 TRACE(cdaudio,"MCI_STATUS_READY !\n");
467 lpParms->dwReturn = (wmcda->wcda.cdaMode != WINE_CDA_DONTKNOW && wmcda->wcda.cdaMode != WINE_CDA_NOTREADY);
468 TRACE(cdaudio,"MCI_STATUS_READY=%ld!\n", lpParms->dwReturn);
470 case MCI_STATUS_TIME_FORMAT:
471 lpParms->dwReturn = wmcda->dwTimeFormat;
472 TRACE(cdaudio,"MCI_STATUS_TIME_FORMAT =%08lx!\n", lpParms->dwReturn);
474 case MCI_CDA_STATUS_TYPE_TRACK:
475 if (!(dwFlags & MCI_TRACK))
476 return MCIERR_MISSING_PARAMETER;
477 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
478 return MCIERR_OUTOFRANGE;
479 lpParms->dwReturn = (wmcda->wcda.lpbTrackFlags[lpParms->dwTrack - 1] &
480 CDROM_DATA_TRACK) ? MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
481 TRACE(cdaudio, "MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
484 WARN(cdaudio, "unknown command %08lX !\n", lpParms->dwItem);
485 return MCIERR_UNRECOGNIZED_COMMAND;
489 WARN(cdaudio, "not MCI_STATUS_ITEM !\n");
493 /**************************************************************************
494 * CDAUDIO_mciPlay [internal]
496 static DWORD CDAUDIO_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
499 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
502 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
504 if (lpParms == NULL) {
505 ret = MCIERR_NULL_PARAMETER_BLOCK;
506 } else if (wmcda == NULL) {
507 ret = MCIERR_INVALID_DEVICE_ID;
509 if (wmcda->wcda.nTracks == 0) {
510 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
511 WARN(cdaudio, "error reading TracksInfo !\n");
512 return MCIERR_DRIVER_INTERNAL;
515 end = wmcda->wcda.dwFirstOffset + wmcda->wcda.dwTotalLen;
516 wmcda->wcda.nCurTrack = 1;
517 if (dwFlags & MCI_FROM) {
518 start = CDAUDIO_CalcFrame(wmcda, lpParms->dwFrom);
519 TRACE(cdaudio,"MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
521 if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) return MCIERR_DRIVER_INTERNAL;
522 start = wmcda->wcda.dwCurFrame;
524 if (dwFlags & MCI_TO) {
525 end = CDAUDIO_CalcFrame(wmcda, lpParms->dwTo);
526 TRACE(cdaudio, "MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
529 if (CDAUDIO_Play(&wmcda->wcda, start, end) == -1)
530 return MCIERR_HARDWARE;
531 wmcda->mciMode = MCI_MODE_PLAY;
532 if (dwFlags & MCI_NOTIFY) {
533 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
535 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
536 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
543 /**************************************************************************
544 * CDAUDIO_mciStop [internal]
546 static DWORD CDAUDIO_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
548 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
550 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
552 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
554 if (CDAUDIO_Stop(&wmcda->wcda) == -1)
555 return MCIERR_HARDWARE;
556 wmcda->mciMode = MCI_MODE_STOP;
557 if (lpParms && (dwFlags & MCI_NOTIFY)) {
558 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
559 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
560 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
565 /**************************************************************************
566 * CDAUDIO_mciPause [internal]
568 static DWORD CDAUDIO_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
570 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
572 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
574 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
576 if (CDAUDIO_Pause(&wmcda->wcda, 1) == -1)
577 return MCIERR_HARDWARE;
578 wmcda->mciMode = MCI_MODE_PAUSE;
579 if (lpParms && (dwFlags & MCI_NOTIFY)) {
580 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
581 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
582 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
587 /**************************************************************************
588 * CDAUDIO_mciResume [internal]
590 static DWORD CDAUDIO_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
592 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
594 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
596 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
598 if (CDAUDIO_Pause(&wmcda->wcda, 0) == -1)
599 return MCIERR_HARDWARE;
600 wmcda->mciMode = MCI_MODE_STOP;
601 if (lpParms && (dwFlags & MCI_NOTIFY)) {
602 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
603 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
604 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
609 /**************************************************************************
610 * CDAUDIO_mciSeek [internal]
612 static DWORD CDAUDIO_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
615 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
617 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
619 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
620 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
622 wmcda->mciMode = MCI_MODE_SEEK;
623 switch (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)) {
624 case MCI_SEEK_TO_START:
625 TRACE(cdaudio, "Seeking to start\n");
628 case MCI_SEEK_TO_END:
629 TRACE(cdaudio, "Seeking to end\n");
630 at = wmcda->wcda.dwTotalLen;
633 TRACE(cdaudio, "Seeking to %lu\n", lpParms->dwTo);
637 TRACE(cdaudio, "Seeking to ??=%lu\n", dwFlags);
638 return MCIERR_UNSUPPORTED_FUNCTION;
640 if (CDAUDIO_Seek(&wmcda->wcda, at) == -1) {
641 return MCIERR_HARDWARE;
643 if (dwFlags & MCI_NOTIFY) {
644 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
645 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
646 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
651 /**************************************************************************
652 * CDAUDIO_mciSetDoor [internal]
654 static DWORD CDAUDIO_mciSetDoor(UINT16 wDevID, int open)
656 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
658 TRACE(cdaudio, "(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
660 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
662 if (CDAUDIO_SetDoor(&wmcda->wcda, open) == -1)
663 return MCIERR_HARDWARE;
664 wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
668 /**************************************************************************
669 * CDAUDIO_mciSet [internal]
671 static DWORD CDAUDIO_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
673 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
675 TRACE(cdaudio,"(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
677 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
678 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;;
680 TRACE(cdaudio,"dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
681 TRACE(cdaudio,"dwAudio=%08lX\n", lpParms->dwAudio);
683 if (dwFlags & MCI_SET_TIME_FORMAT) {
684 switch (lpParms->dwTimeFormat) {
685 case MCI_FORMAT_MILLISECONDS:
686 TRACE(cdaudio, "MCI_FORMAT_MILLISECONDS !\n");
689 TRACE(cdaudio,"MCI_FORMAT_MSF !\n");
691 case MCI_FORMAT_TMSF:
692 TRACE(cdaudio,"MCI_FORMAT_TMSF !\n");
695 WARN(cdaudio, "bad time format !\n");
696 return MCIERR_BAD_TIME_FORMAT;
698 wmcda->dwTimeFormat = lpParms->dwTimeFormat;
700 if (dwFlags & MCI_SET_DOOR_OPEN) {
701 CDAUDIO_mciSetDoor(wDevID, TRUE);
703 if (dwFlags & MCI_SET_DOOR_CLOSED) {
704 CDAUDIO_mciSetDoor(wDevID, FALSE);
706 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
707 if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
708 if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
709 if (dwFlags & MCI_NOTIFY) {
710 TRACE(cdaudio, "MCI_NOTIFY_SUCCESSFUL %08lX !\n",
711 lpParms->dwCallback);
712 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
713 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
718 /**************************************************************************
719 * MCICDAUDIO_DriverProc [sample driver]
721 LONG MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
722 DWORD dwParam1, DWORD dwParam2)
725 case DRV_LOAD: return 1;
726 case DRV_FREE: return 1;
727 case DRV_OPEN: return CDAUDIO_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
728 case DRV_CLOSE: return CDAUDIO_drvClose(dwDevID);
729 case DRV_ENABLE: return 1;
730 case DRV_DISABLE: return 1;
731 case DRV_QUERYCONFIGURE: return 1;
732 case DRV_CONFIGURE: MessageBoxA(0, "Sample Multimedia Driver !", "Wine Driver", MB_OK); return 1;
733 case DRV_INSTALL: return DRVCNF_RESTART;
734 case DRV_REMOVE: return DRVCNF_RESTART;
736 case MCI_OPEN_DRIVER: return CDAUDIO_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
737 case MCI_CLOSE_DRIVER: return CDAUDIO_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
738 case MCI_GETDEVCAPS: return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
739 case MCI_INFO: return CDAUDIO_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS16)dwParam2);
740 case MCI_STATUS: return CDAUDIO_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
741 case MCI_SET: return CDAUDIO_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
742 case MCI_PLAY: return CDAUDIO_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
743 case MCI_STOP: return CDAUDIO_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
744 case MCI_PAUSE: return CDAUDIO_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
745 case MCI_RESUME: return CDAUDIO_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
746 case MCI_SEEK: return CDAUDIO_mciSeek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
747 /* FIXME: I wonder if those two next items are really called ? */
748 case MCI_SET_DOOR_OPEN: return CDAUDIO_mciSetDoor(dwDevID, TRUE);
749 case MCI_SET_DOOR_CLOSED: return CDAUDIO_mciSetDoor(dwDevID, FALSE);
766 WARN(cdaudio, "Unsupported command=%s\n", MCI_CommandToString(wMsg));
770 FIXME(cdaudio, "Shouldn't receive a MCI_OPEN or CLOSE message\n");
773 TRACE(cdaudio, "Sending msg=%s to default driver proc\n", MCI_CommandToString(wMsg));
774 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
776 return MCIERR_UNRECOGNIZED_COMMAND;
779 /*-----------------------------------------------------------------------*/