- removed (now obsolete) driver.h file (it's content is now in mmsystem.h)
[wine.git] / dlls / winmm / mcicda / mcicda.c
blobc3566453f30e397a185b75f5d806c890325fa313
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*
3 * MCI driver for audio CD (MCICDA)
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1998-99 Eric Pouech
7 * Copyright 2000 Andreas Mohr
8 */
10 #include "config.h"
11 #include <stdio.h>
12 #include "windef.h"
13 #include "wingdi.h"
14 #include "winuser.h"
15 #include "mmddk.h"
16 #include "cdrom.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(mcicda);
21 typedef struct {
22 UINT wDevID;
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 */
27 DWORD dwTimeFormat;
28 WINE_CDAUDIO wcda;
29 int mciMode;
30 } WINE_MCICDAUDIO;
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));
41 if (!wmcda)
42 return 0;
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);
58 if (wmcda) {
59 HeapFree(GetProcessHeap(), 0, wmcda);
60 mciSetDriverData(dwDevID, 0);
62 return 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);
74 return 0;
76 return wmcda;
79 /**************************************************************************
80 * MCICDA_Mode [internal]
82 static int MCICDA_Mode(int wcdaMode)
84 switch (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;
91 default:
92 FIXME("Unknown mode %04x\n", wcdaMode);
94 return MCI_MODE_STOP;
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;
106 case WINE_CDA_PLAY:
107 case WINE_CDA_STOP:
108 case WINE_CDA_PAUSE: break;
109 default:
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)
120 DWORD dwFrame = 0;
121 UINT wTrack;
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);
129 break;
130 case MCI_FORMAT_MSF:
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);
136 break;
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);
149 break;
151 return dwFrame;
154 /**************************************************************************
155 * MCICDA_CalcTime [internal]
157 static DWORD MCICDA_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame,
158 LPDWORD lpRet)
160 DWORD dwTime = 0;
161 UINT wTrack;
162 UINT wMinutes;
163 UINT wSeconds;
164 UINT wFrames;
166 TRACE("(%p, %08lX, %lu);\n", wmcda, tf, dwFrame);
168 switch (tf) {
169 case MCI_FORMAT_MILLISECONDS:
170 dwTime = (dwFrame * 1000) / CDFRAMES_PERSEC + 1;
171 TRACE("MILLISECONDS %lu\n", dwTime);
172 *lpRet = 0;
173 break;
174 case MCI_FORMAT_MSF:
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;
182 break;
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);
188 *lpRet = 0;
189 return 0;
191 for (wTrack = 1; wTrack < wmcda->wcda.nTracks; wTrack++) {
192 if (wmcda->wcda.lpdwTrackPos[wTrack] > dwFrame)
193 break;
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;
202 break;
204 return dwTime;
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)
215 DWORD dwDeviceID;
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))
231 ++wmcda->nUseCount;
232 else
233 return MCIERR_MUST_USE_SHAREABLE;
234 } else {
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) {
250 --wmcda->nUseCount;
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);
262 return 0;
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);
279 wmcda->nUseCount--;
280 return 0;
283 /**************************************************************************
284 * MCICDA_GetDevCaps [internal]
286 static DWORD MCICDA_GetDevCaps(UINT wDevID, DWORD dwFlags,
287 LPMCI_GETDEVCAPS_PARMS lpParms)
289 DWORD ret = 0;
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;
302 break;
303 case MCI_GETDEVCAPS_HAS_AUDIO:
304 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
305 ret = MCI_RESOURCE_RETURNED;
306 break;
307 case MCI_GETDEVCAPS_HAS_VIDEO:
308 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
309 ret = MCI_RESOURCE_RETURNED;
310 break;
311 case MCI_GETDEVCAPS_DEVICE_TYPE:
312 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_CD_AUDIO, MCI_DEVTYPE_CD_AUDIO);
313 ret = MCI_RESOURCE_RETURNED;
314 break;
315 case MCI_GETDEVCAPS_USES_FILES:
316 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
317 ret = MCI_RESOURCE_RETURNED;
318 break;
319 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
320 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
321 ret = MCI_RESOURCE_RETURNED;
322 break;
323 case MCI_GETDEVCAPS_CAN_EJECT:
324 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
325 ret = MCI_RESOURCE_RETURNED;
326 break;
327 case MCI_GETDEVCAPS_CAN_PLAY:
328 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
329 ret = MCI_RESOURCE_RETURNED;
330 break;
331 case MCI_GETDEVCAPS_CAN_SAVE:
332 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
333 ret = MCI_RESOURCE_RETURNED;
334 break;
335 default:
336 ERR("Unsupported %lx devCaps item\n", lpParms->dwItem);
337 return MCIERR_UNRECOGNIZED_COMMAND;
339 } else {
340 TRACE("No GetDevCaps-Item !\n");
341 return MCIERR_UNRECOGNIZED_COMMAND;
343 TRACE("lpParms->dwReturn=%08lX;\n", lpParms->dwReturn);
344 return ret;
347 /**************************************************************************
348 * MCICDA_Info [internal]
350 static DWORD MCICDA_Info(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
352 LPSTR str = NULL;
353 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
354 DWORD ret = 0;
355 char buffer[16];
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) {
370 DWORD res = 0;
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);
385 str = buffer;
386 } else {
387 WARN("Don't know this info command (%lu)\n", dwFlags);
388 ret = MCIERR_UNRECOGNIZED_COMMAND;
390 if (str) {
391 if (lpParms->dwRetSize <= strlen(str)) {
392 lstrcpynA(lpParms->lpstrReturn, str, lpParms->dwRetSize - 1);
393 ret = MCIERR_PARAM_OVERFLOW;
394 } else {
395 strcpy(lpParms->lpstrReturn, str);
397 } else {
398 *lpParms->lpstrReturn = 0;
400 TRACE("=> %s (%ld)\n", lpParms->lpstrReturn, ret);
401 return 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);
410 DWORD ret = 0;
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);
430 break;
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 } else {
444 lpParms->dwReturn = wmcda->wcda.dwLastFrame;
446 lpParms->dwReturn = MCICDA_CalcTime(wmcda,
447 (wmcda->dwTimeFormat == MCI_FORMAT_TMSF)
448 ? MCI_FORMAT_MSF : wmcda->dwTimeFormat,
449 lpParms->dwReturn,
450 &ret);
451 TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
452 break;
453 case MCI_STATUS_MODE:
454 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda))
455 return MCICDA_GetError(wmcda);
456 lpParms->dwReturn = MCICDA_Mode(wmcda->wcda.cdaMode);
457 if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
458 TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
459 lpParms->dwReturn = MAKEMCIRESOURCE(lpParms->dwReturn, lpParms->dwReturn);
460 ret = MCI_RESOURCE_RETURNED;
461 break;
462 case MCI_STATUS_MEDIA_PRESENT:
463 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda))
464 return MCICDA_GetError(wmcda);
465 lpParms->dwReturn = (wmcda->wcda.nTracks == 0) ?
466 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
467 TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms->dwReturn) ? 'Y' : 'N');
468 ret = MCI_RESOURCE_RETURNED;
469 break;
470 case MCI_STATUS_NUMBER_OF_TRACKS:
471 lpParms->dwReturn = CDROM_Audio_GetNumberOfTracks(&wmcda->wcda);
472 TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
473 if (lpParms->dwReturn == (WORD)-1)
474 return MCICDA_GetError(wmcda);
475 break;
476 case MCI_STATUS_POSITION:
477 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda))
478 return MCICDA_GetError(wmcda);
479 lpParms->dwReturn = wmcda->wcda.dwCurFrame;
480 if (dwFlags & MCI_STATUS_START) {
481 lpParms->dwReturn = wmcda->wcda.dwFirstFrame;
482 TRACE("get MCI_STATUS_START !\n");
484 if (dwFlags & MCI_TRACK) {
485 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
486 return MCIERR_OUTOFRANGE;
487 lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
488 TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
490 lpParms->dwReturn = MCICDA_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
491 TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
492 break;
493 case MCI_STATUS_READY:
494 TRACE("MCI_STATUS_READY !\n");
495 lpParms->dwReturn = (wmcda->wcda.cdaMode == WINE_CDA_DONTKNOW ||
496 wmcda->wcda.cdaMode == WINE_CDA_NOTREADY) ?
497 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
498 TRACE("MCI_STATUS_READY=%u!\n", LOWORD(lpParms->dwReturn));
499 ret = MCI_RESOURCE_RETURNED;
500 break;
501 case MCI_STATUS_TIME_FORMAT:
502 lpParms->dwReturn = MAKEMCIRESOURCE(wmcda->dwTimeFormat, wmcda->dwTimeFormat);
503 TRACE("MCI_STATUS_TIME_FORMAT=%08x!\n", LOWORD(lpParms->dwReturn));
504 ret = MCI_RESOURCE_RETURNED;
505 break;
506 case 4001: /* FIXME: for boggus FullCD */
507 case MCI_CDA_STATUS_TYPE_TRACK:
508 if (!(dwFlags & MCI_TRACK))
509 ret = MCIERR_MISSING_PARAMETER;
510 else if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
511 ret = MCIERR_OUTOFRANGE;
512 else
513 lpParms->dwReturn = (wmcda->wcda.lpbTrackFlags[lpParms->dwTrack - 1] &
514 CDROM_DATA_TRACK) ? MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
515 TRACE("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
516 break;
517 default:
518 FIXME("unknown command %08lX !\n", lpParms->dwItem);
519 return MCIERR_UNRECOGNIZED_COMMAND;
521 } else {
522 WARN("not MCI_STATUS_ITEM !\n");
524 return ret;
527 /**************************************************************************
528 * MCICDA_Play [internal]
530 static DWORD MCICDA_Play(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
532 int start, end;
533 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
534 DWORD ret = 0;
536 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
538 if (lpParms == NULL) {
539 ret = MCIERR_NULL_PARAMETER_BLOCK;
540 } else if (wmcda == NULL) {
541 ret = MCIERR_INVALID_DEVICE_ID;
542 } else {
543 if (wmcda->wcda.nTracks == 0) {
544 if (!CDROM_Audio_GetTracksInfo(&wmcda->wcda)) {
545 WARN("error reading TracksInfo !\n");
546 return MCIERR_DRIVER_INTERNAL;
549 wmcda->wcda.nCurTrack = 1;
550 if (dwFlags & MCI_FROM) {
551 start = MCICDA_CalcFrame(wmcda, lpParms->dwFrom);
552 TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
553 } else {
554 if (!CDROM_Audio_GetCDStatus(&wmcda->wcda)) return MCIERR_DRIVER_INTERNAL;
555 start = wmcda->wcda.dwCurFrame;
557 if (dwFlags & MCI_TO) {
558 end = MCICDA_CalcFrame(wmcda, lpParms->dwTo);
559 TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
560 } else {
561 end = wmcda->wcda.dwLastFrame;
564 if (CDROM_Audio_Play(&wmcda->wcda, start, end) == -1)
565 return MCIERR_HARDWARE;
566 wmcda->mciMode = MCI_MODE_PLAY;
567 if (dwFlags & MCI_NOTIFY) {
568 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
570 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
571 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
575 return ret;
578 /**************************************************************************
579 * MCICDA_Stop [internal]
581 static DWORD MCICDA_Stop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
583 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
585 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
587 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
589 if (CDROM_Audio_Stop(&wmcda->wcda) == -1)
590 return MCIERR_HARDWARE;
592 wmcda->mciMode = MCI_MODE_STOP;
593 if (lpParms && (dwFlags & MCI_NOTIFY)) {
594 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
595 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
596 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
598 return 0;
601 /**************************************************************************
602 * MCICDA_Pause [internal]
604 static DWORD MCICDA_Pause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
606 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
608 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
610 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
612 if (CDROM_Audio_Pause(&wmcda->wcda, 1) == -1)
613 return MCIERR_HARDWARE;
614 wmcda->mciMode = MCI_MODE_PAUSE;
615 if (lpParms && (dwFlags & MCI_NOTIFY)) {
616 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
617 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
618 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
620 return 0;
623 /**************************************************************************
624 * MCICDA_Resume [internal]
626 static DWORD MCICDA_Resume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
628 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
630 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
632 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
634 if (CDROM_Audio_Pause(&wmcda->wcda, 0) == -1)
635 return MCIERR_HARDWARE;
636 wmcda->mciMode = MCI_MODE_STOP;
637 if (lpParms && (dwFlags & MCI_NOTIFY)) {
638 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
639 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
640 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
642 return 0;
645 /**************************************************************************
646 * MCICDA_Seek [internal]
648 static DWORD MCICDA_Seek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
650 DWORD at;
651 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
653 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
655 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
656 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
658 wmcda->mciMode = MCI_MODE_SEEK;
659 switch (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)) {
660 case MCI_SEEK_TO_START:
661 TRACE("Seeking to start\n");
662 at = wmcda->wcda.dwFirstFrame;
663 break;
664 case MCI_SEEK_TO_END:
665 TRACE("Seeking to end\n");
666 at = wmcda->wcda.dwLastFrame;
667 break;
668 case MCI_TO:
669 TRACE("Seeking to %lu\n", lpParms->dwTo);
670 at = lpParms->dwTo;
671 break;
672 default:
673 TRACE("Seeking to ??=%lu\n", dwFlags);
674 return MCIERR_UNSUPPORTED_FUNCTION;
676 if (CDROM_Audio_Seek(&wmcda->wcda, at) == -1) {
677 return MCIERR_HARDWARE;
679 if (dwFlags & MCI_NOTIFY) {
680 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
681 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
682 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
684 return 0;
687 /**************************************************************************
688 * MCICDA_SetDoor [internal]
690 static DWORD MCICDA_SetDoor(UINT wDevID, int open)
692 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
694 TRACE("(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
696 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
698 if (CDROM_SetDoor(&wmcda->wcda, open) == -1)
699 return MCIERR_HARDWARE;
700 wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
701 return 0;
704 /**************************************************************************
705 * MCICDA_Set [internal]
707 static DWORD MCICDA_Set(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
709 WINE_MCICDAUDIO* wmcda = MCICDA_GetOpenDrv(wDevID);
711 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
713 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
714 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;;
716 TRACE("dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
717 TRACE("dwAudio=%08lX\n", lpParms->dwAudio);
719 if (dwFlags & MCI_SET_TIME_FORMAT) {
720 switch (lpParms->dwTimeFormat) {
721 case MCI_FORMAT_MILLISECONDS:
722 TRACE("MCI_FORMAT_MILLISECONDS !\n");
723 break;
724 case MCI_FORMAT_MSF:
725 TRACE("MCI_FORMAT_MSF !\n");
726 break;
727 case MCI_FORMAT_TMSF:
728 TRACE("MCI_FORMAT_TMSF !\n");
729 break;
730 default:
731 WARN("bad time format !\n");
732 return MCIERR_BAD_TIME_FORMAT;
734 wmcda->dwTimeFormat = lpParms->dwTimeFormat;
736 if (dwFlags & MCI_SET_DOOR_OPEN) {
737 MCICDA_SetDoor(wDevID, TRUE);
739 if (dwFlags & MCI_SET_DOOR_CLOSED) {
740 MCICDA_SetDoor(wDevID, FALSE);
742 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
743 if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
744 if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
745 if (dwFlags & MCI_NOTIFY) {
746 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n",
747 lpParms->dwCallback);
748 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
749 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
751 return 0;
754 /**************************************************************************
755 * MCICDA_DriverProc [exported]
757 LONG CALLBACK MCICDA_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
758 DWORD dwParam1, DWORD dwParam2)
760 switch(wMsg) {
761 case DRV_LOAD: return 1;
762 case DRV_FREE: return 1;
763 case DRV_OPEN: return MCICDA_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
764 case DRV_CLOSE: return MCICDA_drvClose(dwDevID);
765 case DRV_ENABLE: return 1;
766 case DRV_DISABLE: return 1;
767 case DRV_QUERYCONFIGURE: return 1;
768 case DRV_CONFIGURE: MessageBoxA(0, "MCI audio CD driver !", "Wine Driver", MB_OK); return 1;
769 case DRV_INSTALL: return DRVCNF_RESTART;
770 case DRV_REMOVE: return DRVCNF_RESTART;
772 case MCI_OPEN_DRIVER: return MCICDA_Open(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
773 case MCI_CLOSE_DRIVER: return MCICDA_Close(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
774 case MCI_GETDEVCAPS: return MCICDA_GetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
775 case MCI_INFO: return MCICDA_Info(dwDevID, dwParam1, (LPMCI_INFO_PARMSA)dwParam2);
776 case MCI_STATUS: return MCICDA_Status(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
777 case MCI_SET: return MCICDA_Set(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
778 case MCI_PLAY: return MCICDA_Play(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
779 case MCI_STOP: return MCICDA_Stop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
780 case MCI_PAUSE: return MCICDA_Pause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
781 case MCI_RESUME: return MCICDA_Resume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
782 case MCI_SEEK: return MCICDA_Seek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
783 /* FIXME: I wonder if those two next items are really called ? */
784 case MCI_SET_DOOR_OPEN: FIXME("MCI_SET_DOOR_OPEN called. Please report this.\n");
785 return MCICDA_SetDoor(dwDevID, TRUE);
786 case MCI_SET_DOOR_CLOSED: FIXME("MCI_SET_DOOR_CLOSED called. Please report this.\n");
787 return MCICDA_SetDoor(dwDevID, FALSE);
788 /* commands that should be supported */
789 case MCI_LOAD:
790 case MCI_SAVE:
791 case MCI_FREEZE:
792 case MCI_PUT:
793 case MCI_REALIZE:
794 case MCI_UNFREEZE:
795 case MCI_UPDATE:
796 case MCI_WHERE:
797 case MCI_STEP:
798 case MCI_SPIN:
799 case MCI_ESCAPE:
800 case MCI_COPY:
801 case MCI_CUT:
802 case MCI_DELETE:
803 case MCI_PASTE:
804 FIXME("Unsupported yet command [%lu]\n", wMsg);
805 break;
806 /* commands that should report an error */
807 case MCI_WINDOW:
808 TRACE("Unsupported command [%lu]\n", wMsg);
809 break;
810 case MCI_OPEN:
811 case MCI_CLOSE:
812 ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
813 break;
814 default:
815 TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
816 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
818 return MCIERR_UNRECOGNIZED_COMMAND;
821 /*-----------------------------------------------------------------------*/