1 /* -*- tab-width: 8; c-basic-offset: 4 -*- */
3 * Wine Wave mapper driver
5 * Copyright 1999,2001 Eric Pouech
9 * + better protection against evilish dwUser parameters
10 * + use asynchronous ACM conversion
11 * + don't use callback functions when none is required in open
12 * + the buffer sizes may not be accurate, so there may be some
13 * remaining bytes in src and dst buffers after ACM conversions...
14 * those should be taken care of...
24 #include "debugtools.h"
26 DEFAULT_DEBUG_CHANNEL(msacm
);
28 typedef struct tagWAVEMAPDATA
{
29 struct tagWAVEMAPDATA
* self
;
32 HACMSTREAM hAcmStream
;
33 /* needed data to filter callbacks. Only needed when hAcmStream is not 0 */
35 DWORD dwClientInstance
;
39 static BOOL
WAVEMAP_IsData(WAVEMAPDATA
* wm
)
41 return (!IsBadReadPtr(wm
, sizeof(WAVEMAPDATA
)) && wm
->self
== wm
);
44 /*======================================================================*
46 *======================================================================*/
48 static void CALLBACK
wodCallback(HWAVE hWave
, UINT uMsg
, DWORD dwInstance
,
49 DWORD dwParam1
, DWORD dwParam2
)
51 WAVEMAPDATA
* wom
= (WAVEMAPDATA
*)dwInstance
;
53 TRACE("(0x%x %u %ld %lx %lx);\n", hWave
, uMsg
, dwInstance
, dwParam1
, dwParam2
);
55 if (!WAVEMAP_IsData(wom
)) {
60 if (hWave
!= wom
->hInnerWave
&& uMsg
!= WOM_OPEN
)
61 ERR("Shouldn't happen (%08x %08x)\n", hWave
, wom
->hInnerWave
);
66 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
69 if (wom
->hAcmStream
) {
70 LPWAVEHDR lpWaveHdrDst
= (LPWAVEHDR
)dwParam1
;
71 PACMSTREAMHEADER ash
= (PACMSTREAMHEADER
)((LPSTR
)lpWaveHdrDst
- sizeof(ACMSTREAMHEADER
));
72 LPWAVEHDR lpWaveHdrSrc
= (LPWAVEHDR
)ash
->dwUser
;
74 lpWaveHdrSrc
->dwFlags
&= ~WHDR_INQUEUE
;
75 lpWaveHdrSrc
->dwFlags
|= WHDR_DONE
;
76 dwParam1
= (DWORD
)lpWaveHdrSrc
;
80 ERR("Unknown msg %u\n", uMsg
);
83 DriverCallback(wom
->dwCallback
, HIWORD(wom
->dwFlags
), wom
->hOuterWave
, uMsg
,
84 wom
->dwClientInstance
, dwParam1
, dwParam2
);
87 static DWORD
wodOpenHelper(WAVEMAPDATA
* wom
, UINT idx
,
88 LPWAVEOPENDESC lpDesc
, LPWAVEFORMATEX lpwfx
,
93 /* destination is always PCM, so the formulas below apply */
94 lpwfx
->nBlockAlign
= (lpwfx
->nChannels
* lpwfx
->wBitsPerSample
) / 8;
95 lpwfx
->nAvgBytesPerSec
= lpwfx
->nSamplesPerSec
* lpwfx
->nBlockAlign
;
96 ret
= acmStreamOpen(&wom
->hAcmStream
, 0, lpDesc
->lpFormat
, lpwfx
, NULL
, 0L, 0L,
97 (dwFlags
& WAVE_FORMAT_QUERY
) ? ACM_STREAMOPENF_QUERY
: 0L);
98 if (ret
!= MMSYSERR_NOERROR
)
100 return waveOutOpen(&wom
->hInnerWave
, idx
, lpwfx
, (DWORD
)wodCallback
,
101 (DWORD
)wom
, (dwFlags
& ~CALLBACK_TYPEMASK
) | CALLBACK_FUNCTION
);
104 static DWORD
wodOpen(LPDWORD lpdwUser
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
106 UINT nd
= waveOutGetNumDevs();
108 WAVEMAPDATA
* wom
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA
));
111 TRACE("(%p %p %08lx\n", lpdwUser
, lpDesc
, dwFlags
);
114 return MMSYSERR_NOMEM
;
117 wom
->dwCallback
= lpDesc
->dwCallback
;
118 wom
->dwFlags
= dwFlags
;
119 wom
->dwClientInstance
= lpDesc
->dwInstance
;
120 wom
->hOuterWave
= lpDesc
->hWave
;
122 for (i
= 0; i
< nd
; i
++) {
123 /* if no ACM stuff is involved, no need to handle callbacks at this
124 * level, this will be done transparently
126 if (waveOutOpen(&wom
->hInnerWave
, i
, lpDesc
->lpFormat
, (DWORD
)wodCallback
,
127 (DWORD
)wom
, (dwFlags
& ~CALLBACK_TYPEMASK
) | CALLBACK_FUNCTION
) == MMSYSERR_NOERROR
) {
133 wfx
.wFormatTag
= WAVE_FORMAT_PCM
;
134 wfx
.cbSize
= 0; /* normally, this field is not used for PCM format, just in case */
135 /* try some ACM stuff */
137 #define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \
138 if (wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags) == MMSYSERR_NOERROR) goto found;
140 for (i
= 0; i
< nd
; i
++) {
141 /* first try with same stereo/mono option as source */
142 wfx
.nChannels
= lpDesc
->lpFormat
->nChannels
;
147 /* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
155 HeapFree(GetProcessHeap(), 0, wom
);
156 return MMSYSERR_ALLOCATED
;
158 if (dwFlags
& WAVE_FORMAT_QUERY
) {
160 HeapFree(GetProcessHeap(), 0, wom
);
162 *lpdwUser
= (DWORD
)wom
;
164 return MMSYSERR_NOERROR
;
167 static DWORD
wodClose(WAVEMAPDATA
* wom
)
169 DWORD ret
= waveOutClose(wom
->hInnerWave
);
171 if (ret
== MMSYSERR_NOERROR
) {
172 if (wom
->hAcmStream
) {
173 ret
= acmStreamClose(wom
->hAcmStream
, 0);
175 if (ret
== MMSYSERR_NOERROR
) {
176 HeapFree(GetProcessHeap(), 0, wom
);
182 static DWORD
wodWrite(WAVEMAPDATA
* wom
, LPWAVEHDR lpWaveHdrSrc
, DWORD dwParam2
)
184 PACMSTREAMHEADER ash
;
185 LPWAVEHDR lpWaveHdrDst
;
187 if (!wom
->hAcmStream
) {
188 return waveOutWrite(wom
->hInnerWave
, lpWaveHdrSrc
, dwParam2
);
191 lpWaveHdrSrc
->dwFlags
|= WHDR_INQUEUE
;
192 ash
= (PACMSTREAMHEADER
)lpWaveHdrSrc
->reserved
;
193 if (acmStreamConvert(wom
->hAcmStream
, ash
, 0L) != MMSYSERR_NOERROR
)
194 return MMSYSERR_ERROR
;
196 lpWaveHdrDst
= (LPWAVEHDR
)((LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
));
197 lpWaveHdrDst
->dwBufferLength
= ash
->cbDstLengthUsed
;
198 return waveOutWrite(wom
->hInnerWave
, lpWaveHdrDst
, sizeof(*lpWaveHdrDst
));
201 static DWORD
wodPrepare(WAVEMAPDATA
* wom
, LPWAVEHDR lpWaveHdrSrc
, DWORD dwParam2
)
203 PACMSTREAMHEADER ash
;
206 LPWAVEHDR lpWaveHdrDst
;
208 if (!wom
->hAcmStream
) {
209 return waveOutPrepareHeader(wom
->hInnerWave
, lpWaveHdrSrc
, dwParam2
);
211 if (acmStreamSize(wom
->hAcmStream
, lpWaveHdrSrc
->dwBufferLength
, &size
, ACM_STREAMSIZEF_SOURCE
) != MMSYSERR_NOERROR
)
212 return MMSYSERR_ERROR
;
214 ash
= HeapAlloc(GetProcessHeap(), 0, sizeof(ACMSTREAMHEADER
) + sizeof(WAVEHDR
) + size
);
216 return MMSYSERR_NOMEM
;
218 ash
->cbStruct
= sizeof(*ash
);
220 ash
->dwUser
= (DWORD
)lpWaveHdrSrc
;
221 ash
->pbSrc
= lpWaveHdrSrc
->lpData
;
222 ash
->cbSrcLength
= lpWaveHdrSrc
->dwBufferLength
;
223 /* ash->cbSrcLengthUsed */
224 ash
->dwSrcUser
= lpWaveHdrSrc
->dwUser
; /* FIXME ? */
225 ash
->pbDst
= (LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
) + sizeof(WAVEHDR
);
226 ash
->cbDstLength
= size
;
227 /* ash->cbDstLengthUsed */
228 ash
->dwDstUser
= 0; /* FIXME ? */
229 dwRet
= acmStreamPrepareHeader(wom
->hAcmStream
, ash
, 0L);
230 if (dwRet
!= MMSYSERR_NOERROR
)
233 lpWaveHdrDst
= (LPWAVEHDR
)((LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
));
234 lpWaveHdrDst
->lpData
= ash
->pbDst
;
235 lpWaveHdrDst
->dwBufferLength
= size
; /* conversion is not done yet */
236 lpWaveHdrDst
->dwFlags
= 0;
237 lpWaveHdrDst
->dwLoops
= 0;
238 dwRet
= waveOutPrepareHeader(wom
->hInnerWave
, lpWaveHdrDst
, sizeof(*lpWaveHdrDst
));
239 if (dwRet
!= MMSYSERR_NOERROR
)
242 lpWaveHdrSrc
->reserved
= (DWORD
)ash
;
243 lpWaveHdrSrc
->dwFlags
= WHDR_PREPARED
;
245 return MMSYSERR_NOERROR
;
247 TRACE("=> (%ld)\n", dwRet
);
248 HeapFree(GetProcessHeap(), 0, ash
);
252 static DWORD
wodUnprepare(WAVEMAPDATA
* wom
, LPWAVEHDR lpWaveHdrSrc
, DWORD dwParam2
)
254 PACMSTREAMHEADER ash
;
255 LPWAVEHDR lpWaveHdrDst
;
256 DWORD dwRet1
, dwRet2
;
258 if (!wom
->hAcmStream
) {
259 return waveOutUnprepareHeader(wom
->hInnerWave
, lpWaveHdrSrc
, dwParam2
);
261 ash
= (PACMSTREAMHEADER
)lpWaveHdrSrc
->reserved
;
262 dwRet1
= acmStreamUnprepareHeader(wom
->hAcmStream
, ash
, 0L);
264 lpWaveHdrDst
= (LPWAVEHDR
)((LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
));
265 dwRet2
= waveOutUnprepareHeader(wom
->hInnerWave
, lpWaveHdrDst
, sizeof(*lpWaveHdrDst
));
267 HeapFree(GetProcessHeap(), 0, ash
);
269 lpWaveHdrSrc
->dwFlags
&= ~WHDR_PREPARED
;
270 return (dwRet1
== MMSYSERR_NOERROR
) ? dwRet2
: dwRet1
;
273 static DWORD
wodGetPosition(WAVEMAPDATA
* wom
, LPMMTIME lpTime
, DWORD dwParam2
)
276 FIXME("No position conversion done for PCM => non-PCM, returning PCM position\n");
277 return waveOutGetPosition(wom
->hInnerWave
, lpTime
, dwParam2
);
280 static DWORD
wodGetDevCaps(UINT wDevID
, WAVEMAPDATA
* wom
, LPWAVEOUTCAPSA lpWaveCaps
, DWORD dwParam2
)
282 /* if opened low driver, forward message */
283 if (WAVEMAP_IsData(wom
))
284 return waveOutGetDevCapsA(wom
->hInnerWave
, lpWaveCaps
, dwParam2
);
285 /* otherwise, return caps of mapper itself */
286 if (wDevID
== (UINT
)-1 || wDevID
== (UINT16
)-1) {
287 lpWaveCaps
->wMid
= 0x00FF;
288 lpWaveCaps
->wPid
= 0x0001;
289 lpWaveCaps
->vDriverVersion
= 0x0100;
290 strcpy(lpWaveCaps
->szPname
, "Wine wave out mapper");
291 lpWaveCaps
->dwFormats
=
292 WAVE_FORMAT_4M08
| WAVE_FORMAT_4S08
| WAVE_FORMAT_4M16
| WAVE_FORMAT_4S16
|
293 WAVE_FORMAT_2M08
| WAVE_FORMAT_2S08
| WAVE_FORMAT_2M16
| WAVE_FORMAT_2S16
|
294 WAVE_FORMAT_1M08
| WAVE_FORMAT_1S08
| WAVE_FORMAT_1M16
| WAVE_FORMAT_1S16
;
295 lpWaveCaps
->wChannels
= 2;
296 lpWaveCaps
->dwSupport
= WAVECAPS_VOLUME
| WAVECAPS_LRVOLUME
;
298 return MMSYSERR_NOERROR
;
300 ERR("This shouldn't happen\n");
301 return MMSYSERR_ERROR
;
304 static DWORD
wodGetVolume(UINT wDevID
, WAVEMAPDATA
* wom
, LPDWORD lpVol
)
306 if (WAVEMAP_IsData(wom
))
307 return waveOutGetVolume(wom
->hInnerWave
, lpVol
);
308 return MMSYSERR_NOERROR
;
311 static DWORD
wodSetVolume(UINT wDevID
, WAVEMAPDATA
* wom
, DWORD vol
)
313 if (WAVEMAP_IsData(wom
))
314 return waveOutSetVolume(wom
->hInnerWave
, vol
);
315 return MMSYSERR_NOERROR
;
318 static DWORD
wodPause(WAVEMAPDATA
* wom
)
320 return waveOutPause(wom
->hInnerWave
);
323 static DWORD
wodRestart(WAVEMAPDATA
* wom
)
325 return waveOutRestart(wom
->hInnerWave
);
328 static DWORD
wodReset(WAVEMAPDATA
* wom
)
330 return waveOutReset(wom
->hInnerWave
);
333 static DWORD
wodBreakLoop(WAVEMAPDATA
* wom
)
335 return waveOutBreakLoop(wom
->hInnerWave
);
338 static DWORD
wodMapperStatus(WAVEMAPDATA
* wom
, DWORD flags
, LPVOID ptr
)
341 DWORD ret
= MMSYSERR_NOTSUPPORTED
;
344 case WAVEOUT_MAPPER_STATUS_DEVICE
:
345 ret
= waveOutGetID(wom
->hInnerWave
, &id
);
348 case WAVEOUT_MAPPER_STATUS_MAPPED
:
349 FIXME("Unsupported flag=%ld\n", flags
);
350 *(LPDWORD
)ptr
= 0; /* FIXME ?? */
352 case WAVEOUT_MAPPER_STATUS_FORMAT
:
353 FIXME("Unsupported flag=%ld\n", flags
);
354 /* ptr points to a WAVEFORMATEX struct - before or after streaming ? */
358 FIXME("Unsupported flag=%ld\n", flags
);
365 /**************************************************************************
366 * WAVEMAP_wodMessage [sample driver]
368 DWORD WINAPI
WAVEMAP_wodMessage(UINT wDevID
, UINT wMsg
, DWORD dwUser
,
369 DWORD dwParam1
, DWORD dwParam2
)
371 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
372 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
379 /* FIXME: Pretend this is supported */
381 case WODM_OPEN
: return wodOpen ((LPDWORD
)dwUser
, (LPWAVEOPENDESC
)dwParam1
,dwParam2
);
382 case WODM_CLOSE
: return wodClose ((WAVEMAPDATA
*)dwUser
);
383 case WODM_WRITE
: return wodWrite ((WAVEMAPDATA
*)dwUser
, (LPWAVEHDR
)dwParam1
, dwParam2
);
384 case WODM_PAUSE
: return wodPause ((WAVEMAPDATA
*)dwUser
);
385 case WODM_GETPOS
: return wodGetPosition ((WAVEMAPDATA
*)dwUser
, (LPMMTIME
)dwParam1
, dwParam2
);
386 case WODM_BREAKLOOP
: return wodBreakLoop ((WAVEMAPDATA
*)dwUser
);
387 case WODM_PREPARE
: return wodPrepare ((WAVEMAPDATA
*)dwUser
, (LPWAVEHDR
)dwParam1
, dwParam2
);
388 case WODM_UNPREPARE
: return wodUnprepare ((WAVEMAPDATA
*)dwUser
, (LPWAVEHDR
)dwParam1
, dwParam2
);
389 case WODM_GETDEVCAPS
: return wodGetDevCaps (wDevID
, (WAVEMAPDATA
*)dwUser
, (LPWAVEOUTCAPSA
)dwParam1
,dwParam2
);
390 case WODM_GETNUMDEVS
: return 1;
391 case WODM_GETPITCH
: return MMSYSERR_NOTSUPPORTED
;
392 case WODM_SETPITCH
: return MMSYSERR_NOTSUPPORTED
;
393 case WODM_GETPLAYBACKRATE
: return MMSYSERR_NOTSUPPORTED
;
394 case WODM_SETPLAYBACKRATE
: return MMSYSERR_NOTSUPPORTED
;
395 case WODM_GETVOLUME
: return wodGetVolume (wDevID
, (WAVEMAPDATA
*)dwUser
, (LPDWORD
)dwParam1
);
396 case WODM_SETVOLUME
: return wodSetVolume (wDevID
, (WAVEMAPDATA
*)dwUser
, dwParam1
);
397 case WODM_RESTART
: return wodRestart ((WAVEMAPDATA
*)dwUser
);
398 case WODM_RESET
: return wodReset ((WAVEMAPDATA
*)dwUser
);
399 case WODM_MAPPER_STATUS
: return wodMapperStatus ((WAVEMAPDATA
*)dwUser
, dwParam1
, (LPVOID
)dwParam2
);
401 FIXME("unknown message %d!\n", wMsg
);
403 return MMSYSERR_NOTSUPPORTED
;
406 /*======================================================================*
408 *======================================================================*/
410 static void CALLBACK
widCallback(HWAVE hWave
, UINT uMsg
, DWORD dwInstance
,
411 DWORD dwParam1
, DWORD dwParam2
)
413 WAVEMAPDATA
* wim
= (WAVEMAPDATA
*)dwInstance
;
415 TRACE("(0x%x %u %ld %lx %lx);\n", hWave
, uMsg
, dwInstance
, dwParam1
, dwParam2
);
417 if (!WAVEMAP_IsData(wim
)) {
422 if (hWave
!= wim
->hInnerWave
&& uMsg
!= WIM_OPEN
)
423 ERR("Shouldn't happen (%08x %08x)\n", hWave
, wim
->hInnerWave
);
428 /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */
431 if (wim
->hAcmStream
) {
432 LPWAVEHDR lpWaveHdrSrc
= (LPWAVEHDR
)dwParam1
;
433 PACMSTREAMHEADER ash
= (PACMSTREAMHEADER
)((LPSTR
)lpWaveHdrSrc
- sizeof(ACMSTREAMHEADER
));
434 LPWAVEHDR lpWaveHdrDst
= (LPWAVEHDR
)ash
->dwUser
;
436 /* convert data just gotten from waveIn into requested format */
437 if (acmStreamConvert(wim
->hAcmStream
, ash
, 0L) != MMSYSERR_NOERROR
) {
438 ERR("ACM conversion failed\n");
441 TRACE("Converted %ld bytes into %ld\n", ash
->cbSrcLengthUsed
, ash
->cbDstLengthUsed
);
443 /* and setup the wavehdr to return accordingly */
444 lpWaveHdrDst
->dwFlags
&= ~WHDR_INQUEUE
;
445 lpWaveHdrDst
->dwFlags
|= WHDR_DONE
;
446 lpWaveHdrDst
->dwBytesRecorded
= ash
->cbDstLengthUsed
;
447 dwParam1
= (DWORD
)lpWaveHdrDst
;
451 ERR("Unknown msg %u\n", uMsg
);
454 DriverCallback(wim
->dwCallback
, HIWORD(wim
->dwFlags
), wim
->hOuterWave
, uMsg
,
455 wim
->dwClientInstance
, dwParam1
, dwParam2
);
458 static DWORD
widOpenHelper(WAVEMAPDATA
* wim
, UINT idx
,
459 LPWAVEOPENDESC lpDesc
, LPWAVEFORMATEX lpwfx
,
464 /* source is always PCM, so the formulas below apply */
465 lpwfx
->nBlockAlign
= (lpwfx
->nChannels
* lpwfx
->wBitsPerSample
) / 8;
466 lpwfx
->nAvgBytesPerSec
= lpwfx
->nSamplesPerSec
* lpwfx
->nBlockAlign
;
467 ret
= acmStreamOpen(&wim
->hAcmStream
, 0, lpwfx
, lpDesc
->lpFormat
, NULL
, 0L, 0L,
468 (dwFlags
& WAVE_FORMAT_QUERY
) ? ACM_STREAMOPENF_QUERY
: 0L);
469 if (ret
!= MMSYSERR_NOERROR
)
471 return waveInOpen(&wim
->hInnerWave
, idx
, lpwfx
, (DWORD
)widCallback
,
472 (DWORD
)wim
, (dwFlags
& ~CALLBACK_TYPEMASK
) | CALLBACK_FUNCTION
);
475 static DWORD
widOpen(LPDWORD lpdwUser
, LPWAVEOPENDESC lpDesc
, DWORD dwFlags
)
477 UINT nd
= waveInGetNumDevs();
479 WAVEMAPDATA
* wim
= HeapAlloc(GetProcessHeap(), 0, sizeof(WAVEMAPDATA
));
482 TRACE("(%p %p %08lx\n", lpdwUser
, lpDesc
, dwFlags
);
485 return MMSYSERR_NOMEM
;
488 wim
->dwCallback
= lpDesc
->dwCallback
;
489 wim
->dwFlags
= dwFlags
;
490 wim
->dwClientInstance
= lpDesc
->dwInstance
;
491 wim
->hOuterWave
= lpDesc
->hWave
;
493 for (i
= 0; i
< nd
; i
++) {
494 if (waveInOpen(&wim
->hInnerWave
, i
, lpDesc
->lpFormat
, (DWORD
)widCallback
,
495 (DWORD
)wim
, (dwFlags
& ~CALLBACK_TYPEMASK
) | CALLBACK_FUNCTION
) == MMSYSERR_NOERROR
) {
500 wfx
.wFormatTag
= WAVE_FORMAT_PCM
;
501 wfx
.cbSize
= 0; /* normally, this field is not used for PCM format, just in case */
502 /* try some ACM stuff */
504 #define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \
505 if (widOpenHelper(wim, i, lpDesc, &wfx, dwFlags) == MMSYSERR_NOERROR) goto found;
507 for (i
= 0; i
< nd
; i
++) {
508 /* first try with same stereo/mono option as source */
509 wfx
.nChannels
= lpDesc
->lpFormat
->nChannels
;
514 /* 2^3 => 1, 1^3 => 2, so if stereo, try mono (and the other way around) */
522 HeapFree(GetProcessHeap(), 0, wim
);
523 return MMSYSERR_ALLOCATED
;
525 if (dwFlags
& WAVE_FORMAT_QUERY
) {
527 HeapFree(GetProcessHeap(), 0, wim
);
529 *lpdwUser
= (DWORD
)wim
;
531 return MMSYSERR_NOERROR
;
534 static DWORD
widClose(WAVEMAPDATA
* wim
)
536 DWORD ret
= waveInClose(wim
->hInnerWave
);
538 if (ret
== MMSYSERR_NOERROR
) {
539 if (wim
->hAcmStream
) {
540 ret
= acmStreamClose(wim
->hAcmStream
, 0);
542 if (ret
== MMSYSERR_NOERROR
) {
543 HeapFree(GetProcessHeap(), 0, wim
);
549 static DWORD
widAddBuffer(WAVEMAPDATA
* wim
, LPWAVEHDR lpWaveHdrDst
, DWORD dwParam2
)
551 PACMSTREAMHEADER ash
;
552 LPWAVEHDR lpWaveHdrSrc
;
554 if (!wim
->hAcmStream
) {
555 return waveInAddBuffer(wim
->hInnerWave
, lpWaveHdrDst
, dwParam2
);
558 lpWaveHdrDst
->dwFlags
|= WHDR_INQUEUE
;
559 ash
= (PACMSTREAMHEADER
)lpWaveHdrDst
->reserved
;
561 lpWaveHdrSrc
= (LPWAVEHDR
)((LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
));
562 return waveInAddBuffer(wim
->hInnerWave
, lpWaveHdrSrc
, sizeof(*lpWaveHdrSrc
));
565 static DWORD
widPrepare(WAVEMAPDATA
* wim
, LPWAVEHDR lpWaveHdrDst
, DWORD dwParam2
)
567 PACMSTREAMHEADER ash
;
570 LPWAVEHDR lpWaveHdrSrc
;
572 if (!wim
->hAcmStream
) {
573 return waveInPrepareHeader(wim
->hInnerWave
, lpWaveHdrDst
, dwParam2
);
575 if (acmStreamSize(wim
->hAcmStream
, lpWaveHdrDst
->dwBufferLength
, &size
,
576 ACM_STREAMSIZEF_DESTINATION
) != MMSYSERR_NOERROR
)
577 return MMSYSERR_ERROR
;
579 ash
= HeapAlloc(GetProcessHeap(), 0, sizeof(ACMSTREAMHEADER
) + sizeof(WAVEHDR
) + size
);
581 return MMSYSERR_NOMEM
;
583 ash
->cbStruct
= sizeof(*ash
);
585 ash
->dwUser
= (DWORD
)lpWaveHdrDst
;
586 ash
->pbSrc
= (LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
) + sizeof(WAVEHDR
);
587 ash
->cbSrcLength
= size
;
588 /* ash->cbSrcLengthUsed */
589 ash
->dwSrcUser
= 0L; /* FIXME ? */
590 ash
->pbDst
= lpWaveHdrDst
->lpData
;
591 ash
->cbDstLength
= lpWaveHdrDst
->dwBufferLength
;
592 /* ash->cbDstLengthUsed */
593 ash
->dwDstUser
= lpWaveHdrDst
->dwUser
; /* FIXME ? */
594 dwRet
= acmStreamPrepareHeader(wim
->hAcmStream
, ash
, 0L);
595 if (dwRet
!= MMSYSERR_NOERROR
)
598 lpWaveHdrSrc
= (LPWAVEHDR
)((LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
));
599 lpWaveHdrSrc
->lpData
= ash
->pbSrc
;
600 lpWaveHdrSrc
->dwBufferLength
= size
; /* conversion is not done yet */
601 lpWaveHdrSrc
->dwFlags
= 0;
602 lpWaveHdrSrc
->dwLoops
= 0;
603 dwRet
= waveInPrepareHeader(wim
->hInnerWave
, lpWaveHdrSrc
, sizeof(*lpWaveHdrSrc
));
604 if (dwRet
!= MMSYSERR_NOERROR
)
607 lpWaveHdrDst
->reserved
= (DWORD
)ash
;
608 lpWaveHdrDst
->dwFlags
= WHDR_PREPARED
;
610 return MMSYSERR_NOERROR
;
612 TRACE("=> (%ld)\n", dwRet
);
613 HeapFree(GetProcessHeap(), 0, ash
);
617 static DWORD
widUnprepare(WAVEMAPDATA
* wim
, LPWAVEHDR lpWaveHdrDst
, DWORD dwParam2
)
619 PACMSTREAMHEADER ash
;
620 LPWAVEHDR lpWaveHdrSrc
;
621 DWORD dwRet1
, dwRet2
;
623 if (!wim
->hAcmStream
) {
624 return waveInUnprepareHeader(wim
->hInnerWave
, lpWaveHdrDst
, dwParam2
);
626 ash
= (PACMSTREAMHEADER
)lpWaveHdrDst
->reserved
;
627 dwRet1
= acmStreamUnprepareHeader(wim
->hAcmStream
, ash
, 0L);
629 lpWaveHdrSrc
= (LPWAVEHDR
)((LPSTR
)ash
+ sizeof(ACMSTREAMHEADER
));
630 dwRet2
= waveInUnprepareHeader(wim
->hInnerWave
, lpWaveHdrSrc
, sizeof(*lpWaveHdrSrc
));
632 HeapFree(GetProcessHeap(), 0, ash
);
634 lpWaveHdrDst
->dwFlags
&= ~WHDR_PREPARED
;
635 return (dwRet1
== MMSYSERR_NOERROR
) ? dwRet2
: dwRet1
;
638 static DWORD
widGetPosition(WAVEMAPDATA
* wim
, LPMMTIME lpTime
, DWORD dwParam2
)
641 FIXME("No position conversion done for PCM => non-PCM, returning PCM position\n");
642 return waveInGetPosition(wim
->hInnerWave
, lpTime
, dwParam2
);
645 static DWORD
widGetDevCaps(UINT wDevID
, WAVEMAPDATA
* wim
, LPWAVEINCAPSA lpWaveCaps
, DWORD dwParam2
)
647 /* if opened low driver, forward message */
648 if (WAVEMAP_IsData(wim
))
649 return waveInGetDevCapsA(wim
->hInnerWave
, lpWaveCaps
, dwParam2
);
650 /* otherwise, return caps of mapper itself */
651 if (wDevID
== (UINT
)-1 || wDevID
== (UINT16
)-1) {
652 lpWaveCaps
->wMid
= 0x00FF;
653 lpWaveCaps
->wPid
= 0x0001;
654 lpWaveCaps
->vDriverVersion
= 0x0001;
655 strcpy(lpWaveCaps
->szPname
, "Wine wave in mapper");
656 lpWaveCaps
->dwFormats
=
657 WAVE_FORMAT_4M08
| WAVE_FORMAT_4S08
| WAVE_FORMAT_4M16
| WAVE_FORMAT_4S16
|
658 WAVE_FORMAT_2M08
| WAVE_FORMAT_2S08
| WAVE_FORMAT_2M16
| WAVE_FORMAT_2S16
|
659 WAVE_FORMAT_1M08
| WAVE_FORMAT_1S08
| WAVE_FORMAT_1M16
| WAVE_FORMAT_1S16
;
660 lpWaveCaps
->wChannels
= 2;
661 return MMSYSERR_NOERROR
;
663 ERR("This shouldn't happen\n");
664 return MMSYSERR_ERROR
;
667 static DWORD
widStop(WAVEMAPDATA
* wim
)
669 return waveInStop(wim
->hInnerWave
);
672 static DWORD
widStart(WAVEMAPDATA
* wim
)
674 return waveInStart(wim
->hInnerWave
);
677 static DWORD
widReset(WAVEMAPDATA
* wim
)
679 return waveInReset(wim
->hInnerWave
);
682 static DWORD
widMapperStatus(WAVEMAPDATA
* wim
, DWORD flags
, LPVOID ptr
)
685 DWORD ret
= MMSYSERR_NOTSUPPORTED
;
688 case WAVEIN_MAPPER_STATUS_DEVICE
:
689 ret
= waveInGetID(wim
->hInnerWave
, &id
);
692 case WAVEIN_MAPPER_STATUS_MAPPED
:
693 FIXME("Unsupported yet flag=%ld\n", flags
);
694 *(LPDWORD
)ptr
= 0; /* FIXME ?? */
696 case WAVEIN_MAPPER_STATUS_FORMAT
:
697 FIXME("Unsupported flag=%ld\n", flags
);
698 /* ptr points to a WAVEFORMATEX struct - before or after streaming ? */
699 *(LPDWORD
)ptr
= 0; /* FIXME ?? */
702 FIXME("Unsupported flag=%ld\n", flags
);
709 /**************************************************************************
710 * WAVEMAP_widMessage [sample driver]
712 DWORD WINAPI
WAVEMAP_widMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
713 DWORD dwParam1
, DWORD dwParam2
)
715 TRACE("(%u, %04X, %08lX, %08lX, %08lX);\n",
716 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
723 /* FIXME: Pretend this is supported */
726 case WIDM_OPEN
: return widOpen ((LPDWORD
)dwUser
, (LPWAVEOPENDESC
)dwParam1
, dwParam2
);
727 case WIDM_CLOSE
: return widClose ((WAVEMAPDATA
*)dwUser
);
729 case WIDM_ADDBUFFER
: return widAddBuffer ((WAVEMAPDATA
*)dwUser
, (LPWAVEHDR
)dwParam1
, dwParam2
);
730 case WIDM_PREPARE
: return widPrepare ((WAVEMAPDATA
*)dwUser
, (LPWAVEHDR
)dwParam1
, dwParam2
);
731 case WIDM_UNPREPARE
: return widUnprepare ((WAVEMAPDATA
*)dwUser
, (LPWAVEHDR
)dwParam1
, dwParam2
);
732 case WIDM_GETDEVCAPS
: return widGetDevCaps (wDevID
, (WAVEMAPDATA
*)dwUser
, (LPWAVEINCAPSA
)dwParam1
, dwParam2
);
733 case WIDM_GETNUMDEVS
: return 1;
734 case WIDM_GETPOS
: return widGetPosition ((WAVEMAPDATA
*)dwUser
, (LPMMTIME
)dwParam1
, dwParam2
);
735 case WIDM_RESET
: return widReset ((WAVEMAPDATA
*)dwUser
);
736 case WIDM_START
: return widStart ((WAVEMAPDATA
*)dwUser
);
737 case WIDM_STOP
: return widStop ((WAVEMAPDATA
*)dwUser
);
738 case WIDM_MAPPER_STATUS
: return widMapperStatus ((WAVEMAPDATA
*)dwUser
, dwParam1
, (LPVOID
)dwParam2
);
740 FIXME("unknown message %u!\n", wMsg
);
742 return MMSYSERR_NOTSUPPORTED
;
745 /*======================================================================*
747 *======================================================================*/
749 static struct WINE_WAVEMAP
* oss
= NULL
;
751 /**************************************************************************
752 * WAVEMAP_drvOpen [internal]
754 static DWORD
WAVEMAP_drvOpen(LPSTR str
)
759 /* I know, this is ugly, but who cares... */
760 oss
= (struct WINE_WAVEMAP
*)1;
764 /**************************************************************************
765 * WAVEMAP_drvClose [internal]
767 static DWORD
WAVEMAP_drvClose(DWORD dwDevID
)
776 /**************************************************************************
777 * WAVEMAP_DriverProc [internal]
779 LONG CALLBACK
WAVEMAP_DriverProc(DWORD dwDevID
, HDRVR hDriv
, DWORD wMsg
,
780 DWORD dwParam1
, DWORD dwParam2
)
782 TRACE("(%08lX, %04X, %08lX, %08lX, %08lX)\n",
783 dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
786 case DRV_LOAD
: return 1;
787 case DRV_FREE
: return 1;
788 case DRV_OPEN
: return WAVEMAP_drvOpen((LPSTR
)dwParam1
);
789 case DRV_CLOSE
: return WAVEMAP_drvClose(dwDevID
);
790 case DRV_ENABLE
: return 1;
791 case DRV_DISABLE
: return 1;
792 case DRV_QUERYCONFIGURE
: return 1;
793 case DRV_CONFIGURE
: MessageBoxA(0, "WAVEMAP MultiMedia Driver !", "OSS Driver", MB_OK
); return 1;
794 case DRV_INSTALL
: return DRVCNF_RESTART
;
795 case DRV_REMOVE
: return DRVCNF_RESTART
;
797 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);