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
11 #include "multimedia.h"
16 int nUseCount
; /* Incremented for each shared open */
17 BOOL16 fShareable
; /* TRUE if first open was shareable */
18 WORD wNotifyDeviceID
; /* MCI device ID with a pending notification */
19 HANDLE16 hCallback
; /* Callback handle for pending notification */
20 MCI_OPEN_PARMS16 openParms
;
26 #define MAX_CDAUDIODRV (1)
27 static WINE_MCICDAUDIO CDADev
[MAX_CDAUDIODRV
];
29 /*-----------------------------------------------------------------------*/
31 /**************************************************************************
32 * CDAUDIO_mciGetOpenDrv [internal]
34 static WINE_MCICDAUDIO
* CDAUDIO_mciGetOpenDrv(UINT16 wDevID
)
36 if (wDevID
>= MAX_CDAUDIODRV
|| CDADev
[wDevID
].nUseCount
== 0 ||
37 CDADev
[wDevID
].wcda
.unixdev
<= 0) {
38 WARN(cdaudio
, "Invalid wDevID=%u\n", wDevID
);
41 return &CDADev
[wDevID
];
44 /**************************************************************************
45 * CDAUDIO_mciMode [internal]
47 static int CDAUDIO_mciMode(int wcdaMode
)
50 case WINE_CDA_DONTKNOW
: return MCI_MODE_STOP
;
51 case WINE_CDA_NOTREADY
: return MCI_MODE_STOP
;
52 case WINE_CDA_OPEN
: return MCI_MODE_OPEN
;
53 case WINE_CDA_PLAY
: return MCI_MODE_PLAY
;
54 case WINE_CDA_STOP
: return MCI_MODE_STOP
;
55 case WINE_CDA_PAUSE
: return MCI_MODE_PAUSE
;
57 FIXME(cdaudio
, "Unknown mode %04x\n", wcdaMode
);
62 /**************************************************************************
63 * CDAUDIO_mciGetError [internal]
65 static int CDAUDIO_mciGetError(WINE_MCICDAUDIO
* wmcda
)
67 switch (wmcda
->wcda
.cdaMode
) {
68 case WINE_CDA_DONTKNOW
:
69 case WINE_CDA_NOTREADY
: return MCIERR_DEVICE_NOT_READY
;
70 case WINE_CDA_OPEN
: return MCIERR_DEVICE_OPEN
;
73 case WINE_CDA_PAUSE
: break;
75 FIXME(cdaudio
, "Unknown mode %04x\n", wmcda
->wcda
.cdaMode
);
77 return MCIERR_DRIVER_INTERNAL
;
80 /**************************************************************************
81 * CDAUDIO_CalcFrame [internal]
83 static DWORD
CDAUDIO_CalcFrame(WINE_MCICDAUDIO
* wmcda
, DWORD dwTime
)
88 TRACE(cdaudio
,"(%p, %08lX, %lu);\n", wmcda
, wmcda
->dwTimeFormat
, dwTime
);
90 switch (wmcda
->dwTimeFormat
) {
91 case MCI_FORMAT_MILLISECONDS
:
92 dwFrame
= (dwTime
* CDFRAMES_PERSEC
) / 1000;
93 TRACE(cdaudio
, "MILLISECONDS %lu\n", dwFrame
);
96 TRACE(cdaudio
, "MSF %02u:%02u:%02u\n",
97 MCI_MSF_MINUTE(dwTime
), MCI_MSF_SECOND(dwTime
), MCI_MSF_FRAME(dwTime
));
98 dwFrame
+= CDFRAMES_PERMIN
* MCI_MSF_MINUTE(dwTime
);
99 dwFrame
+= CDFRAMES_PERSEC
* MCI_MSF_SECOND(dwTime
);
100 dwFrame
+= MCI_MSF_FRAME(dwTime
);
102 case MCI_FORMAT_TMSF
:
104 /* unknown format ! force TMSF ! ... */
105 wTrack
= MCI_TMSF_TRACK(dwTime
);
106 TRACE(cdaudio
, "MSF %02u-%02u:%02u:%02u\n",
107 MCI_TMSF_TRACK(dwTime
), MCI_TMSF_MINUTE(dwTime
),
108 MCI_TMSF_SECOND(dwTime
), MCI_TMSF_FRAME(dwTime
));
109 TRACE(cdaudio
, "TMSF trackpos[%u]=%lu\n",
110 wTrack
, wmcda
->wcda
.lpdwTrackPos
[wTrack
- 1]);
111 dwFrame
= wmcda
->wcda
.lpdwTrackPos
[wTrack
- 1];
112 dwFrame
+= CDFRAMES_PERMIN
* MCI_TMSF_MINUTE(dwTime
);
113 dwFrame
+= CDFRAMES_PERSEC
* MCI_TMSF_SECOND(dwTime
);
114 dwFrame
+= MCI_TMSF_FRAME(dwTime
);
120 /**************************************************************************
121 * CDAUDIO_CalcTime [internal]
123 static DWORD
CDAUDIO_CalcTime(WINE_MCICDAUDIO
* wmcda
, DWORD dwFrame
)
131 TRACE(cdaudio
,"(%p, %08lX, %lu);\n", wmcda
, wmcda
->dwTimeFormat
, dwFrame
);
133 switch (wmcda
->dwTimeFormat
) {
134 case MCI_FORMAT_MILLISECONDS
:
135 dwTime
= (dwFrame
* 1000) / CDFRAMES_PERSEC
;
136 TRACE(cdaudio
, "MILLISECONDS %lu\n", dwTime
);
139 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
140 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
141 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
- CDFRAMES_PERSEC
* wSeconds
;
142 dwTime
= MCI_MAKE_MSF(wMinutes
, wSeconds
, wFrames
);
143 TRACE(cdaudio
,"MSF %02u:%02u:%02u -> dwTime=%lu\n",wMinutes
, wSeconds
, wFrames
, dwTime
);
145 case MCI_FORMAT_TMSF
:
147 /* unknown format ! force TMSF ! ... */
148 for (wTrack
= 0; wTrack
< wmcda
->wcda
.nTracks
; wTrack
++) {
149 /* dwTime += wmcda->lpdwTrackLen[wTrack - 1];
150 TRACE(cdaudio, "Adding trk#%u curpos=%u \n", dwTime);
151 if (dwTime >= dwFrame) break; */
152 if (wmcda
->wcda
.lpdwTrackPos
[wTrack
- 1] >= dwFrame
) break;
154 wMinutes
= dwFrame
/ CDFRAMES_PERMIN
;
155 wSeconds
= (dwFrame
- CDFRAMES_PERMIN
* wMinutes
) / CDFRAMES_PERSEC
;
156 wFrames
= dwFrame
- CDFRAMES_PERMIN
* wMinutes
- CDFRAMES_PERSEC
* wSeconds
;
157 dwTime
= MCI_MAKE_TMSF(wTrack
, wMinutes
, wSeconds
, wFrames
);
158 TRACE(cdaudio
, "%02u-%02u:%02u:%02u\n", wTrack
, wMinutes
, wSeconds
, wFrames
);
164 static DWORD
CDAUDIO_mciSeek(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
);
165 static DWORD
CDAUDIO_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
);
167 /**************************************************************************
168 * CDAUDIO_mciOpen [internal]
170 static DWORD
CDAUDIO_mciOpen(UINT16 wDevID
, DWORD dwFlags
, LPMCI_OPEN_PARMSA lpOpenParms
)
173 WINE_MCICDAUDIO
* wmcda
;
174 MCI_SEEK_PARMS seekParms
;
176 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpOpenParms
);
178 if (lpOpenParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
179 if (wDevID
> MAX_CDAUDIODRV
) return MCIERR_INVALID_DEVICE_ID
;
181 dwDeviceID
= lpOpenParms
->wDeviceID
;
183 wmcda
= &CDADev
[wDevID
];
185 if (wmcda
->nUseCount
> 0) {
186 /* The driver is already open on this channel */
187 /* If the driver was opened shareable before and this open specifies */
188 /* shareable then increment the use count */
189 if (wmcda
->fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
192 return MCIERR_MUST_USE_SHAREABLE
;
194 wmcda
->nUseCount
= 1;
195 wmcda
->fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
197 if (dwFlags
& MCI_OPEN_ELEMENT
) {
198 TRACE(cdaudio
,"MCI_OPEN_ELEMENT !\n");
199 /* return MCIERR_NO_ELEMENT_ALLOWED; */
202 wmcda
->openParms
.dwCallback
= lpOpenParms
->dwCallback
;
203 wmcda
->openParms
.wDeviceID
= (WORD
)lpOpenParms
->wDeviceID
;
204 wmcda
->openParms
.wReserved0
= 0; /*????*/
205 wmcda
->openParms
.lpstrDeviceType
= lpOpenParms
->lpstrDeviceType
;
206 wmcda
->openParms
.lpstrElementName
= lpOpenParms
->lpstrElementName
;
207 wmcda
->openParms
.lpstrAlias
= lpOpenParms
->lpstrAlias
;
209 wmcda
->wNotifyDeviceID
= dwDeviceID
;
210 if (CDAUDIO_Open(&wmcda
->wcda
) == -1) {
212 return MCIERR_HARDWARE
;
214 wmcda
->mciMode
= MCI_MODE_STOP
;
215 wmcda
->dwTimeFormat
= MCI_FORMAT_TMSF
;
216 if (!CDAUDIO_GetTracksInfo(&wmcda
->wcda
)) {
217 WARN(cdaudio
,"error reading TracksInfo !\n");
218 /* return MCIERR_INTERNAL; */
221 CDAUDIO_mciSeek(wDevID
, MCI_SEEK_TO_START
, &seekParms
);
226 /**************************************************************************
227 * CDAUDIO_mciClose [internal]
229 static DWORD
CDAUDIO_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
231 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
233 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
235 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
237 if (wmcda
->nUseCount
== 1) {
238 CDAUDIO_mciStop(wDevID
, 0, NULL
);
239 CDAUDIO_Close(&wmcda
->wcda
);
245 /**************************************************************************
246 * CDAUDIO_mciGetDevCaps [internal]
248 static DWORD
CDAUDIO_mciGetDevCaps(UINT16 wDevID
, DWORD dwFlags
,
249 LPMCI_GETDEVCAPS_PARMS lpParms
)
251 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
253 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
255 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
256 TRACE(cdaudio
, "MCI_GETDEVCAPS_ITEM dwItem=%08lX;\n", lpParms
->dwItem
);
258 switch(lpParms
->dwItem
) {
259 case MCI_GETDEVCAPS_CAN_RECORD
:
260 lpParms
->dwReturn
= FALSE
;
262 case MCI_GETDEVCAPS_HAS_AUDIO
:
263 lpParms
->dwReturn
= TRUE
;
265 case MCI_GETDEVCAPS_HAS_VIDEO
:
266 lpParms
->dwReturn
= FALSE
;
268 case MCI_GETDEVCAPS_DEVICE_TYPE
:
269 lpParms
->dwReturn
= MCI_DEVTYPE_CD_AUDIO
;
271 case MCI_GETDEVCAPS_USES_FILES
:
272 lpParms
->dwReturn
= FALSE
;
274 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
275 lpParms
->dwReturn
= FALSE
;
277 case MCI_GETDEVCAPS_CAN_EJECT
:
278 lpParms
->dwReturn
= TRUE
;
280 case MCI_GETDEVCAPS_CAN_PLAY
:
281 lpParms
->dwReturn
= TRUE
;
283 case MCI_GETDEVCAPS_CAN_SAVE
:
284 lpParms
->dwReturn
= FALSE
;
287 return MCIERR_UNRECOGNIZED_COMMAND
;
290 TRACE(cdaudio
, "lpParms->dwReturn=%08lX;\n", lpParms
->dwReturn
);
294 /**************************************************************************
295 * CDAUDIO_mciInfo [internal]
297 static DWORD
CDAUDIO_mciInfo(UINT16 wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS16 lpParms
)
301 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
303 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
305 if (lpParms
== NULL
|| lpParms
->lpstrReturn
== NULL
) {
306 ret
= MCIERR_NULL_PARAMETER_BLOCK
;
307 } else if (wmcda
== NULL
) {
308 ret
= MCIERR_INVALID_DEVICE_ID
;
310 TRACE(cdaudio
, "buf=%p, len=%lu\n", lpParms
->lpstrReturn
, lpParms
->dwRetSize
);
313 case MCI_INFO_PRODUCT
:
314 str
= "Wine's audio CD";
317 WARN(cdaudio
, "Don't know this info command (%lu)\n", dwFlags
);
318 ret
= MCIERR_UNRECOGNIZED_COMMAND
;
322 ret
= MCI_WriteString(lpParms
->lpstrReturn
, lpParms
->dwRetSize
, str
);
324 lpParms
->lpstrReturn
[0] = 0;
330 /**************************************************************************
331 * CDAUDIO_mciStatus [internal]
333 static DWORD
CDAUDIO_mciStatus(UINT16 wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
335 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
338 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
340 if (lpParms
== NULL
) {
341 ret
= MCIERR_NULL_PARAMETER_BLOCK
;
342 } else if (wmcda
== NULL
) {
343 ret
= MCIERR_INVALID_DEVICE_ID
;
345 if (dwFlags
& MCI_NOTIFY
) {
346 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
347 mciDriverNotify16((HWND16
)LOWORD(lpParms
->dwCallback
),
348 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
350 if (dwFlags
& MCI_STATUS_ITEM
) {
351 switch (lpParms
->dwItem
) {
352 case MCI_STATUS_CURRENT_TRACK
:
353 if (!CDAUDIO_GetCDStatus(&wmcda
->wcda
)) {
354 return CDAUDIO_mciGetError(wmcda
);
356 lpParms
->dwReturn
= wmcda
->wcda
.nCurTrack
;
357 TRACE(cdaudio
,"CURRENT_TRACK=%lu!\n", lpParms
->dwReturn
);
359 case MCI_STATUS_LENGTH
:
360 if (wmcda
->wcda
.nTracks
== 0) {
361 if (!CDAUDIO_GetTracksInfo(&wmcda
->wcda
)) {
362 WARN(cdaudio
, "error reading TracksInfo !\n");
363 return CDAUDIO_mciGetError(wmcda
);
366 if (dwFlags
& MCI_TRACK
) {
367 TRACE(cdaudio
,"MCI_TRACK #%lu LENGTH=??? !\n", lpParms
->dwTrack
);
368 if (lpParms
->dwTrack
> wmcda
->wcda
.nTracks
|| lpParms
->dwTrack
== 0)
369 return MCIERR_OUTOFRANGE
;
370 lpParms
->dwReturn
= wmcda
->wcda
.lpdwTrackLen
[lpParms
->dwTrack
- 1];
372 lpParms
->dwReturn
= wmcda
->wcda
.dwTotalLen
;
374 lpParms
->dwReturn
= CDAUDIO_CalcTime(wmcda
, lpParms
->dwReturn
);
375 TRACE(cdaudio
,"LENGTH=%lu !\n", lpParms
->dwReturn
);
377 case MCI_STATUS_MODE
:
378 if (!CDAUDIO_GetCDStatus(&wmcda
->wcda
))
379 return CDAUDIO_mciGetError(wmcda
);
380 lpParms
->dwReturn
= CDAUDIO_mciMode(wmcda
->wcda
.cdaMode
);
381 if (!lpParms
->dwReturn
) lpParms
->dwReturn
= wmcda
->mciMode
;
382 TRACE(cdaudio
,"MCI_STATUS_MODE=%08lX !\n", lpParms
->dwReturn
);
384 case MCI_STATUS_MEDIA_PRESENT
:
385 if (!CDAUDIO_GetCDStatus(&wmcda
->wcda
))
386 return CDAUDIO_mciGetError(wmcda
);
387 lpParms
->dwReturn
= (wmcda
->wcda
.nTracks
> 0) ? TRUE
: FALSE
;
388 TRACE(cdaudio
,"MCI_STATUS_MEDIA_PRESENT =%s!\n", lpParms
->dwReturn
? "Y" : "N");
390 case MCI_STATUS_NUMBER_OF_TRACKS
:
391 lpParms
->dwReturn
= CDAUDIO_GetNumberOfTracks(&wmcda
->wcda
);
392 TRACE(cdaudio
,"MCI_STATUS_NUMBER_OF_TRACKS = %lu !\n", lpParms
->dwReturn
);
393 if (lpParms
->dwReturn
== (WORD
)-1)
394 return CDAUDIO_mciGetError(wmcda
);
396 case MCI_STATUS_POSITION
:
397 if (!CDAUDIO_GetCDStatus(&wmcda
->wcda
))
398 return CDAUDIO_mciGetError(wmcda
);
399 lpParms
->dwReturn
= wmcda
->wcda
.dwCurFrame
;
400 if (dwFlags
& MCI_STATUS_START
) {
401 lpParms
->dwReturn
= wmcda
->wcda
.dwFirstOffset
;
402 TRACE(cdaudio
,"get MCI_STATUS_START !\n");
404 if (dwFlags
& MCI_TRACK
) {
405 if (lpParms
->dwTrack
> wmcda
->wcda
.nTracks
|| lpParms
->dwTrack
== 0)
406 return MCIERR_OUTOFRANGE
;
407 lpParms
->dwReturn
= wmcda
->wcda
.lpdwTrackPos
[lpParms
->dwTrack
- 1];
408 TRACE(cdaudio
,"get MCI_TRACK #%lu !\n", lpParms
->dwTrack
);
410 lpParms
->dwReturn
= CDAUDIO_CalcTime(wmcda
, lpParms
->dwReturn
);
411 TRACE(cdaudio
,"MCI_STATUS_POSITION=%08lX !\n", lpParms
->dwReturn
);
413 case MCI_STATUS_READY
:
414 TRACE(cdaudio
,"MCI_STATUS_READY !\n");
415 lpParms
->dwReturn
= (wmcda
->wcda
.cdaMode
!= WINE_CDA_DONTKNOW
&& wmcda
->wcda
.cdaMode
!= WINE_CDA_NOTREADY
);
416 TRACE(cdaudio
,"MCI_STATUS_READY=%ld!\n", lpParms
->dwReturn
);
418 case MCI_STATUS_TIME_FORMAT
:
419 lpParms
->dwReturn
= wmcda
->dwTimeFormat
;
420 TRACE(cdaudio
,"MCI_STATUS_TIME_FORMAT =%08lx!\n", lpParms
->dwReturn
);
422 case MCI_CDA_STATUS_TYPE_TRACK
:
423 if (!(dwFlags
& MCI_TRACK
))
424 return MCIERR_MISSING_PARAMETER
;
425 if (lpParms
->dwTrack
> wmcda
->wcda
.nTracks
|| lpParms
->dwTrack
== 0)
426 return MCIERR_OUTOFRANGE
;
427 lpParms
->dwReturn
= (wmcda
->wcda
.lpbTrackFlags
[lpParms
->dwTrack
- 1] &
428 CDROM_DATA_TRACK
) ? MCI_CDA_TRACK_OTHER
: MCI_CDA_TRACK_AUDIO
;
429 TRACE(cdaudio
, "MCI_CDA_STATUS_TYPE_TRACK[%ld]=%08lx\n", lpParms
->dwTrack
, lpParms
->dwReturn
);
432 WARN(cdaudio
, "unknown command %08lX !\n", lpParms
->dwItem
);
433 return MCIERR_UNRECOGNIZED_COMMAND
;
437 WARN(cdaudio
, "not MCI_STATUS_ITEM !\n");
441 /**************************************************************************
442 * CDAUDIO_mciPlay [internal]
444 static DWORD
CDAUDIO_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
447 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
450 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
452 if (lpParms
== NULL
) {
453 ret
= MCIERR_NULL_PARAMETER_BLOCK
;
454 } else if (wmcda
== NULL
) {
455 ret
= MCIERR_INVALID_DEVICE_ID
;
457 if (wmcda
->wcda
.nTracks
== 0) {
458 if (!CDAUDIO_GetTracksInfo(&wmcda
->wcda
)) {
459 WARN(cdaudio
, "error reading TracksInfo !\n");
460 return MCIERR_DRIVER_INTERNAL
;
463 end
= wmcda
->wcda
.dwTotalLen
;
464 wmcda
->wcda
.nCurTrack
= 1;
465 if (dwFlags
& MCI_FROM
) {
466 start
= CDAUDIO_CalcFrame(wmcda
, lpParms
->dwFrom
);
467 TRACE(cdaudio
,"MCI_FROM=%08lX -> %u \n", lpParms
->dwFrom
, start
);
469 if (!CDAUDIO_GetCDStatus(&wmcda
->wcda
)) return MCIERR_DRIVER_INTERNAL
;
470 start
= wmcda
->wcda
.dwCurFrame
;
472 if (dwFlags
& MCI_TO
) {
473 end
= CDAUDIO_CalcFrame(wmcda
, lpParms
->dwTo
);
474 TRACE(cdaudio
, "MCI_TO=%08lX -> %u \n", lpParms
->dwTo
, end
);
476 end
+= wmcda
->wcda
.dwFirstOffset
;
478 if (CDAUDIO_Play(&wmcda
->wcda
, start
, end
) == -1)
479 return MCIERR_HARDWARE
;
480 wmcda
->mciMode
= MCI_MODE_PLAY
;
481 if (dwFlags
& MCI_NOTIFY
) {
482 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
484 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
485 wmcda->wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
492 /**************************************************************************
493 * CDAUDIO_mciStop [internal]
495 static DWORD
CDAUDIO_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
497 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
499 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
501 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
503 if (CDAUDIO_Stop(&wmcda
->wcda
) == -1)
504 return MCIERR_HARDWARE
;
505 wmcda
->mciMode
= MCI_MODE_STOP
;
506 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
507 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
508 mciDriverNotify16((HWND16
)LOWORD(lpParms
->dwCallback
),
509 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
514 /**************************************************************************
515 * CDAUDIO_mciPause [internal]
517 static DWORD
CDAUDIO_mciPause(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
519 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
521 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
523 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
525 if (CDAUDIO_Pause(&wmcda
->wcda
, 1) == -1)
526 return MCIERR_HARDWARE
;
527 wmcda
->mciMode
= MCI_MODE_PAUSE
;
528 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
529 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
530 mciDriverNotify16((HWND16
)LOWORD(lpParms
->dwCallback
),
531 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
536 /**************************************************************************
537 * CDAUDIO_mciResume [internal]
539 static DWORD
CDAUDIO_mciResume(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
541 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
543 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
545 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
547 if (CDAUDIO_Pause(&wmcda
->wcda
, 0) == -1)
548 return MCIERR_HARDWARE
;
549 wmcda
->mciMode
= MCI_MODE_STOP
;
550 if (lpParms
&& (dwFlags
& MCI_NOTIFY
)) {
551 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
552 mciDriverNotify16((HWND16
)LOWORD(lpParms
->dwCallback
),
553 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
558 /**************************************************************************
559 * CDAUDIO_mciSeek [internal]
561 static DWORD
CDAUDIO_mciSeek(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SEEK_PARMS lpParms
)
564 MCI_PLAY_PARMS playParms
;
566 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
568 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
570 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
571 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;
573 wmcda
->mciMode
= MCI_MODE_SEEK
;
574 switch (dwFlags
& ~(MCI_NOTIFY
|MCI_WAIT
)) {
575 case MCI_SEEK_TO_START
:
576 TRACE(cdaudio
, "Seeking to start\n");
577 playParms
.dwFrom
= 0;
579 case MCI_SEEK_TO_END
:
580 TRACE(cdaudio
, "Seeking to end\n");
581 playParms
.dwFrom
= wmcda
->wcda
.dwTotalLen
;
584 TRACE(cdaudio
, "Seeking to %lu\n", lpParms
->dwTo
);
585 playParms
.dwFrom
= lpParms
->dwTo
;
588 TRACE(cdaudio
, "Seeking to ??=%lu\n", dwFlags
);
589 return MCIERR_UNSUPPORTED_FUNCTION
;
591 dwRet
= CDAUDIO_mciPlay(wDevID
, MCI_WAIT
| MCI_FROM
, &playParms
);
592 if (dwRet
!= 0) return dwRet
;
593 dwRet
= CDAUDIO_mciStop(wDevID
, MCI_WAIT
, (LPMCI_GENERIC_PARMS
)&playParms
);
594 if (dwFlags
& MCI_NOTIFY
) {
595 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
596 mciDriverNotify16((HWND16
)LOWORD(lpParms
->dwCallback
),
597 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
602 /**************************************************************************
603 * CDAUDIO_mciSetDoor [internal]
605 static DWORD
CDAUDIO_mciSetDoor(UINT16 wDevID
, int open
)
607 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
609 TRACE(cdaudio
, "(%04x, %s) !\n", wDevID
, (open
) ? "OPEN" : "CLOSE");
611 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
613 if (CDAUDIO_SetDoor(&wmcda
->wcda
, open
) == -1)
614 return MCIERR_HARDWARE
;
615 wmcda
->mciMode
= (open
) ? MCI_MODE_OPEN
: MCI_MODE_STOP
;
619 /**************************************************************************
620 * CDAUDIO_mciSet [internal]
622 static DWORD
CDAUDIO_mciSet(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
624 WINE_MCICDAUDIO
* wmcda
= CDAUDIO_mciGetOpenDrv(wDevID
);
626 TRACE(cdaudio
,"(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
628 if (wmcda
== NULL
) return MCIERR_INVALID_DEVICE_ID
;
629 if (lpParms
== NULL
) return MCIERR_NULL_PARAMETER_BLOCK
;;
631 TRACE(cdaudio,"dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
632 TRACE(cdaudio,"dwAudio=%08lX\n", lpParms->dwAudio);
634 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
635 switch (lpParms
->dwTimeFormat
) {
636 case MCI_FORMAT_MILLISECONDS
:
637 TRACE(cdaudio
, "MCI_FORMAT_MILLISECONDS !\n");
640 TRACE(cdaudio
,"MCI_FORMAT_MSF !\n");
642 case MCI_FORMAT_TMSF
:
643 TRACE(cdaudio
,"MCI_FORMAT_TMSF !\n");
646 WARN(cdaudio
, "bad time format !\n");
647 return MCIERR_BAD_TIME_FORMAT
;
649 wmcda
->dwTimeFormat
= lpParms
->dwTimeFormat
;
651 if (dwFlags
& MCI_SET_DOOR_OPEN
) {
652 CDAUDIO_mciSetDoor(wDevID
, TRUE
);
654 if (dwFlags
& MCI_SET_DOOR_CLOSED
) {
655 CDAUDIO_mciSetDoor(wDevID
, FALSE
);
657 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
658 if (dwFlags
& MCI_SET_ON
) return MCIERR_UNSUPPORTED_FUNCTION
;
659 if (dwFlags
& MCI_SET_OFF
) return MCIERR_UNSUPPORTED_FUNCTION
;
660 if (dwFlags
& MCI_NOTIFY
) {
661 TRACE(cdaudio
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n",
662 lpParms
->dwCallback
);
663 mciDriverNotify16((HWND16
)LOWORD(lpParms
->dwCallback
),
664 wmcda
->wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
669 /**************************************************************************
670 * MCICDAUDIO_DriverProc32 [sample driver]
672 LONG
MCICDAUDIO_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, DWORD wMsg
,
673 DWORD dwParam1
, DWORD dwParam2
)
676 case DRV_LOAD
: return 1;
677 case DRV_FREE
: return 1;
678 case DRV_OPEN
: return 1;
679 case DRV_CLOSE
: return 1;
680 case DRV_ENABLE
: return 1;
681 case DRV_DISABLE
: return 1;
682 case DRV_QUERYCONFIGURE
: return 1;
683 case DRV_CONFIGURE
: MessageBoxA(0, "Sample Multimedia Linux Driver !", "MMLinux Driver", MB_OK
); return 1;
684 case DRV_INSTALL
: return DRVCNF_RESTART
;
685 case DRV_REMOVE
: return DRVCNF_RESTART
;
687 case MCI_OPEN_DRIVER
: return CDAUDIO_mciOpen(dwDevID
, dwParam1
, (LPMCI_OPEN_PARMSA
)dwParam2
);
688 case MCI_CLOSE_DRIVER
: return CDAUDIO_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
689 case MCI_GETDEVCAPS
: return CDAUDIO_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)dwParam2
);
690 case MCI_INFO
: return CDAUDIO_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS16
)dwParam2
);
691 case MCI_STATUS
: return CDAUDIO_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)dwParam2
);
692 case MCI_SET
: return CDAUDIO_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)dwParam2
);
693 case MCI_PLAY
: return CDAUDIO_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)dwParam2
);
694 case MCI_STOP
: return CDAUDIO_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
695 case MCI_PAUSE
: return CDAUDIO_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
696 case MCI_RESUME
: return CDAUDIO_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)dwParam2
);
697 case MCI_SEEK
: return CDAUDIO_mciSeek(dwDevID
, dwParam1
, (LPMCI_SEEK_PARMS
)dwParam2
);
698 /* FIXME: I wonder if those two next items are really called ? */
699 case MCI_SET_DOOR_OPEN
: return CDAUDIO_mciSetDoor(dwDevID
, TRUE
);
700 case MCI_SET_DOOR_CLOSED
: return CDAUDIO_mciSetDoor(dwDevID
, FALSE
);
717 WARN(cdaudio
, "Unsupported command=%s\n", MCI_CommandToString(wMsg
));
721 FIXME(cdaudio
, "Shouldn't receive a MCI_OPEN or CLOSE message\n");
724 TRACE(cdaudio
, "Sending msg=%s to default driver proc\n", MCI_CommandToString(wMsg
));
725 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
727 return MCIERR_UNRECOGNIZED_COMMAND
;
730 /*-----------------------------------------------------------------------*/