📄 mixfunc.cpp
字号:
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Copyright (c) 1999 Microsoft Corporation
Module Name:
mixfunc.c
Abstract:
Environment:
Notes:
Revision History:
5/20/1999
-------------------------------------------------------------------*/
#include "includes.h"
#include <mmddk.h>
#include "globals.h"
#include "mixdrv.h"
#include "mixfunc.h"
#include "mmreg.h"
#include "mixhw.h"
static void CopyControlStruct(PMIXERCONTROL pMixerControl, int iIndex);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_GETNUMDEVS
Description:
Returns the number of supported instances for the driver
(1, that is each app can open only one instance). Not that we check for that,
i.e, an app could still open multiple instances, but it shouldn't
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD dwUser : returned by the app (not used)
DWORD dwParam1 :
DWORD dwParam2 :
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_GETNUMDEVS(PMIXER_CONTEXT pMixer, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
return MAX_SUPPORTED_INSTANCES; // the driver only supports one device instance at the moment
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_OPEN
Description:
Opens a mixer handle; i.e., initializes the stored values in the MIXER_CONTEXT structure that
describes the mixer with the values sent by the application
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD *pdwUser : given us by the app for storage; we don't use it at this time
DWORD dwParam1 : pointer to a MIXEROPENDESC structure, describing parameters
DWORD dwParam2 : not used
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_OPEN(PMIXER_CONTEXT pMixer, DWORD *pdwUser, DWORD dwParam1, DWORD dwParam2)
{
MIXEROPENDESC *pMixDesc = (MIXEROPENDESC *) MapPtrToProcess((PVOID)dwParam1, GetCallerProcess());
ASSERT(pMixer && pdwUser);
if (!pMixDesc)
{
SetLastError(ERROR_INVALID_PARAMETER);
return MMSYSERR_INVALPARAM;
}
pMixer->dwInstance = pMixDesc->dwInstance;
pMixer->hProcess = GetCallerProcess();
pMixer->pfnMixerCallback = (PDRVCALLBACK)pMixDesc->dwCallback;
*pdwUser = 0; // not really used
return MMSYSERR_NOERROR;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_GETDEVCAPS
Description:
Gets the device capabilities
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD dwUser : returned by the app (not used)
DWORD dwParam1 : pointer to a MIXERCAPS struct where the info is returned
DWORD dwParam2 :
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_GETDEVCAPS(PMIXER_CONTEXT pMixer, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
PMIXERCAPS pMixCaps = (PMIXERCAPS) MapPtrToProcess((PMIXERCAPS) dwParam1, GetCallerProcess());
ASSERT(pMixer);
if (!pMixCaps)
{
SetLastError(ERROR_INVALID_PARAMETER);
return MMSYSERR_INVALPARAM;
}
// set mixer capabilites
pMixCaps->wMid = DRIVER_WMID;
pMixCaps->wPid = MM_MSFT_WDMAUDIO_MIXER;
pMixCaps->fdwSupport = 0;
pMixCaps->cDestinations = DESTINATION_LINES_COUNT;
pMixCaps->vDriverVersion = DRIVER_VERSION; // version 1.1
_tcsncpy(pMixCaps->szPname, MIXERDRIVER_NAME, MAXPNAMELEN);
pMixCaps->szPname[MAXPNAMELEN - 1] = 0;
return MMSYSERR_NOERROR;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_CLOSE
Description:
handles a mixerClose call from mixapi.lib. It does not deallocate the mixer context; that happens
in MIX_Close, which is called when the calling app calls CloseHandle on the handle returned by
CreateFile("MIX1:",...)
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD dwUser : returned by the app (not used)
DWORD dwParam1 : not used
DWORD dwParam2 : not used
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_CLOSE(PMIXER_CONTEXT pMixer, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
ASSERT(pMixer);
pMixer->dwInstance = 0;
//pMixer->hMixer = NULL;
pMixer->pfnMixerCallback = NULL;
return MMSYSERR_NOERROR;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_GETLINEINFO
Description:
Gets info about a mixer line
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD dwUser : returned by the app (not used)
DWORD dwParam1 : pointer to a MIXERLINE struct that gets filled with the line info
DWORD dwParam2 : flags that describe the info requested
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_GETLINEINFO(PMIXER_CONTEXT pMixer, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
MIXER_LINES mxLine;
LPMIXERLINE pTempLine;
LPMIXERLINE pLine = (LPMIXERLINE) MapPtrToProcess((PVOID)dwParam1, GetCallerProcess());
ASSERT(pMixer);
if (!pLine)
{
MIXERRMSG("Bad pLine in mix_handle_GETLINEINFO");
goto badparms;
}
if (pLine->cbStruct < sizeof(MIXERLINE) )
{
MIXERRMSG("Bad pLine cbStruct in mix_handle_GETLINEINFO");
goto badparms;
}
// what line does the user want info about?
switch (dwParam2 & MIXER_GETLINEINFOF_QUERYMASK)
{
case MIXER_GETLINEINFOF_DESTINATION:
// the caller wants info about a destination line
if (pLine->dwSource != 0|| pLine->dwDestination >= DESTINATION_LINES_COUNT)
// be paranoid; the docs say dwSource must needs be 0 in this case
{
MIXERRMSG("Bad pLine line in mix_handle_GETLINEINFO");
goto badparms;
}
mxLine = (MIXER_LINES) pLine->dwDestination;
// fill in info
break;
case MIXER_GETLINEINFOF_SOURCE:
// the user wants info about a source line (the one that's associated to destination line pLine->dwDestination
{
pTempLine = FindMixerLine(pLine->dwDestination);
if (!pTempLine)
{
MIXERRMSG1("Unknown line ID in mix_handle_GETLINEINFO: %d", pLine->dwDestination);
goto badparms;
}
if (pLine->dwSource >= pTempLine->cConnections)
{
MIXERRMSG2("Bad pLine dwSource (%d) in mix_handle_GETLINEINFO (max %d)",
pLine->dwSource, pTempLine->cConnections);
goto badparms;
}
mxLine = g_Connections[pLine->dwDestination][pLine->dwSource];
// fill in the info
}
break;
case MIXER_GETLINEINFOF_LINEID:
if (pLine->dwLineID >= LINES_COUNT)
{
MIXERRMSG("Bad pLine dwLineID in mix_handle_GETLINEINFO");
goto badparms;
}
mxLine = (MIXER_LINES) pLine->dwLineID;
break;
case MIXER_GETLINEINFOF_COMPONENTTYPE:
{
// search the first line that supports the type of component requested
int i;
mxLine = NO_CONNECTION;
for (i = 0; i < LINES_COUNT; i++)
{
pTempLine = FindMixerLine(i);
if (!pTempLine)
continue;
if (pTempLine->dwComponentType == pLine->dwComponentType)
{
mxLine = (MIXER_LINES) i;
break;
}
}
if (mxLine == NO_CONNECTION)
{
return MIXERR_INVALLINE;
}
}
break;
case MIXER_GETLINEINFOF_TARGETTYPE:
{
// search the first line that supports the type of component requested
int i;
mxLine = NO_CONNECTION;
for (i = 0; i < LINES_COUNT; i++)
{
pTempLine = FindMixerLine(i);
if (!pTempLine)
continue;
if (pTempLine->Target.dwType == pLine->dwComponentType)
{
mxLine = (MIXER_LINES) i;
break;
}
}
if (mxLine == NO_CONNECTION)
{
return MIXERR_INVALLINE;
}
}
break;
default:
MIXERRMSG1("Unknown param in mix_handle_GETLINEINFO: %d", dwParam2);
return MMSYSERR_NOTSUPPORTED;
}
pTempLine = FindMixerLine(mxLine);
pLine->dwLineID = pTempLine->dwLineID;
pLine->dwComponentType = pTempLine->dwComponentType;
pLine->cChannels = pTempLine->cChannels;
pLine->cConnections = pTempLine->cConnections;
pLine->cControls = pTempLine->cControls;
pLine->dwDestination = pTempLine->dwDestination;
pLine->dwSource = pTempLine->dwSource;
_tcscpy(pLine->szShortName, pTempLine->szShortName);
_tcscpy(pLine->szName, pTempLine->szName);
pLine->Target.dwType = pTempLine->Target.dwType;
pLine->Target.dwDeviceID = pTempLine->Target.dwDeviceID;
pLine->Target.wMid = pTempLine->Target.wMid;
pLine->Target.wPid = pTempLine->Target.wPid;
pLine->Target.vDriverVersion = pTempLine->Target.vDriverVersion;
pLine->fdwLine = pTempLine->fdwLine;
_tcscpy(pLine->Target.szPname, pTempLine->Target.szPname);
return MMSYSERR_NOERROR;
badparms:
MIXERRMSG("Bad parameters in mix_handle_GETLINEINFO");
SetLastError(ERROR_INVALID_PARAMETER);
return MMSYSERR_INVALPARAM;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_GETLINECONTROLS
Description:
Gets info about the controls of a line
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD dwUser : returned by the app (not used)
DWORD dwParam1 : pointer to a MIXERLINECONTROLS structure that is filled with the controls info
DWORD dwParam2 : flags that describe the information requested
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_GETLINECONTROLS(PMIXER_CONTEXT pMixer, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
LPMIXERLINECONTROLS pLineControl = (LPMIXERLINECONTROLS)MapPtrToProcess((PVOID)dwParam1,
GetCallerProcess());
LPMIXERCONTROL pMixerControl;
DWORD i;
ASSERT(pMixer);
if (!pLineControl)
{
MIXERRMSG("Bad pLineControl in mix_handle_GETLINECONTROLS");
goto badparms;
}
pMixerControl = (LPMIXERCONTROL)MapPtrToProcess(pLineControl->pamxctrl, GetCallerProcess());
if (pLineControl->cbStruct < sizeof(MIXERLINECONTROLS) || pLineControl->cControls < 1 || pMixerControl == NULL)
{
MIXERRMSG("Bad pMixerControl in mix_handle_GETLINECONTROLS");
goto badparms;
}
// first identify the control
switch (dwParam2 & MIXER_GETLINECONTROLSF_QUERYMASK)
{
case MIXER_GETLINECONTROLSF_ALL:
{
int nControls;
LPMIXERLINE pTempLine;
MIXMSG("mix_handle_GETLINECONTROLS: MIXER_GETLINECONTROLSF_ALL");
//the caller wants all of this line's controls
if (pLineControl->dwLineID >= LINES_COUNT)
{
WARNMSG("Bad pLineControl dwLineID in mix_handle_GETLINECONTROLS");
return MIXERR_INVALLINE;
}
// does the line have any controls?
pTempLine = FindMixerLine(pLineControl->dwLineID);
if (!pTempLine)
{
WARNMSG("Unknown pLineControl dwLineID in mix_handle_GETLINECONTROLS");
return MIXERR_INVALLINE;
}
if (pTempLine->cControls == 0 ||
pTempLine->cControls > pLineControl->cControls)
{
WARNMSG("Line has no controls in mix_handle_GETLINECONTROLS");
return MIXERR_INVALLINE;
}
// all seems ok; let's find the first line control
for (nControls = i = 0; i < sizeof(g_Controls)/sizeof(g_Controls[0]); i++)
{
if (g_Controls[i].dwLineID == pLineControl->dwLineID)
{
CopyControlStruct(&pMixerControl[nControls++], i);
}
}
}
break;
case MIXER_GETLINECONTROLSF_ONEBYID:
MIXMSG1("mix_handle_GETLINECONTROLS: MIXER_GETLINECONTROLSF_ONEBYID: %d", pLineControl->dwControlID);
if (pLineControl->dwControlID >= sizeof(g_Controls)/sizeof(g_Controls[0]))
return MIXERR_INVALCONTROL;
// the ID is the index of the control in the g_Controls table;
if (pLineControl->cControls != 1)
goto badparms;
CopyControlStruct(pMixerControl, pLineControl->dwControlID);
break;
case MIXER_GETLINECONTROLSF_ONEBYTYPE:
MIXMSG2("mix_handle_GETLINECONTROLS: MIXER_GETLINECONTROLSF_ONEBYTYPE: line %d, type %d",
pLineControl->dwLineID, pLineControl->dwControlType);
if (pLineControl->cControls != 1)
goto badparms;
for (i = 0; i < sizeof(g_Controls)/sizeof(g_Controls[0]); i++)
{
if (g_Controls[i].dwLineID == pLineControl->dwLineID &&
(g_Controls[i].dwControlType & MIXERCONTROL_CT_CLASS_MASK) ==
(pLineControl->dwControlType & MIXERCONTROL_CT_CLASS_MASK))
{
CopyControlStruct(pMixerControl, i);
break;
}
}
// did we find any?
if (i == sizeof(g_Controls)/sizeof(g_Controls[0]))
{
// no
WARNMSG("No control of requested type");
return MIXERR_INVALCONTROL;
}
break;
default:
return MMSYSERR_INVALFLAG;
}
return MMSYSERR_NOERROR;
badparms:
MIXERRMSG("Bad parameters in mix_handle_GETLINECONTROLS");
SetLastError(ERROR_INVALID_PARAMETER);
return MMSYSERR_INVALPARAM;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:
mix_handle_GETCONTROLDETAILS
Description:
Gets detailed information about a control
Arguments:
PMIXER_CONTEXT pMixer : pointer to the mixer context structure
DWORD dwUser : returned by the app (not used)
DWORD dwParam1 : pointer to the MIXERCONTROLDETAILS structure where the function returns info
DWORD dwParam2 : flags that describe the information requested
Return Value: DWORD
-------------------------------------------------------------------*/
DWORD mix_handle_GETCONTROLDETAILS(PMIXER_CONTEXT pMixer, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
LPMIXERCONTROLDETAILS pControlDetails = (LPMIXERCONTROLDETAILS) MapPtrToProcess((PVOID)dwParam1, GetCallerProcess());
DWORD dwRet = NO_ERROR;
PDRIVER_CONTEXT pDriverContext = g_pDriverContext;
ASSERT(pDriverContext);
if (!pControlDetails)
goto badparms;
if (pControlDetails->cbStruct < sizeof(MIXERCONTROLDETAILS))
goto badparms;
if (pControlDetails->dwControlID >= MAX_CONTROLS)
{
MIXERRMSG1("mix_handle_GETCONTROLDETAILS: Bad control ID: %d", pControlDetails->dwControlID);
return MIXERR_INVALCONTROL;
}
switch (dwParam2 & MIXER_GETCONTROLDETAILSF_QUERYMASK)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -