Re: [PATCH] Add Callback for wavemapper -> widOpen
"James Hatheway" <james(a)macadamian.com> writes:
I implemented the callback in a very similar way as the Wave out callback is implemented. You can see this in the functions wodOpen(), wodOpenHelper(), and WAVEMAP_DstCallback() , look at the data passed in the wom structure (in dlls/winmm/wavemap/wavemap.c). I don't see any other way that I will be able to callback into the app when the WineOSS layer notifies the wavemap layer. The way it is now (wineoss directly calling the app) causes my app to crash, and doesn't work that way on waveout.
But these other functions are not using the WINE_MLD internal winmm structure, so why do you need it in widOpen()? Couldn't you instead do exactly what wodOpen() does? -- Alexandre Julliard julliard(a)winehq.com
But these other functions are not using the WINE_MLD internal winmm structure, so why do you need it in widOpen()? Couldn't you instead do exactly what wodOpen() does?
Hi Alexandre, Ok, I see what you are saying now. Sorry about that. Humm.. I guess the short answer is because it doesn't work if I do it the same way wodOpen does. :-) I'll look into this and send another patch when I have a bit of time (maybe today or on Monday), it appears that it is breaking in MMDRV_WaveIn_Callback, but I'm not 100% sure yet... -James -- James Hatheway Software Designer - Macadamian Technologies, Inc. james(a)macadamian.com ~ http://www.macadamian.com "Man könnte froh sein, wenn die Luft so rein wäre wie das Bier" "One could be happy if the air were as pure as the beer"
James Hatheway wrote:
But these other functions are not using the WINE_MLD internal winmm structure, so why do you need it in widOpen()? Couldn't you instead do exactly what wodOpen() does?
Hi Alexandre,
Ok, I see what you are saying now. Sorry about that. Humm.. I guess the short answer is because it doesn't work if I do it the same way wodOpen does. :-) I'll look into this and send another patch when I have a bit of time (maybe today or on Monday), it appears that it is breaking in MMDRV_WaveIn_Callback, but I'm not 100% sure yet...
well, the waveOut case is broken when no ACM conversion is required (only mapping to an available device). it uses the wrong waveOut handle (which seems to crash your app). I'll try to whip out something this week-end A+ -- --------------- Eric Pouech (http://perso.wanadoo.fr/eric.pouech/) "The future will be better tomorrow", Vice President Dan Quayle
well, the waveOut case is broken when no ACM conversion is required (only mapping to an available device). it uses the wrong waveOut handle (which seems to crash your app). I'll try to whip out something this week-end
Hi Eric, Thanks. I've been caught up with some other bugs lately that I didn't have the chance to come back to this issue yet. -James -- James Hatheway Software Designer - Macadamian Technologies, Inc. james(a)macadamian.com ~ http://www.macadamian.com "Man könnte froh sein, wenn die Luft so rein wäre wie das Bier" "One could be happy if the air were as pure as the beer"
James Hatheway wrote:
well, the waveOut case is broken when no ACM conversion is required (only mapping to an available device). it uses the wrong waveOut handle (which seems to crash your app). I'll try to whip out something this week-end
Hi Eric,
Thanks. I've been caught up with some other bugs lately that I didn't have the chance to come back to this issue yet.
does the attached patch solve your issue ? A+ -- --------------- Eric Pouech (http://perso.wanadoo.fr/eric.pouech/) "The future will be better tomorrow", Vice President Dan Quayle Name: wavemap ChangeLog: fixed callback parameters (bogus hWave) GenDate: 2001/04/07 15:46:26 UTC ModifiedFiles: dlls/winmm/wavemap/wavemap.c AddedFiles: =================================================================== RCS file: /usr/share/cvs/cvsroot/wine/wine/dlls/winmm/wavemap/wavemap.c,v retrieving revision 1.11 diff -u -u -r1.11 wavemap.c --- dlls/winmm/wavemap/wavemap.c 2001/01/26 20:43:45 1.11 +++ dlls/winmm/wavemap/wavemap.c 2001/04/07 13:33:24 @@ -2,13 +2,14 @@ /* * Wine Wave mapper driver * - * Copyright 1999 Eric Pouech + * Copyright 1999,2001 Eric Pouech */ /* TODOs * + implement wavein as waveout has been implemented * + better protection against evilish dwUser parameters * + use asynchronous ACM conversion + * + don't use callback functions when none is required in open */ #include <string.h> @@ -24,7 +25,8 @@ typedef struct tagWAVEMAPDATA { struct tagWAVEMAPDATA* self; - HWAVE hWave; + HWAVE hOuterWave; + HWAVE hInnerWave; HACMSTREAM hAcmStream; /* needed data to filter callbacks. Only needed when hAcmStream is not 0 */ DWORD dwCallback; @@ -38,23 +40,28 @@ } /*======================================================================* - * WAVE OUT part * + * Notification * *======================================================================*/ -static void CALLBACK WAVEMAP_DstCallback(HDRVR hDev, UINT uMsg, DWORD dwInstance, +static void CALLBACK WAVEMAP_DstCallback(HWAVE hWave, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2) { - WAVEMAPDATA* wom = (WAVEMAPDATA*)dwInstance; + WAVEMAPDATA* wmd = (WAVEMAPDATA*)dwInstance; - TRACE("(0x%x %u %ld %lx %lx);\n", hDev, uMsg, dwInstance, dwParam1, dwParam2); + TRACE("(0x%x %u %ld %lx %lx);\n", hWave, uMsg, dwInstance, dwParam1, dwParam2); + if (hWave != wmd->hInnerWave && uMsg != WOM_OPEN && uMsg != WIM_OPEN) + ERR("Shouldn't happen (%08x %08x)\n", hWave, wmd->hInnerWave); switch (uMsg) { case WOM_OPEN: case WOM_CLOSE: + case WIM_OPEN: + case WIM_CLOSE: /* dwParam1 & dwParam2 are supposed to be 0, nothing to do */ break; case WOM_DONE: - { + case WIM_DATA: + if (wmd->hAcmStream) { LPWAVEHDR lpWaveHdrDst = (LPWAVEHDR)dwParam1; PACMSTREAMHEADER ash = (PACMSTREAMHEADER)((LPSTR)lpWaveHdrDst - sizeof(ACMSTREAMHEADER)); LPWAVEHDR lpWaveHdrSrc = (LPWAVEHDR)ash->dwUser; @@ -68,10 +75,14 @@ ERR("Unknown msg %u\n", uMsg); } - DriverCallback(wom->dwCallback, HIWORD(wom->dwFlags), hDev, uMsg, - wom->dwClientInstance, dwParam1, dwParam2); + DriverCallback(wmd->dwCallback, HIWORD(wmd->dwFlags), wmd->hOuterWave, uMsg, + wmd->dwClientInstance, dwParam1, dwParam2); } +/*======================================================================* + * WAVE OUT part * + *======================================================================*/ + static DWORD wodOpenHelper(WAVEMAPDATA* wom, UINT idx, LPWAVEOPENDESC lpDesc, LPWAVEFORMATEX lpwfx, DWORD dwFlags) @@ -85,7 +96,7 @@ (dwFlags & WAVE_FORMAT_QUERY) ? ACM_STREAMOPENF_QUERY : 0L); if (ret != MMSYSERR_NOERROR) return ret; - return waveOutOpen(&wom->hWave, idx, lpwfx, (DWORD)WAVEMAP_DstCallback, + return waveOutOpen(&wom->hInnerWave, idx, lpwfx, (DWORD)WAVEMAP_DstCallback, (DWORD)wom, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION); } @@ -102,13 +113,17 @@ return MMSYSERR_NOMEM; wom->self = wom; + wom->dwCallback = lpDesc->dwCallback; + wom->dwFlags = dwFlags; + wom->dwClientInstance = lpDesc->dwInstance; + wom->hOuterWave = lpDesc->hWave; for (i = 0; i < nd; i++) { /* if no ACM stuff is involved, no need to handle callbacks at this * level, this will be done transparently */ - if (waveOutOpen(&wom->hWave, i, lpDesc->lpFormat, lpDesc->dwCallback, - lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) { + if (waveOutOpen(&wom->hInnerWave, i, lpDesc->lpFormat, (DWORD)WAVEMAP_DstCallback, + (DWORD)wom, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION) == MMSYSERR_NOERROR) { wom->hAcmStream = 0; goto found; } @@ -118,10 +133,6 @@ wfx.cbSize = 0; /* normally, this field is not used for PCM format, just in case */ /* try some ACM stuff */ - wom->dwCallback = lpDesc->dwCallback; - wom->dwFlags = dwFlags; - wom->dwClientInstance = lpDesc->dwInstance; - #define TRY(sps,bps) wfx.nSamplesPerSec = (sps); wfx.wBitsPerSample = (bps); \ if (wodOpenHelper(wom, i, lpDesc, &wfx, dwFlags) == MMSYSERR_NOERROR) goto found; @@ -144,11 +155,9 @@ return MMSYSERR_ALLOCATED; found: if (dwFlags & WAVE_FORMAT_QUERY) { - lpDesc->hWave = 0; *lpdwUser = 0L; HeapFree(GetProcessHeap(), 0, wom); } else { - lpDesc->hWave = wom->hWave; *lpdwUser = (DWORD)wom; } return MMSYSERR_NOERROR; @@ -156,7 +165,7 @@ static DWORD wodClose(WAVEMAPDATA* wom) { - DWORD ret = waveOutClose(wom->hWave); + DWORD ret = waveOutClose(wom->hInnerWave); if (ret == MMSYSERR_NOERROR) { if (wom->hAcmStream) { @@ -175,7 +184,7 @@ LPWAVEHDR lpWaveHdrDst; if (!wom->hAcmStream) { - return waveOutWrite(wom->hWave, lpWaveHdrSrc, dwParam2); + return waveOutWrite(wom->hInnerWave, lpWaveHdrSrc, dwParam2); } lpWaveHdrSrc->dwFlags |= WHDR_INQUEUE; @@ -185,7 +194,7 @@ lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER)); lpWaveHdrDst->dwBufferLength = ash->cbDstLengthUsed; - return waveOutWrite(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); + return waveOutWrite(wom->hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); } static DWORD wodPrepare(WAVEMAPDATA* wom, LPWAVEHDR lpWaveHdrSrc, DWORD dwParam2) @@ -196,7 +205,7 @@ LPWAVEHDR lpWaveHdrDst; if (!wom->hAcmStream) { - return waveOutPrepareHeader(wom->hWave, lpWaveHdrSrc, dwParam2); + return waveOutPrepareHeader(wom->hInnerWave, lpWaveHdrSrc, dwParam2); } if (acmStreamSize(wom->hAcmStream, lpWaveHdrSrc->dwBufferLength, &size, ACM_STREAMSIZEF_SOURCE) != MMSYSERR_NOERROR) return MMSYSERR_ERROR; @@ -225,7 +234,7 @@ lpWaveHdrDst->dwBufferLength = size; /* conversion is not done yet */ lpWaveHdrDst->dwFlags = 0; lpWaveHdrDst->dwLoops = 0; - dwRet = waveOutPrepareHeader(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); + dwRet = waveOutPrepareHeader(wom->hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); if (dwRet != MMSYSERR_NOERROR) goto errCleanUp; @@ -246,13 +255,13 @@ DWORD dwRet1, dwRet2; if (!wom->hAcmStream) { - return waveOutUnprepareHeader(wom->hWave, lpWaveHdrSrc, dwParam2); + return waveOutUnprepareHeader(wom->hInnerWave, lpWaveHdrSrc, dwParam2); } ash = (PACMSTREAMHEADER)lpWaveHdrSrc->reserved; dwRet1 = acmStreamUnprepareHeader(wom->hAcmStream, ash, 0L); lpWaveHdrDst = (LPWAVEHDR)((LPSTR)ash + sizeof(ACMSTREAMHEADER)); - dwRet2 = waveOutUnprepareHeader(wom->hWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); + dwRet2 = waveOutUnprepareHeader(wom->hInnerWave, lpWaveHdrDst, sizeof(*lpWaveHdrDst)); HeapFree(GetProcessHeap(), 0, ash); @@ -262,14 +271,14 @@ static DWORD wodGetPosition(WAVEMAPDATA* wom, LPMMTIME lpTime, DWORD dwParam2) { - return waveOutGetPosition(wom->hWave, lpTime, dwParam2); + return waveOutGetPosition(wom->hInnerWave, lpTime, dwParam2); } static DWORD wodGetDevCaps(UINT wDevID, WAVEMAPDATA* wom, LPWAVEOUTCAPSA lpWaveCaps, DWORD dwParam2) { /* if opened low driver, forward message */ if (WAVEMAP_IsData(wom)) - return waveOutGetDevCapsA(wom->hWave, lpWaveCaps, dwParam2); + return waveOutGetDevCapsA(wom->hInnerWave, lpWaveCaps, dwParam2); /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { lpWaveCaps->wMid = 0x00FF; @@ -292,35 +301,35 @@ static DWORD wodGetVolume(UINT wDevID, WAVEMAPDATA* wom, LPDWORD lpVol) { if (WAVEMAP_IsData(wom)) - return waveOutGetVolume(wom->hWave, lpVol); + return waveOutGetVolume(wom->hInnerWave, lpVol); return MMSYSERR_NOERROR; } static DWORD wodSetVolume(UINT wDevID, WAVEMAPDATA* wom, DWORD vol) { if (WAVEMAP_IsData(wom)) - return waveOutSetVolume(wom->hWave, vol); + return waveOutSetVolume(wom->hInnerWave, vol); return MMSYSERR_NOERROR; } static DWORD wodPause(WAVEMAPDATA* wom) { - return waveOutPause(wom->hWave); + return waveOutPause(wom->hInnerWave); } static DWORD wodRestart(WAVEMAPDATA* wom) { - return waveOutRestart(wom->hWave); + return waveOutRestart(wom->hInnerWave); } static DWORD wodReset(WAVEMAPDATA* wom) { - return waveOutReset(wom->hWave); + return waveOutReset(wom->hInnerWave); } static DWORD wodBreakLoop(WAVEMAPDATA* wom) { - return waveOutBreakLoop(wom->hWave); + return waveOutBreakLoop(wom->hInnerWave); } static DWORD wodMapperStatus(WAVEMAPDATA* wom, DWORD flags, LPVOID ptr) @@ -330,7 +339,7 @@ switch (flags) { case WAVEOUT_MAPPER_STATUS_DEVICE: - ret = waveOutGetID(wom->hWave, &id); + ret = waveOutGetID(wom->hInnerWave, &id); *(LPDWORD)ptr = id; break; case WAVEOUT_MAPPER_STATUS_MAPPED: @@ -404,12 +413,16 @@ TRACE("(%p %p %08lx\n", lpdwUser, lpDesc, dwFlags); wim->self = wim; - + wim->dwCallback = lpDesc->dwCallback; + wim->dwFlags = dwFlags; + wim->dwClientInstance = lpDesc->dwInstance; + wim->hOuterWave = lpDesc->hWave; + for (i = 0; i < nd; i++) { - if (waveInOpen(&wim->hWave, i, lpDesc->lpFormat, lpDesc->dwCallback, - lpDesc->dwInstance, dwFlags) == MMSYSERR_NOERROR) { - lpDesc->hWave = wim->hWave; + if (waveInOpen(&wim->hInnerWave, i, lpDesc->lpFormat, (DWORD)WAVEMAP_DstCallback, + (DWORD)wim, (dwFlags & ~CALLBACK_TYPEMASK) | CALLBACK_FUNCTION) == MMSYSERR_NOERROR) { *lpdwUser = (DWORD)wim; + wim->hAcmStream = 0; return MMSYSERR_NOERROR; } } @@ -419,7 +432,7 @@ static DWORD widClose(WAVEMAPDATA* wim) { - DWORD ret = waveInClose(wim->hWave); + DWORD ret = waveInClose(wim->hInnerWave); if (ret == MMSYSERR_NOERROR) HeapFree(GetProcessHeap(), 0, wim); return ret; @@ -427,29 +440,29 @@ static DWORD widAddBuffer(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2) { - return waveInAddBuffer(wim->hWave, lpWaveHdr, dwParam2); + return waveInAddBuffer(wim->hInnerWave, lpWaveHdr, dwParam2); } static DWORD widPrepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2) { - return waveInPrepareHeader(wim->hWave, lpWaveHdr, dwParam2); + return waveInPrepareHeader(wim->hInnerWave, lpWaveHdr, dwParam2); } static DWORD widUnprepare(WAVEMAPDATA* wim, LPWAVEHDR lpWaveHdr, DWORD dwParam2) { - return waveInUnprepareHeader(wim->hWave, lpWaveHdr, dwParam2); + return waveInUnprepareHeader(wim->hInnerWave, lpWaveHdr, dwParam2); } static DWORD widGetPosition(WAVEMAPDATA* wim, LPMMTIME lpTime, DWORD dwParam2) { - return waveInGetPosition(wim->hWave, lpTime, dwParam2); + return waveInGetPosition(wim->hInnerWave, lpTime, dwParam2); } static DWORD widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSA lpWaveCaps, DWORD dwParam2) { /* if opened low driver, forward message */ if (WAVEMAP_IsData(wim)) - return waveInGetDevCapsA(wim->hWave, lpWaveCaps, dwParam2); + return waveInGetDevCapsA(wim->hInnerWave, lpWaveCaps, dwParam2); /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { lpWaveCaps->wMid = 0x00FF; @@ -469,17 +482,17 @@ static DWORD widStop(WAVEMAPDATA* wim) { - return waveInStop(wim->hWave); + return waveInStop(wim->hInnerWave); } static DWORD widStart(WAVEMAPDATA* wim) { - return waveInStart(wim->hWave); + return waveInStart(wim->hInnerWave); } static DWORD widReset(WAVEMAPDATA* wim) { - return waveInReset(wim->hWave); + return waveInReset(wim->hInnerWave); } static DWORD widMapperStatus(WAVEMAPDATA* wim, DWORD flags, LPVOID ptr) @@ -489,7 +502,7 @@ switch (flags) { case WAVEIN_MAPPER_STATUS_DEVICE: - ret = waveInGetID(wim->hWave, &id); + ret = waveInGetID(wim->hInnerWave, &id); *(LPDWORD)ptr = id; break; case WAVEIN_MAPPER_STATUS_MAPPED:
James Hatheway wrote:
well, the waveOut case is broken when no ACM conversion is required (only mapping to an available device). it uses the wrong waveOut handle (which seems to crash your app). I'll try to whip out something this week-end
Hi Eric,
Thanks. I've been caught up with some other bugs lately that I didn't have the chance to come back to this issue yet.
does the attached patch solve your issue ?
Hi Eric, after a quick test it does seem to solve my problem. I'll let you know if I encounter any problems. Thanks, -James -- James Hatheway Software Designer - Macadamian Technologies, Inc. james(a)macadamian.com ~ http://www.macadamian.com "Man könnte froh sein, wenn die Luft so rein wäre wie das Bier" "One could be happy if the air were as pure as the beer"
participants (3)
-
Alexandre Julliard -
eric pouech -
James Hatheway