Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

456 lines
10 KiB

//==========================================================================;
//
// wavein.c
//
// Copyright (c) 1992-1998 Microsoft Corporation
//
// Description:
//
//
// History:
// 9/18/93 cjp [curtisp]
//
//==========================================================================;
#include <windows.h>
#include <windowsx.h>
#include <mmsystem.h>
#include <mmddk.h>
#include <mmreg.h>
#include <msacm.h>
#include <msacmdrv.h>
#include <memory.h>
#ifdef DEBUG
#include <stdlib.h>
#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()