source: trunk/src/winmm/mcicda/mcicda.cpp@ 2473

Last change on this file since 2473 was 2473, checked in by sandervl, 26 years ago

JW: ported MCICDA.DLL from Wine 20000901 (Linux cdrom calls stubbed so it doesn't work)

File size: 27.3 KB
Line 
1/* -*- tab-width: 8; c-basic-offset: 4 -*- */
2/*
3 * Sample MCI CDAUDIO Wine Driver for Linux
4 *
5 * Copyright 1994 Martin Ayotte
6 * Copyright 1998-99 Eric Pouech
7 */
8
9#include <os2win.h>
10#include <string.h>
11#include "winuser.h"
12#include "driver.h"
13#include "mmddk.h"
14#include "cdrom.h"
15#include "debugtools.h"
16
17DEFAULT_DEBUG_CHANNEL(cdaudio)
18
19typedef struct {
20 UINT wDevID;
21 int nUseCount; /* Incremented for each shared open */
22 BOOL fShareable; /* TRUE if first open was shareable */
23 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
24 HANDLE hCallback; /* Callback handle for pending notification */
25 DWORD dwTimeFormat;
26 WINE_CDAUDIO wcda;
27 int mciMode;
28} WINE_MCICDAUDIO;
29
30/*-----------------------------------------------------------------------*/
31
32/**************************************************************************
33 * CDAUDIO_drvOpen [internal]
34 */
35static DWORD CDAUDIO_drvOpen(LPSTR str, LPMCI_OPEN_DRIVER_PARMSA modp)
36{
37 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINE_MCICDAUDIO));
38
39 if (!wmcda)
40 return 0;
41
42 wmcda->wDevID = modp->wDeviceID;
43 mciSetDriverData(wmcda->wDevID, (DWORD)wmcda);
44 modp->wCustomCommandTable = MCI_NO_COMMAND_TABLE;
45 modp->wType = MCI_DEVTYPE_CD_AUDIO;
46 return modp->wDeviceID;
47}
48
49/**************************************************************************
50 * CDAUDIO_drvClose [internal]
51 */
52static DWORD CDAUDIO_drvClose(DWORD dwDevID)
53{
54 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(dwDevID);
55
56 if (wmcda) {
57 HeapFree(GetProcessHeap(), 0, wmcda);
58 mciSetDriverData(dwDevID, 0);
59 }
60 return 0;
61}
62
63/**************************************************************************
64 * CDAUDIO_mciGetOpenDrv [internal]
65 */
66static WINE_MCICDAUDIO* CDAUDIO_mciGetOpenDrv(UINT wDevID)
67{
68 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
69
70 if (wmcda == NULL || wmcda->nUseCount == 0 || wmcda->wcda.unixdev <= 0) {
71 WARN("Invalid wDevID=%u\n", wDevID);
72 return 0;
73 }
74 return wmcda;
75}
76
77/**************************************************************************
78 * CDAUDIO_mciMode [internal]
79 */
80static int CDAUDIO_mciMode(int wcdaMode)
81{
82 switch (wcdaMode) {
83 case WINE_CDA_DONTKNOW: return MCI_MODE_STOP;
84 case WINE_CDA_NOTREADY: return MCI_MODE_STOP;
85 case WINE_CDA_OPEN: return MCI_MODE_OPEN;
86 case WINE_CDA_PLAY: return MCI_MODE_PLAY;
87 case WINE_CDA_STOP: return MCI_MODE_STOP;
88 case WINE_CDA_PAUSE: return MCI_MODE_PAUSE;
89 default:
90 FIXME("Unknown mode %04x\n", wcdaMode);
91 }
92 return MCI_MODE_STOP;
93}
94
95/**************************************************************************
96 * CDAUDIO_mciGetError [internal]
97 */
98static int CDAUDIO_mciGetError(WINE_MCICDAUDIO* wmcda)
99{
100 switch (wmcda->wcda.cdaMode) {
101 case WINE_CDA_DONTKNOW:
102 case WINE_CDA_NOTREADY: return MCIERR_DEVICE_NOT_READY;
103 case WINE_CDA_OPEN: return MCIERR_DEVICE_OPEN;
104 case WINE_CDA_PLAY:
105 case WINE_CDA_STOP:
106 case WINE_CDA_PAUSE: break;
107 default:
108 FIXME("Unknown mode %04x\n", wmcda->wcda.cdaMode);
109 }
110 return MCIERR_DRIVER_INTERNAL;
111}
112
113/**************************************************************************
114 * CDAUDIO_CalcFrame [internal]
115 */
116static DWORD CDAUDIO_CalcFrame(WINE_MCICDAUDIO* wmcda, DWORD dwTime)
117{
118 DWORD dwFrame = 0;
119 UINT wTrack;
120
121 TRACE("(%p, %08lX, %lu);\n", wmcda, wmcda->dwTimeFormat, dwTime);
122
123 switch (wmcda->dwTimeFormat) {
124 case MCI_FORMAT_MILLISECONDS:
125 dwFrame = ((dwTime - 1) * CDFRAMES_PERSEC + 500) / 1000;
126 TRACE("MILLISECONDS %lu\n", dwFrame);
127 break;
128 case MCI_FORMAT_MSF:
129 TRACE("MSF %02u:%02u:%02u\n",
130 MCI_MSF_MINUTE(dwTime), MCI_MSF_SECOND(dwTime), MCI_MSF_FRAME(dwTime));
131 dwFrame += CDFRAMES_PERMIN * MCI_MSF_MINUTE(dwTime);
132 dwFrame += CDFRAMES_PERSEC * MCI_MSF_SECOND(dwTime);
133 dwFrame += MCI_MSF_FRAME(dwTime);
134 break;
135 case MCI_FORMAT_TMSF:
136 default: /* unknown format ! force TMSF ! ... */
137 wTrack = MCI_TMSF_TRACK(dwTime);
138 TRACE("MSF %02u-%02u:%02u:%02u\n",
139 MCI_TMSF_TRACK(dwTime), MCI_TMSF_MINUTE(dwTime),
140 MCI_TMSF_SECOND(dwTime), MCI_TMSF_FRAME(dwTime));
141 TRACE("TMSF trackpos[%u]=%lu\n",
142 wTrack, wmcda->wcda.lpdwTrackPos[wTrack - 1]);
143 dwFrame = wmcda->wcda.lpdwTrackPos[wTrack - 1];
144 dwFrame += CDFRAMES_PERMIN * MCI_TMSF_MINUTE(dwTime);
145 dwFrame += CDFRAMES_PERSEC * MCI_TMSF_SECOND(dwTime);
146 dwFrame += MCI_TMSF_FRAME(dwTime);
147 break;
148 }
149 return dwFrame;
150}
151
152/**************************************************************************
153 * CDAUDIO_CalcTime [internal]
154 */
155static DWORD CDAUDIO_CalcTime(WINE_MCICDAUDIO* wmcda, DWORD tf, DWORD dwFrame,
156 LPDWORD lpRet)
157{
158 DWORD dwTime = 0;
159 UINT wTrack;
160 UINT wMinutes;
161 UINT wSeconds;
162 UINT wFrames;
163
164 TRACE("(%p, %08lX, %lu);\n", wmcda, tf, dwFrame);
165
166 switch (tf) {
167 case MCI_FORMAT_MILLISECONDS:
168 dwTime = (dwFrame * 1000) / CDFRAMES_PERSEC + 1;
169 TRACE("MILLISECONDS %lu\n", dwTime);
170 *lpRet = 0;
171 break;
172 case MCI_FORMAT_MSF:
173 wMinutes = dwFrame / CDFRAMES_PERMIN;
174 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
175 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
176 dwTime = MCI_MAKE_MSF(wMinutes, wSeconds, wFrames);
177 TRACE("MSF %02u:%02u:%02u -> dwTime=%lu\n",
178 wMinutes, wSeconds, wFrames, dwTime);
179 *lpRet = MCI_COLONIZED3_RETURN;
180 break;
181 case MCI_FORMAT_TMSF:
182 default: /* unknown format ! force TMSF ! ... */
183 if (dwFrame < wmcda->wcda.dwFirstFrame || dwFrame > wmcda->wcda.dwLastFrame) {
184 ERR("Out of range value %lu [%lu,%lu]\n",
185 dwFrame, wmcda->wcda.dwFirstFrame, wmcda->wcda.dwLastFrame);
186 *lpRet = 0;
187 return 0;
188 }
189 for (wTrack = 1; wTrack < wmcda->wcda.nTracks; wTrack++) {
190 if (wmcda->wcda.lpdwTrackPos[wTrack] > dwFrame)
191 break;
192 }
193 dwFrame -= wmcda->wcda.lpdwTrackPos[wTrack - 1];
194 wMinutes = dwFrame / CDFRAMES_PERMIN;
195 wSeconds = (dwFrame - CDFRAMES_PERMIN * wMinutes) / CDFRAMES_PERSEC;
196 wFrames = dwFrame - CDFRAMES_PERMIN * wMinutes - CDFRAMES_PERSEC * wSeconds;
197 dwTime = MCI_MAKE_TMSF(wTrack, wMinutes, wSeconds, wFrames);
198 TRACE("%02u-%02u:%02u:%02u\n", wTrack, wMinutes, wSeconds, wFrames);
199 *lpRet = MCI_COLONIZED4_RETURN;
200 break;
201 }
202 return dwTime;
203}
204
205static DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms);
206static DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
207
208/**************************************************************************
209 * CDAUDIO_mciOpen [internal]
210 */
211static DWORD CDAUDIO_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMSA lpOpenParms)
212{
213 DWORD dwDeviceID;
214 WINE_MCICDAUDIO* wmcda = (WINE_MCICDAUDIO*)mciGetDriverData(wDevID);
215 MCI_SEEK_PARMS seekParms;
216
217 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpOpenParms);
218
219 if (lpOpenParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
220 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
221
222 dwDeviceID = lpOpenParms->wDeviceID;
223
224 if (wmcda->nUseCount > 0) {
225 /* The driver is already open on this channel */
226 /* If the driver was opened shareable before and this open specifies */
227 /* shareable then increment the use count */
228 if (wmcda->fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
229 ++wmcda->nUseCount;
230 else
231 return MCIERR_MUST_USE_SHAREABLE;
232 } else {
233 wmcda->nUseCount = 1;
234 wmcda->fShareable = dwFlags & MCI_OPEN_SHAREABLE;
235 }
236 if (dwFlags & MCI_OPEN_ELEMENT) {
237 if (dwFlags & MCI_OPEN_ELEMENT_ID) {
238 WARN("MCI_OPEN_ELEMENT_ID %8lx ! Abort", (DWORD)lpOpenParms->lpstrElementName);
239 return MCIERR_NO_ELEMENT_ALLOWED;
240 }
241 WARN("MCI_OPEN_ELEMENT %s ignored\n",lpOpenParms->lpstrElementName);
242 /*return MCIERR_NO_ELEMENT_ALLOWED;
243 bon 19991106 allows cdplayer.exe to run*/
244 }
245
246 wmcda->wNotifyDeviceID = dwDeviceID;
247 if (CDAUDIO_Open(&wmcda->wcda) == -1) {
248 --wmcda->nUseCount;
249 return MCIERR_HARDWARE;
250 }
251 wmcda->mciMode = MCI_MODE_STOP;
252 wmcda->dwTimeFormat = MCI_FORMAT_MSF;
253 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
254 WARN("error reading TracksInfo !\n");
255 return MCIERR_INTERNAL;
256 }
257
258 CDAUDIO_mciSeek(wDevID, MCI_SEEK_TO_START, &seekParms);
259
260 return 0;
261}
262
263/**************************************************************************
264 * CDAUDIO_mciClose [internal]
265 */
266static DWORD CDAUDIO_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
267{
268 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
269
270 TRACE("(%04X, %08lX, %p);\n", wDevID, dwParam, lpParms);
271
272 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
273
274 if (wmcda->nUseCount == 1) {
275 CDAUDIO_Close(&wmcda->wcda);
276 }
277 wmcda->nUseCount--;
278 return 0;
279}
280
281/**************************************************************************
282 * CDAUDIO_mciGetDevCaps [internal]
283 */
284static DWORD CDAUDIO_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
285 LPMCI_GETDEVCAPS_PARMS lpParms)
286{
287 DWORD ret = 0;
288
289 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
290
291 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
292
293 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
294 TRACE("MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms->dwItem);
295
296 switch (lpParms->dwItem) {
297 case MCI_GETDEVCAPS_CAN_RECORD:
298 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
299 ret = MCI_RESOURCE_RETURNED;
300 break;
301 case MCI_GETDEVCAPS_HAS_AUDIO:
302 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
303 ret = MCI_RESOURCE_RETURNED;
304 break;
305 case MCI_GETDEVCAPS_HAS_VIDEO:
306 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
307 ret = MCI_RESOURCE_RETURNED;
308 break;
309 case MCI_GETDEVCAPS_DEVICE_TYPE:
310 lpParms->dwReturn = MAKEMCIRESOURCE(MCI_DEVTYPE_CD_AUDIO, MCI_DEVTYPE_CD_AUDIO);
311 ret = MCI_RESOURCE_RETURNED;
312 break;
313 case MCI_GETDEVCAPS_USES_FILES:
314 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
315 ret = MCI_RESOURCE_RETURNED;
316 break;
317 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
318 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
319 ret = MCI_RESOURCE_RETURNED;
320 break;
321 case MCI_GETDEVCAPS_CAN_EJECT:
322 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
323 ret = MCI_RESOURCE_RETURNED;
324 break;
325 case MCI_GETDEVCAPS_CAN_PLAY:
326 lpParms->dwReturn = MAKEMCIRESOURCE(TRUE, MCI_TRUE);
327 ret = MCI_RESOURCE_RETURNED;
328 break;
329 case MCI_GETDEVCAPS_CAN_SAVE:
330 lpParms->dwReturn = MAKEMCIRESOURCE(FALSE, MCI_FALSE);
331 ret = MCI_RESOURCE_RETURNED;
332 break;
333 default:
334 ERR("Unsupported %lx devCaps item\n", lpParms->dwItem);
335 return MCIERR_UNRECOGNIZED_COMMAND;
336 }
337 } else {
338 TRACE("No GetDevCaps-Item !\n");
339 return MCIERR_UNRECOGNIZED_COMMAND;
340 }
341 TRACE("lpParms->dwReturn=%08lX;\n", lpParms->dwReturn);
342 return ret;
343}
344
345/**************************************************************************
346 * CDAUDIO_mciInfo [internal]
347 */
348static DWORD CDAUDIO_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMSA lpParms)
349{
350 LPSTR str = NULL;
351 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
352 DWORD ret = 0;
353 char buffer[16];
354
355 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
356
357 if (lpParms == NULL || lpParms->lpstrReturn == NULL)
358 return MCIERR_NULL_PARAMETER_BLOCK;
359 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
360
361 TRACE("buf=%p, len=%lu\n", lpParms->lpstrReturn, lpParms->dwRetSize);
362
363 if (dwFlags & MCI_INFO_PRODUCT) {
364 str = "Wine's audio CD";
365 } else if (dwFlags & MCI_INFO_MEDIA_UPC) {
366// ret = MCIERR_NO_IDENTITY;
367 ret = 0; // No Info about MCIERR_NO_IDENTITY
368 } else if (dwFlags & MCI_INFO_MEDIA_IDENTITY) {
369 DWORD msf, res = 0, dummy;
370 int i;
371
372 if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) {
373 return CDAUDIO_mciGetError(wmcda);
374 }
375
376 for (i = 0; i < wmcda->wcda.nTracks; i++) {
377 msf = CDAUDIO_CalcTime(wmcda, MCI_FORMAT_MSF, wmcda->wcda.lpdwTrackPos[i], &dummy);
378 res += (MCI_MSF_MINUTE(msf) << 16) +
379 (MCI_MSF_SECOND(msf) << 8) +
380 (MCI_MSF_FRAME(msf));
381 }
382 if (wmcda->wcda.nTracks <= 2) {
383 /* there are some other values added when # of tracks < 3
384 * for most Audio CD it will do without
385 */
386 FIXME("Value is not correct !! "
387 "Please report will full audio CD information (-debugmsg +cdaudio)\n");
388 }
389 sprintf(buffer, "%lu", res);
390 str = buffer;
391 } else {
392 WARN("Don't know this info command (%lu)\n", dwFlags);
393 ret = MCIERR_UNRECOGNIZED_COMMAND;
394 }
395 if (str) {
396 if (lpParms->dwRetSize <= strlen(str)) {
397 lstrcpynA(lpParms->lpstrReturn, str, lpParms->dwRetSize - 1);
398 ret = MCIERR_PARAM_OVERFLOW;
399 } else {
400 strcpy(lpParms->lpstrReturn, str);
401 }
402 } else {
403 *lpParms->lpstrReturn = 0;
404 }
405 TRACE("=> %s (%ld)\n", lpParms->lpstrReturn, ret);
406 return ret;
407}
408
409/**************************************************************************
410 * CDAUDIO_mciStatus [internal]
411 */
412static DWORD CDAUDIO_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
413{
414 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
415 DWORD ret = 0;
416
417 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
418
419 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
420 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
421
422 if (dwFlags & MCI_NOTIFY) {
423 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
424 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
425 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
426 }
427 if (dwFlags & MCI_STATUS_ITEM) {
428 switch (lpParms->dwItem) {
429 case MCI_STATUS_CURRENT_TRACK:
430 if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) {
431 return CDAUDIO_mciGetError(wmcda);
432 }
433 lpParms->dwReturn = wmcda->wcda.nCurTrack;
434 TRACE("CURRENT_TRACK=%lu!\n", lpParms->dwReturn);
435 break;
436 case MCI_STATUS_LENGTH:
437 if (wmcda->wcda.nTracks == 0) {
438 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
439 WARN("error reading TracksInfo !\n");
440 return CDAUDIO_mciGetError(wmcda);
441 }
442 }
443 if (dwFlags & MCI_TRACK) {
444 TRACE("MCI_TRACK #%lu LENGTH=??? !\n", lpParms->dwTrack);
445 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
446 return MCIERR_OUTOFRANGE;
447 lpParms->dwReturn = wmcda->wcda.lpdwTrackLen[lpParms->dwTrack - 1];
448 } else {
449 lpParms->dwReturn = wmcda->wcda.dwLastFrame;
450 }
451 lpParms->dwReturn = CDAUDIO_CalcTime(wmcda,
452 (wmcda->dwTimeFormat == MCI_FORMAT_TMSF)
453 ? MCI_FORMAT_MSF : wmcda->dwTimeFormat,
454 lpParms->dwReturn,
455 &ret);
456 TRACE("LENGTH=%lu !\n", lpParms->dwReturn);
457 break;
458 case MCI_STATUS_MODE:
459 if (!CDAUDIO_GetCDStatus(&wmcda->wcda))
460 return CDAUDIO_mciGetError(wmcda);
461 lpParms->dwReturn = CDAUDIO_mciMode(wmcda->wcda.cdaMode);
462 if (!lpParms->dwReturn) lpParms->dwReturn = wmcda->mciMode;
463 TRACE("MCI_STATUS_MODE=%08lX !\n", lpParms->dwReturn);
464 lpParms->dwReturn = MAKEMCIRESOURCE(lpParms->dwReturn, lpParms->dwReturn);
465 ret = MCI_RESOURCE_RETURNED;
466 break;
467 case MCI_STATUS_MEDIA_PRESENT:
468 if (!CDAUDIO_GetCDStatus(&wmcda->wcda))
469 return CDAUDIO_mciGetError(wmcda);
470 lpParms->dwReturn = (wmcda->wcda.nTracks == 0) ?
471 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
472 TRACE("MCI_STATUS_MEDIA_PRESENT =%c!\n", LOWORD(lpParms->dwReturn) ? 'Y' : 'N');
473 ret = MCI_RESOURCE_RETURNED;
474 break;
475 case MCI_STATUS_NUMBER_OF_TRACKS:
476 lpParms->dwReturn = CDAUDIO_GetNumberOfTracks(&wmcda->wcda);
477 TRACE("MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms->dwReturn);
478 if (lpParms->dwReturn == (WORD)-1)
479 return CDAUDIO_mciGetError(wmcda);
480 break;
481 case MCI_STATUS_POSITION:
482 if (!CDAUDIO_GetCDStatus(&wmcda->wcda))
483 return CDAUDIO_mciGetError(wmcda);
484 lpParms->dwReturn = wmcda->wcda.dwCurFrame;
485 if (dwFlags & MCI_STATUS_START) {
486 lpParms->dwReturn = wmcda->wcda.dwFirstFrame;
487 TRACE("get MCI_STATUS_START !\n");
488 }
489 if (dwFlags & MCI_TRACK) {
490 if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
491 return MCIERR_OUTOFRANGE;
492 lpParms->dwReturn = wmcda->wcda.lpdwTrackPos[lpParms->dwTrack - 1];
493 TRACE("get MCI_TRACK #%lu !\n", lpParms->dwTrack);
494 }
495 lpParms->dwReturn = CDAUDIO_CalcTime(wmcda, wmcda->dwTimeFormat, lpParms->dwReturn, &ret);
496 TRACE("MCI_STATUS_POSITION=%08lX !\n", lpParms->dwReturn);
497 break;
498 case MCI_STATUS_READY:
499 TRACE("MCI_STATUS_READY !\n");
500 lpParms->dwReturn = (wmcda->wcda.cdaMode == WINE_CDA_DONTKNOW ||
501 wmcda->wcda.cdaMode == WINE_CDA_NOTREADY) ?
502 MAKEMCIRESOURCE(FALSE, MCI_FALSE) : MAKEMCIRESOURCE(TRUE, MCI_TRUE);
503 TRACE("MCI_STATUS_READY=%u!\n", LOWORD(lpParms->dwReturn));
504 ret = MCI_RESOURCE_RETURNED;
505 break;
506 case MCI_STATUS_TIME_FORMAT:
507 lpParms->dwReturn = MAKEMCIRESOURCE(wmcda->dwTimeFormat, wmcda->dwTimeFormat);
508 TRACE("MCI_STATUS_TIME_FORMAT=%08x!\n", LOWORD(lpParms->dwReturn));
509 ret = MCI_RESOURCE_RETURNED;
510 break;
511 case 4001: /* FIXME: for boggus FullCD */
512 case MCI_CDA_STATUS_TYPE_TRACK:
513 if (!(dwFlags & MCI_TRACK))
514 ret = MCIERR_MISSING_PARAMETER;
515 else if (lpParms->dwTrack > wmcda->wcda.nTracks || lpParms->dwTrack == 0)
516 ret = MCIERR_OUTOFRANGE;
517 else
518 lpParms->dwReturn = (wmcda->wcda.lpbTrackFlags[lpParms->dwTrack - 1] &
519 CDROM_DATA_TRACK) ? MCI_CDA_TRACK_OTHER : MCI_CDA_TRACK_AUDIO;
520 TRACE("MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms->dwTrack, lpParms->dwReturn);
521 break;
522 default:
523 FIXME("unknown command %08lX !\n", lpParms->dwItem);
524 return MCIERR_UNRECOGNIZED_COMMAND;
525 }
526 } else {
527 WARN("not MCI_STATUS_ITEM !\n");
528 }
529 return ret;
530}
531
532/**************************************************************************
533 * CDAUDIO_mciPlay [internal]
534 */
535static DWORD CDAUDIO_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
536{
537 int start, end;
538 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
539 DWORD ret = 0;
540
541 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
542
543 if (lpParms == NULL) {
544 ret = MCIERR_NULL_PARAMETER_BLOCK;
545 } else if (wmcda == NULL) {
546 ret = MCIERR_INVALID_DEVICE_ID;
547 } else {
548 if (wmcda->wcda.nTracks == 0) {
549 if (!CDAUDIO_GetTracksInfo(&wmcda->wcda)) {
550 WARN("error reading TracksInfo !\n");
551 return MCIERR_DRIVER_INTERNAL;
552 }
553 }
554 wmcda->wcda.nCurTrack = 1;
555 if (dwFlags & MCI_FROM) {
556 start = CDAUDIO_CalcFrame(wmcda, lpParms->dwFrom);
557 TRACE("MCI_FROM=%08lX -> %u \n", lpParms->dwFrom, start);
558 } else {
559 if (!CDAUDIO_GetCDStatus(&wmcda->wcda)) return MCIERR_DRIVER_INTERNAL;
560 start = wmcda->wcda.dwCurFrame;
561 }
562 if (dwFlags & MCI_TO) {
563 end = CDAUDIO_CalcFrame(wmcda, lpParms->dwTo);
564 TRACE("MCI_TO=%08lX -> %u \n", lpParms->dwTo, end);
565 } else {
566 end = wmcda->wcda.dwLastFrame;
567 }
568
569 if (CDAUDIO_Play(&wmcda->wcda, start, end) == -1)
570 return MCIERR_HARDWARE;
571 wmcda->mciMode = MCI_MODE_PLAY;
572 if (dwFlags & MCI_NOTIFY) {
573 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
574 /*
575 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
576 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
577 */
578 }
579 }
580 return ret;
581}
582
583/**************************************************************************
584 * CDAUDIO_mciStop [internal]
585 */
586static DWORD CDAUDIO_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
587{
588 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
589
590 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
591
592 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
593
594 if (CDAUDIO_Stop(&wmcda->wcda) == -1)
595 return MCIERR_HARDWARE;
596
597 wmcda->mciMode = MCI_MODE_STOP;
598 if (lpParms && (dwFlags & MCI_NOTIFY)) {
599 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
600 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
601 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
602 }
603 return 0;
604}
605
606/**************************************************************************
607 * CDAUDIO_mciPause [internal]
608 */
609static DWORD CDAUDIO_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
610{
611 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
612
613 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
614
615 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
616
617 if (CDAUDIO_Pause(&wmcda->wcda, 1) == -1)
618 return MCIERR_HARDWARE;
619 wmcda->mciMode = MCI_MODE_PAUSE;
620 if (lpParms && (dwFlags & MCI_NOTIFY)) {
621 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
622 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
623 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
624 }
625 return 0;
626}
627
628/**************************************************************************
629 * CDAUDIO_mciResume [internal]
630 */
631static DWORD CDAUDIO_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
632{
633 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
634
635 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
636
637 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
638
639 if (CDAUDIO_Pause(&wmcda->wcda, 0) == -1)
640 return MCIERR_HARDWARE;
641 wmcda->mciMode = MCI_MODE_STOP;
642 if (lpParms && (dwFlags & MCI_NOTIFY)) {
643 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
644 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
645 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
646 }
647 return 0;
648}
649
650/**************************************************************************
651 * CDAUDIO_mciSeek [internal]
652 */
653static DWORD CDAUDIO_mciSeek(UINT wDevID, DWORD dwFlags, LPMCI_SEEK_PARMS lpParms)
654{
655 DWORD at;
656 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
657
658 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
659
660 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
661 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;
662
663 wmcda->mciMode = MCI_MODE_SEEK;
664 switch (dwFlags & ~(MCI_NOTIFY|MCI_WAIT)) {
665 case MCI_SEEK_TO_START:
666 TRACE("Seeking to start\n");
667 at = wmcda->wcda.dwFirstFrame;
668 break;
669 case MCI_SEEK_TO_END:
670 TRACE("Seeking to end\n");
671 at = wmcda->wcda.dwLastFrame;
672 break;
673 case MCI_TO:
674 TRACE("Seeking to %lu\n", lpParms->dwTo);
675 at = lpParms->dwTo;
676 break;
677 default:
678 TRACE("Seeking to ??=%lu\n", dwFlags);
679 return MCIERR_UNSUPPORTED_FUNCTION;
680 }
681 if (CDAUDIO_Seek(&wmcda->wcda, at) == -1) {
682 return MCIERR_HARDWARE;
683 }
684 if (dwFlags & MCI_NOTIFY) {
685 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
686 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
687 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
688 }
689 return 0;
690}
691
692/**************************************************************************
693 * CDAUDIO_mciSetDoor [internal]
694 */
695static DWORD CDAUDIO_mciSetDoor(UINT wDevID, int open)
696{
697 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
698
699 TRACE("(%04x, %s) !\n", wDevID, (open) ? "OPEN" : "CLOSE");
700
701 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
702
703 if (CDAUDIO_SetDoor(&wmcda->wcda, open) == -1)
704 return MCIERR_HARDWARE;
705 wmcda->mciMode = (open) ? MCI_MODE_OPEN : MCI_MODE_STOP;
706 return 0;
707}
708
709/**************************************************************************
710 * CDAUDIO_mciSet [internal]
711 */
712static DWORD CDAUDIO_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
713{
714 WINE_MCICDAUDIO* wmcda = CDAUDIO_mciGetOpenDrv(wDevID);
715
716 TRACE("(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
717
718 if (wmcda == NULL) return MCIERR_INVALID_DEVICE_ID;
719 if (lpParms == NULL) return MCIERR_NULL_PARAMETER_BLOCK;;
720 /*
721 TRACE("dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
722 TRACE("dwAudio=%08lX\n", lpParms->dwAudio);
723 */
724 if (dwFlags & MCI_SET_TIME_FORMAT) {
725 switch (lpParms->dwTimeFormat) {
726 case MCI_FORMAT_MILLISECONDS:
727 TRACE("MCI_FORMAT_MILLISECONDS !\n");
728 break;
729 case MCI_FORMAT_MSF:
730 TRACE("MCI_FORMAT_MSF !\n");
731 break;
732 case MCI_FORMAT_TMSF:
733 TRACE("MCI_FORMAT_TMSF !\n");
734 break;
735 default:
736 WARN("bad time format !\n");
737 return MCIERR_BAD_TIME_FORMAT;
738 }
739 wmcda->dwTimeFormat = lpParms->dwTimeFormat;
740 }
741 if (dwFlags & MCI_SET_DOOR_OPEN) {
742 CDAUDIO_mciSetDoor(wDevID, TRUE);
743 }
744 if (dwFlags & MCI_SET_DOOR_CLOSED) {
745 CDAUDIO_mciSetDoor(wDevID, FALSE);
746 }
747 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
748 if (dwFlags & MCI_SET_ON) return MCIERR_UNSUPPORTED_FUNCTION;
749 if (dwFlags & MCI_SET_OFF) return MCIERR_UNSUPPORTED_FUNCTION;
750 if (dwFlags & MCI_NOTIFY) {
751 TRACE("MCI_NOTIFY_SUCCESSFUL %08lX !\n",
752 lpParms->dwCallback);
753 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
754 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
755 }
756 return 0;
757}
758
759/**************************************************************************
760 * MCICDAUDIO_DriverProc [sample driver]
761 */
762LONG CALLBACK MCICDAUDIO_DriverProc(DWORD dwDevID, HDRVR hDriv, DWORD wMsg,
763 DWORD dwParam1, DWORD dwParam2)
764{
765 switch(wMsg) {
766 case DRV_LOAD: return 1;
767 case DRV_FREE: return 1;
768 case DRV_OPEN: return CDAUDIO_drvOpen((LPSTR)dwParam1, (LPMCI_OPEN_DRIVER_PARMSA)dwParam2);
769 case DRV_CLOSE: return CDAUDIO_drvClose(dwDevID);
770 case DRV_ENABLE: return 1;
771 case DRV_DISABLE: return 1;
772 case DRV_QUERYCONFIGURE: return 1;
773 case DRV_CONFIGURE: MessageBoxA(0, "Sample Multimedia Driver !", "Wine Driver", MB_OK); return 1;
774 case DRV_INSTALL: return DRVCNF_RESTART;
775 case DRV_REMOVE: return DRVCNF_RESTART;
776
777 case MCI_OPEN_DRIVER: return CDAUDIO_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMSA)dwParam2);
778 case MCI_CLOSE_DRIVER: return CDAUDIO_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
779 case MCI_GETDEVCAPS: return CDAUDIO_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
780 case MCI_INFO: return CDAUDIO_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMSA)dwParam2);
781 case MCI_STATUS: return CDAUDIO_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
782 case MCI_SET: return CDAUDIO_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
783 case MCI_PLAY: return CDAUDIO_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
784 case MCI_STOP: return CDAUDIO_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
785 case MCI_PAUSE: return CDAUDIO_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
786 case MCI_RESUME: return CDAUDIO_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
787 case MCI_SEEK: return CDAUDIO_mciSeek(dwDevID, dwParam1, (LPMCI_SEEK_PARMS)dwParam2);
788 /* FIXME: I wonder if those two next items are really called ? */
789 case MCI_SET_DOOR_OPEN: return CDAUDIO_mciSetDoor(dwDevID, TRUE);
790 case MCI_SET_DOOR_CLOSED: return CDAUDIO_mciSetDoor(dwDevID, FALSE);
791 /* commands that should be supported */
792 case MCI_LOAD:
793 case MCI_SAVE:
794 case MCI_FREEZE:
795 case MCI_PUT:
796 case MCI_REALIZE:
797 case MCI_UNFREEZE:
798 case MCI_UPDATE:
799 case MCI_WHERE:
800 case MCI_STEP:
801 case MCI_SPIN:
802 case MCI_ESCAPE:
803 case MCI_COPY:
804 case MCI_CUT:
805 case MCI_DELETE:
806 case MCI_PASTE:
807 FIXME("Unsupported yet command [%lu]\n", wMsg);
808 break;
809 /* commands that should report an error */
810 case MCI_WINDOW:
811 TRACE("Unsupported command [%lu]\n", wMsg);
812 break;
813 case MCI_OPEN:
814 case MCI_CLOSE:
815 ERR("Shouldn't receive a MCI_OPEN or CLOSE message\n");
816 break;
817 default:
818 TRACE("Sending msg [%lu] to default driver proc\n", wMsg);
819 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
820 }
821 return MCIERR_UNRECOGNIZED_COMMAND;
822}
823
824/*-----------------------------------------------------------------------*/
Note: See TracBrowser for help on using the repository browser.