//==========================================================================; // // wavein.c // // Copyright (c) 1992-1998 Microsoft Corporation // // Description: // // // History: // 9/18/93 cjp [curtisp] // //==========================================================================; #include #include #include #include #include #include #include #include #ifdef DEBUG #include #endif #include "msacmmap.h" #include "debug.h" //--------------------------------------------------------------------------; // // LRESULT mapWaveInputConvertProc // // Description: // Window Proc for hidden window... // // It should just recieve WIM_DATA messages from mapWaveDriverCallback // // Real driver has filled the shadow buffer // Now convert it and call back the app/client. // // Arguments: // DWORD dwInstance: // // Return (LONG): // // History: // 11/15/92 gpd [geoffd] // 08/02/93 cjp [curtisp] rewrote for new mapper // //--------------------------------------------------------------------------; EXTERN_C LRESULT FNCALLBACK mapWaveInputConvertProc ( DWORD dwInstance ) { MMRESULT mmr; MSG msg; LPACMSTREAMHEADER pash; LPWAVEHDR pwh; LPWAVEHDR pwhShadow; LPMAPSTREAM pms; #ifndef WIN32 DPF(1, "mapWaveInputConvertProc: creating htask=%.04Xh, dwInstance=%.08lXh", gpag->htaskInput, dwInstance); #endif // !WIN32 if (!SetMessageQueue(64)) { DPF(0, "!mapWaveInputConvertProc: SetMessageQueue() failed!"); return (0L); } #ifdef WIN32 // // Make sure we have a message queue for this thread and signal the // caller when we're ready to go // GetDesktopWindow(); // Makes sure we've got a message queue SetEvent(LongToHandle(dwInstance)); #endif // // // while (GetMessage(&msg, NULL, 0, 0)) { #ifdef DEBUG if (gpag->fFaultAndDie) { if ((rand() & 0x7) == 0) { gpag->fFaultAndDie = (BOOL)*((LPBYTE)0); DPF(1, "mapWaveInputConvertProc: fault was ignored..."); gpag->fFaultAndDie = TRUE; } } #endif // // if not a 'data' message, then translate and dispatch it... // if (msg.message != WIM_DATA) { DPF(1, "mapWaveInputConvertProc: ignoring message [%.04Xh]", msg.message); TranslateMessage(&msg); DispatchMessage(&msg); continue; } // // lParam is the waveheader of the shadow buffer // pwhShadow = (LPWAVEHDR)msg.lParam; // // client wave header is user data of shadow wave header // the stream header for this client/shadow pair is in the client's // 'reserved' member // // and finally, our stream header's dwUser member contains a // reference to our mapping stream instance data. // pwh = (LPWAVEHDR)pwhShadow->dwUser; pash = (LPACMSTREAMHEADER)pwh->reserved; pms = (LPMAPSTREAM)pash->dwUser; DPF(4, "mapWaveInputConvertProc: WIM_DATA htask=%.04Xh, pms=%.08lXh, pwh=%.08lXh, pwhShadow=%.08lXh", pms->htaskInput, pms, pwh, pwhShadow); // // do the conversion (if there is data in the input buffer) // pash->cbDstLengthUsed = 0L; if (0L != pwhShadow->dwBytesRecorded) { pash->pbSrc = pwhShadow->lpData; pash->cbSrcLength = pwhShadow->dwBytesRecorded; pash->pbDst = pwh->lpData; ////////////pash->cbDstLength = pwh->dwBufferLength; mmr = acmStreamConvert(pms->has, pash, ACM_STREAMCONVERTF_BLOCKALIGN); if (MMSYSERR_NOERROR != mmr) { DPF(0, "!mapWaveInputConvertProc: conversion failed! mmr=%.04Xh, pms=%.08lXh", mmr, pms); pash->cbDstLengthUsed = 0L; } else if (pash->cbSrcLength != pash->cbSrcLengthUsed) { DPF(1, "mapWaveInputConvertProc: discarding %lu bytes of input! pms=%.08lXh", pash->cbSrcLength - pash->cbSrcLengthUsed, pms); } } if (0L == pash->cbDstLengthUsed) { DPF(1, "mapWaveInputConvertProc: nothing converted--no data in input buffer. pms=%.08lXh", pms); } // // update the 'real' header and send the WIM_DATA callback // // pwh->dwBytesRecorded = pash->cbDstLengthUsed; pwh->dwFlags |= WHDR_DONE; pwh->dwFlags &= ~WHDR_INQUEUE; mapWaveDriverCallback(pms, WIM_DATA, (DWORD_PTR)pwh, 0L); #ifdef WIN32 if (InterlockedDecrement((PLONG)&pms->nOutstanding) == 0) { SetEvent(pms->hStoppedEvent); } #endif // WIN32 } #ifndef WIN32 DPF(1, "mapWaveInputConvertProc: being KILLED htask=%.04Xh", gpag->htaskInput); #endif // !WIN32 return (0L); } // mapWaveInputConvertProc() //--------------------------------------------------------------------------; // // DWORD widmMapperStatus // // Description: // // // Arguments: // LPMAPSTREAM pms: // // DWORD dwStatus: // // LPDWORD pdw: // // Return (DWORD): // // History: // 08/13/93 cjp [curtisp] // //--------------------------------------------------------------------------; DWORD FNLOCAL widmMapperStatus ( LPMAPSTREAM pms, DWORD dwStatus, LPDWORD pdw ) { MMRESULT mmr; // V_WPOINTER(pdw, sizeof(DWORD), MMSYSERR_INVALPARAM); if ((NULL == pms) || (NULL == pdw)) { return (MMSYSERR_INVALPARAM); } // // // switch (dwStatus) { case WAVEIN_MAPPER_STATUS_DEVICE: { UINT uId = (UINT)(-1); // Invalid value mmr = waveInGetID(pms->hwiReal, &uId); if (MMSYSERR_NOERROR != mmr) { return (mmr); } *pdw = uId; return (MMSYSERR_NOERROR); } case WAVEIN_MAPPER_STATUS_MAPPED: *pdw = (NULL != pms->has); return (MMSYSERR_NOERROR); case WAVEIN_MAPPER_STATUS_FORMAT: if (NULL != pms->has) _fmemcpy(pdw, pms->pwfxReal, sizeof(PCMWAVEFORMAT)); else _fmemcpy(pdw, pms->pwfxClient, sizeof(PCMWAVEFORMAT)); ((LPWAVEFORMATEX)pdw)->cbSize = 0; return (MMSYSERR_NOERROR); } // // // return (MMSYSERR_NOTSUPPORTED); } // widmMapperStatus() //--------------------------------------------------------------------------; // // DWORD widMessage // // Description: // This function conforms to the standard Wave Input driver message // procedure (widMessage), which is documented in mmddk.d. // // Arguments: // UINT uId: // // UINT uMsg: // // DWORD dwUser: // // DWORD dwParam1: // // DWORD dwParam2: // // Return (DWORD): // // // History: // 11/15/92 cjp [curtisp] // //--------------------------------------------------------------------------; EXTERN_C DWORD FNEXPORT widMessage ( UINT uId, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dwParam1, DWORD_PTR dwParam2 ) { #ifndef WIN32 // Doesn't work for multithread static short fSem = 0; #endif // !WIN32 LPMAPSTREAM pms; // pointer to per-instance info structure DWORD dw; if (!gpag->fEnabled) { DPF(1, "widMessage: called while disabled!"); return ((WIDM_GETNUMDEVS == uMsg) ? 0L : MMSYSERR_NOTENABLED); } #ifndef WIN32 // // we call back into the mmsystem wave APIs so protect ourself // from being re-entered! // if (fSem) { DPF(0, "!widMessage(uMsg=%u, dwUser=%.08lXh) being reentered! fSem=%d", uMsg, dwUser, fSem); // return (MMSYSERR_NOTSUPPORTED); } #endif // !WIN32 pms = (LPMAPSTREAM)dwUser; switch (uMsg) { case WIDM_GETNUMDEVS: return (1L); case WIDM_GETDEVCAPS: return mapWaveGetDevCaps(TRUE, (LPWAVEOUTCAPS)dwParam1, (UINT)dwParam2); case WIDM_OPEN: #ifndef WIN32 fSem++; DPF(1, "**** >> WIDM_OPEN(uMsg=%u, dwUser=%.08lXh, fSem=%d)", uMsg, dwUser, fSem); #endif // !WIN32 // // dwParam1 contains a pointer to a WAVEOPENDESC // dwParam2 contains wave driver specific flags in the LOWORD // and generic driver flags in the HIWORD // dw = mapWaveOpen(TRUE, uId, dwUser, (LPWAVEOPENDESC)dwParam1, (DWORD)(PtrToLong((PVOID)dwParam2)) ); #ifndef WIN32 fSem--; DPF(1, "**** << WIDM_OPEN(uMsg=%u, dwUser=%.08lXh, *dwUser=%.08lXh, fSem=%d)", uMsg, dwUser, *(LPDWORD)dwUser, fSem); #endif // !WIN32 return (dw); case WIDM_CLOSE: return (mapWaveClose(pms)); case WIDM_PREPARE: return (mapWavePrepareHeader(pms, (LPWAVEHDR)dwParam1)); case WIDM_UNPREPARE: return (mapWaveUnprepareHeader(pms, (LPWAVEHDR)dwParam1)); case WIDM_ADDBUFFER: return (mapWaveWriteBuffer(pms, (LPWAVEHDR)dwParam1)); case WIDM_START: DPF(4, "WIDM_START received..."); return waveInStart(pms->hwiReal); case WIDM_STOP: DPF(4, "WIDM_STOP received.."); dw = waveInStop(pms->hwiReal); #pragma message("----try to kill DirectedYield..") // // yield enough to get all input messages processed // if (pms->htaskInput) { #ifdef WIN32 ResetEvent(pms->hStoppedEvent); if (pms->nOutstanding != 0) { WaitForSingleObject(pms->hStoppedEvent, INFINITE); } #else if (IsTask(pms->htaskInput)) { DirectedYield(pms->htaskInput); } else { DPF(0, "!WIDM_STOP: pms=%.08lXh, htask=%.04Xh is not valid!", pms, pms->htaskInput); pms->htaskInput = NULL; } #endif // !WIN32 } return (dw); case WIDM_RESET: DPF(4, "WIDM_RESET received..."); dw = waveInReset(pms->hwiReal); // // yield enough to get all input messages processed // if (pms->htaskInput) { #ifdef WIN32 ResetEvent(pms->hStoppedEvent); if (pms->nOutstanding != 0) { WaitForSingleObject(pms->hStoppedEvent, INFINITE); } #else if (IsTask(pms->htaskInput)) { DirectedYield(pms->htaskInput); } else { DPF(0, "!WIDM_RESET: pms=%.08lXh, htask=%.04Xh is not valid!", pms, pms->htaskInput); pms->htaskInput = NULL; } #endif // !WIN32 } return (dw); case WIDM_GETPOS: return mapWaveGetPosition(pms, (LPMMTIME)dwParam1, (UINT)dwParam2); case WIDM_MAPPER_STATUS: dw = widmMapperStatus(pms, (DWORD)(PtrToLong((PVOID)dwParam1)), (LPDWORD)dwParam2); return (dw); #if (WINVER >= 0x0400) case DRVM_MAPPER_RECONFIGURE: mapDriverDisable(NULL); mapDriverEnable(NULL); return (0); #endif } if (!pms || !pms->hwiReal) return (MMSYSERR_NOTSUPPORTED); return waveInMessage(pms->hwiReal, uMsg, dwParam1, dwParam2); } // widMessage()