Some more pidl-types.
[wine.git] / multimedia / mcicda.c
blobd0d363c051dd2b5e22736d818c5b2e0d7ce86fdc
1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
2 /*
3 * Sample MCI CDAUDIO Wine Driver for Linux
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1998-99 Eric Pouech
7 */
9 #include <sys/types.h>
10 #include "winuser.h"
11 #include "driver.h"
12 #include "multimedia.h"
13 #include "cdrom.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(cdaudio)
18 typedef struct {
19 UINT16 wDevID;
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;
25 DWORD dwTimeFormat;
26 WINE_CDAUDIO wcda;
27 int mciMode;
28 } WINE_MCICDAUDIO;
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)
40 int i;
42 for (i = 0; i < MAX_CDAUDIODRV; i++) {
43 if (CDADev[i].wDevID == wDevID) {
44 return &CDADev[i];
47 return 0;
50 /**************************************************************************
51 * CDAUDIO_drvOpen [internal]
53 static DWORD CDAUDIO_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
55 int i;
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;
65 return 0;
68 /**************************************************************************
69 * CDAUDIO_drvClose [internal]
71 static DWORD CDAUDIO_drvClose(DWORD dwDevID)
73 WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(dwDevID);
75 if (wmcda) {
76 wmcda->wDevID = 0;
77 return 1;
79 return 0;
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("Invalid wDevID=%u\n", wDevID);
91 return 0;
93 return wmcda;
96 /**************************************************************************
97 * CDAUDIO_mciMode [internal]
99 static int CDAUDIO_mciMode(int wcdaMode)
101 switch (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;
108 default:
109 FIXME("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;
123 case WINE_CDA_PLAY:
124 case WINE_CDA_STOP:
125 case WINE_CDA_PAUSE: break;
126 default:
127 FIXME("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)
137 DWORD dwFrame = 0;
138 UINT16 wTrack;
140 TRACE("(%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("MILLISECONDS %lu\n", dwFrame);
146 break;
147 case MCI_FORMAT_MSF:
148 TRACE("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);
153 break;
154 case MCI_FORMAT_TMSF:
155 default:
156 /* unknown format ! force TMSF ! ... */
157 wTrack = MCI_TMSF_TRACK(dwTime);
158 TRACE("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("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);
167 break;
169 return dwFrame;
172 /**************************************************************************
173 * CDAUDIO_CalcTime [internal]
175 static DWORD CDAUDIO_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD dwFrame)
177 DWORD dwTime = 0;
178 UINT16 wTrack;
179 UINT16 wMinutes;
180 UINT16 wSeconds;
181 UINT16 wFrames;
183 TRACE("(%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("MILLISECONDS %lu\n", dwTime);
189 break;
190 case MCI_FORMAT_MSF:
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("MSF %02u:%02u:%02u -> dwTime=%lu\n",wMinutes, wSeconds, wFrames, dwTime);
196 break;
197 case MCI_FORMAT_TMSF:
198 default:
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("%02u-%02u:%02u:%02u\n", wTrack, wMinutes, wSeconds, wFrames);
211 break;
213 return dwTime;
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)
224 DWORD dwDeviceID;
225 WINE_MCICDAUDIO* wmcda = CDAUDIO_drvGetDrv(wDevID);
226 MCI_SEEK_PARMS seekParms;
228 TRACE("(%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))
240 ++wmcda->nUseCount;
241 else
242 return MCIERR_MUST_USE_SHAREABLE;
243 } else {
244 wmcda->nUseCount = 1;
245 wmcda->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
247 if (dwFlags & MCI_OPEN_ELEMENT) {
248 TRACE("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) {
261 --wmcda->nUseCount;
262 return MCIERR_HARDWARE;
264 wmcda->mciMode = MCI_MODE_STOP;
265 wmcda->dwTimeFormat = MCI_FORMAT_TMSF;
266 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
267 WARN("error reading TracksInfo !\n");
268 /* return MCIERR_INTERNAL; */
271 CDAUDIO_mciSeek(wDevID, MCI_SEEK_TO_START, &seekParms);
273 return 0;
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("(%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);
293 wmcda->nUseCount--;
294 return 0;
297 /**************************************************************************
298 * CDAUDIO_mciGetDevCaps [internal]
300 static DWORD CDAUDIO_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
301 LPMCI_GETDEVCAPS_PARMS lpParms)
303 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
305 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
307 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
308 TRACE("MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms->dwItem);
310 switch(lpParms->dwItem) {
311 case MCI_GETDEVCAPS_CAN_RECORD:
312 lpParms->dwReturn = FALSE;
313 break;
314 case MCI_GETDEVCAPS_HAS_AUDIO:
315 lpParms->dwReturn = TRUE;
316 break;
317 case MCI_GETDEVCAPS_HAS_VIDEO:
318 lpParms->dwReturn = FALSE;
319 break;
320 case MCI_GETDEVCAPS_DEVICE_TYPE:
321 lpParms->dwReturn = MCI_DEVTYPE_CD_AUDIO;
322 break;
323 case MCI_GETDEVCAPS_USES_FILES:
324 lpParms->dwReturn = FALSE;
325 break;
326 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
327 lpParms->dwReturn = FALSE;
328 break;
329 case MCI_GETDEVCAPS_CAN_EJECT:
330 lpParms->dwReturn = TRUE;
331 break;
332 case MCI_GETDEVCAPS_CAN_PLAY:
333 lpParms->dwReturn = TRUE;
334 break;
335 case MCI_GETDEVCAPS_CAN_SAVE:
336 lpParms->dwReturn = FALSE;
337 break;
338 default:
339 return MCIERR_UNRECOGNIZED_COMMAND;
342 TRACE("lpParms->dwReturn=%08lX;\n", lpParms->dwReturn);
343 return 0;
346 /**************************************************************************
347 * CDAUDIO_mciInfo [internal]
349 static DWORD CDAUDIO_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
351 DWORD ret = 0;
352 LPSTR str = 0;
353 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
355 TRACE("(%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;
361 } else {
362 TRACE("buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
364 switch(dwFlags) {
365 case MCI_INFO_PRODUCT:
366 str = "Wine's audio CD";
367 break;
368 default:
369 WARN("Don't know this info command (%lu)\n", dwFlags);
370 ret = MCIERR_UNRECOGNIZED_COMMAND;
373 if (str) {
374 ret = MCI_WriteString(lpParms->lpstrReturn, lpParms->dwRetSize, str);
375 } else {
376 lpParms->lpstrReturn[0] = 0;
379 return ret;
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);
388 DWORD ret = 0;
390 TRACE("(%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;
396 } else {
397 if (dwFlags & MCI_NOTIFY) {
398 TRACE("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("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
410 return 0;
411 case MCI_STATUS_LENGTH:
412 if (wmcda->wcda.nTracks == 0) {
413 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
414 WARN("error reading TracksInfo !\n");
415 return CDAUDIO_mciGetError(wmcda);
418 if (dwFlags & MCI_TRACK) {
419 TRACE("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];
423 } else {
424 lpParms->dwReturn = wmcda->wcda.dwTotalLen;
426 lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, lpParms->dwReturn);
427 TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
428 return 0;
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("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
435 return 0;
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("MCI_STATUS_MEDIA_PRESENT =%s!\n", lpParms->dwReturn ? "Y" : "N");
441 return 0;
442 case MCI_STATUS_NUMBER_OF_TRACKS:
443 lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(&wmcda->wcda);
444 TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
445 if (lpParms->dwReturn == (WORD)-1)
446 return CDAUDIO_mciGetError(wmcda);
447 return 0;
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("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("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
462 lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, lpParms->dwReturn);
463 TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
464 return 0;
465 case MCI_STATUS_READY:
466 TRACE("MCI_STATUS_READY !\n");
467 lpParms->dwReturn = (wmcda->wcda.cdaMode != WINE_CDA_DONTKNOW && wmcda->wcda.cdaMode != WINE_CDA_NOTREADY);
468 TRACE("MCI_STATUS_READY=%ld!\n", lpParms->dwReturn);
469 return 0;
470 case MCI_STATUS_TIME_FORMAT:
471 lpParms->dwReturn = wmcda->dwTimeFormat;
472 TRACE("MCI_STATUS_TIME_FORMAT =%08lx!\n", lpParms->dwReturn);
473 return 0;
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("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
482 return 0;
483 default:
484 WARN("unknown command %08lX !\n", lpParms->dwItem);
485 return MCIERR_UNRECOGNIZED_COMMAND;
489 WARN("not MCI_STATUS_ITEM !\n");
490 return 0;
493 /**************************************************************************
494 * CDAUDIO_mciPlay [internal]
496 static DWORD CDAUDIO_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
498 int start, end;
499 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
500 DWORD ret = 0;
502 TRACE("(%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;
508 } else {
509 if (wmcda->wcda.nTracks == 0) {
510 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
511 WARN("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("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
520 } else {
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("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("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
535 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
536 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
540 return ret;
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("(%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("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
559 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
560 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
562 return 0;
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("(%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("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
581 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
582 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
584 return 0;
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("(%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("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
603 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
604 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
606 return 0;
609 /**************************************************************************
610 * CDAUDIO_mciSeek [internal]
612 static DWORD CDAUDIO_mciSeek(UINT16 wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
614 DWORD at;
615 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
617 TRACE("(%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("Seeking to start\n");
626 at = 0;
627 break;
628 case MCI_SEEK_TO_END:
629 TRACE("Seeking to end\n");
630 at = wmcda->wcda.dwTotalLen;
631 break;
632 case MCI_TO:
633 TRACE("Seeking to %lu\n", lpParms->dwTo);
634 at = lpParms->dwTo;
635 break;
636 default:
637 TRACE("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("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
645 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
646 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
648 return 0;
651 /**************************************************************************
652 * CDAUDIO_mciSetDoor [internal]
654 static DWORD CDAUDIO_mciSetDoor(UINT16 wDevID, int open)
656 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
658 TRACE("(%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;
665 return 0;
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("(%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("MCI_FORMAT_MILLISECONDS !\n");
687 break;
688 case MCI_FORMAT_MSF:
689 TRACE("MCI_FORMAT_MSF !\n");
690 break;
691 case MCI_FORMAT_TMSF:
692 TRACE("MCI_FORMAT_TMSF !\n");
693 break;
694 default:
695 WARN("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("MCI_NOTIFY_SUCCESSFUL %08lX !\n",
711 lpParms->dwCallback);
712 mciDriverNotify16((HWND16)LOWORD(lpParms->dwCallback),
713 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
715 return 0;
718 /**************************************************************************
719 * MCICDAUDIO_DriverProc [sample driver]
721 LONG MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
722 DWORD dwParam1, DWORD dwParam2)
724 switch(wMsg) {
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);
750 case MCI_LOAD:
751 case MCI_SAVE:
752 case MCI_FREEZE:
753 case MCI_PUT:
754 case MCI_REALIZE:
755 case MCI_UNFREEZE:
756 case MCI_UPDATE:
757 case MCI_WHERE:
758 case MCI_WINDOW:
759 case MCI_STEP:
760 case MCI_SPIN:
761 case MCI_ESCAPE:
762 case MCI_COPY:
763 case MCI_CUT:
764 case MCI_DELETE:
765 case MCI_PASTE:
766 WARN("Unsupported command=%s\n", MCI_CommandToString(wMsg));
767 break;
768 case MCI_OPEN:
769 case MCI_CLOSE:
770 FIXME("Shouldn't receive a MCI_OPEN or CLOSE message\n");
771 break;
772 default:
773 TRACE("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 /*-----------------------------------------------------------------------*/