📄 mixerdrv.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
// -----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// -----------------------------------------------------------------------------
//
// @doc WDEV_EXT
//
// @module mixerdrv.cpp | Implements the WODM_XXX and WIDM_XXX messages that are
// passed to the wave audio driver via the <f WAV_IOControl> function.
// This module contains code that is common or very similar between
// input and output functions.
//
// @xref <t Wave Input Driver Messages> (WIDM_XXX) <nl>
// <t Wave Output Driver Messages> (WODM_XXX)
//
// -----------------------------------------------------------------------------
#include <wavemain.h>
#include <mmreg.h>
#define ZONE_HWMIXER ZONE_VERBOSE
#define ZONE_VOLUME ZONE_VERBOSE
#define LOGICAL_VOLUME_MAX 0xFFFF
#define LOGICAL_VOLUME_MIN 0
#define LOGICAL_VOLUME_STEPS 16
// only support Mic, LineIn as inputs
#define INPUT_SELECT_COUNT 2
#define DEVICE_NAME L"Audio Mixer"
#define DRIVER_VERSION 0x100
#define NELEMS(x) (sizeof(x)/sizeof((x)[0]))
// mixer handle data types
typedef DWORD (* PFNDRIVERCALL)(DWORD hmx, UINT uMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
typedef struct _tagMCB MIXER_CALLBACK, * PMIXER_CALLBACK;
struct _tagMCB
{
DWORD hmx;
PFNDRIVERCALL pfnCallback;
PMIXER_CALLBACK pNext;
};
// mixer line ID are 16-bit values formed by concatenating the source and destination line indices
//
#define MXLINEID(dst,src) ((USHORT) ((USHORT)(dst) | (((USHORT) (src)) << 8)))
#define GET_MXLINE_SRC(lineid) ((lineid) >> 8)
#define GET_MXLINE_DST(lineid) ((lineid) & 0xff)
#define GET_MXCONTROL_ID(ctl) ((ctl)-g_controls)
#ifdef DEBUG
// DEBUG-only support for displaying control type codes in readable form
typedef struct
{
DWORD val;
PWSTR str;
} MMSYSCODE;
#define MXCTYPE(typ) {typ, TEXT(#typ)}
MMSYSCODE ctype_table[] =
{
MXCTYPE(MIXERCONTROL_CONTROLTYPE_CUSTOM),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BASS),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_EQUALIZER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_FADER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_TREBLE),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_VOLUME),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MIXER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MULTIPLESELECT),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MUX),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SINGLESELECT),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BOOLEANMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_PEAKMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SIGNEDMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_UNSIGNEDMETER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_DECIBELS),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_PERCENT),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SIGNED),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_UNSIGNED),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_PAN),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_QSOUNDPAN),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_SLIDER),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BOOLEAN),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_BUTTON),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_LOUDNESS),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MONO),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MUTE),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_ONOFF),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_STEREOENH),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MICROTIME),
MXCTYPE(MIXERCONTROL_CONTROLTYPE_MILLITIME),
};
PWSTR
COMPTYPE(DWORD dwValue)
{ int i;
for (i = 0; i < NELEMS(ctype_table); i++) {
if (ctype_table[i].val == dwValue) {
return ctype_table[i].str;
}
}
return TEXT("<unknown>");
}
#else
#define COMPTYPE(n) TEXT("<>")
#endif
// Destinations:
// LINE_OUT - line out jack
// PCM_IN - input to ADC
// Sources
// MIC - MIC jack
enum {
LINE_OUT = 0x80,
PCM_IN,
MIC,
NOLINE = 0xff // doesn't HAVE to be FF, but makes it easier to see
};
const USHORT
g_dst_lines[] =
{
MXLINEID(LINE_OUT,NOLINE),
MXLINEID(PCM_IN,NOLINE)
};
const USHORT
g_PCM_IN_sources[] =
{
MXLINEID(PCM_IN,MIC)
};
// MXLINEDESC corresponds to MIXERLINE, but is designed to conserve space
typedef struct tagMXLINEDESC const * PMXLINEDESC, MXLINEDESC;
typedef struct tagMXCONTROLDESC const * PMXCONTROLDESC, MXCONTROLDESC;
struct tagMXLINEDESC {
DWORD dwComponentType;
PCWSTR szShortName;
PCWSTR szName;
DWORD ucFlags;
USHORT const * pSources;
USHORT usLineID;
UINT8 ucChannels;
UINT8 ucConnections;
UINT8 ucControls;
DWORD dwTargetType;
UINT8 ucDstIndex;
UINT8 ucSrcIndex;
} ;
// MXCONTROLDESC is driver shorthand for Volume and Mute MIXERCONTROL
struct tagMXCONTROLDESC
{
PWSTR szName;
DWORD dwType;
USHORT usLineID; // line that owns this control
};
// mixerline ID
#define _MXLE(id,dst,src,flags,comptype,nch,ncnx,nctrl,sname,lname,target,sarray)\
{comptype,\
TEXT(sname),TEXT(lname),\
flags, \
sarray,\
id,\
nch,ncnx,nctrl,\
target,\
dst,src}
// declare a destination line
#define MXLED(id,dst,flags,comptype,nch,nctrl,sname,lname,target,srcarray,nsrcs)\
_MXLE(MXLINEID(id,NOLINE),dst,NOLINE,flags,comptype,nch,nsrcs,nctrl,sname,lname,target,srcarray)\
// declare a source line
#define MXSLE(id,dst,src,flags,comptype,nch,nctrl,sname,lname,target)\
_MXLE(id,dst,src,flags,comptype,nch,0,nctrl,sname,lname,target,NULL)\
MXLINEDESC
g_mixerline[] =
{
// dst line 0 - speaker out
MXLED(LINE_OUT, 0,
MIXERLINE_LINEF_ACTIVE, // no flags
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS,
1, // mono
2, // controls: volume + mute
"Volume Control","Volume Control",
MIXERLINE_TARGETTYPE_WAVEOUT,
NULL, 0
),
// dst line 1 - microphone input
MXLED(PCM_IN, 1,
MIXERLINE_LINEF_ACTIVE, // flags
MIXERLINE_COMPONENTTYPE_DST_WAVEIN,
1, // mono
1, // 1 control (MUX) - the record gain is virtualized across all mux inputs
"Recording Contr","Recording Control",
MIXERLINE_TARGETTYPE_WAVEIN,
g_PCM_IN_sources, NELEMS(g_PCM_IN_sources)
),
// ----------------------
// PCM_IN Sources Lines
// ----------------------
// src line - Microphone
MXSLE(MXLINEID(PCM_IN, MIC), 1, 1,
MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE, // flags
MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE,
1, // mono
2, // controls: volume, mute
"Microphone","Microphone",
MIXERLINE_TARGETTYPE_WAVEIN
),
};
const int nlines = NELEMS(g_mixerline);
#undef _MXLE
#undef MXLED
#undef MXSLE
#define MXCE(dst,src,nme,type) {TEXT(nme),type,MXLINEID(dst,src)}
MXCONTROLDESC
g_controls[] =
{
MXCE(LINE_OUT, NOLINE, "Master Volume", MIXERCONTROL_CONTROLTYPE_VOLUME),
MXCE(LINE_OUT, NOLINE, "Master Mute", MIXERCONTROL_CONTROLTYPE_MUTE),
MXCE(PCM_IN, MIC, "Mic Volume", MIXERCONTROL_CONTROLTYPE_VOLUME),
MXCE(PCM_IN, MIC, "Mic Mute", MIXERCONTROL_CONTROLTYPE_MUTE),
};
const UINT ncontrols = NELEMS(g_controls);
#undef MXCE
PMXLINEDESC
LookupMxLine(USHORT usLineID)
{
// scan for mixer line
int i;
for (i = 0; i < nlines; i++) {
if (g_mixerline[i].usLineID == usLineID) {
return &g_mixerline[i];
}
}
return NULL;
}
int
LookupMxControl (USHORT usLineID, DWORD dwControlType)
{
UINT i;
for (i = 0; i < ncontrols; i++) {
PMXCONTROLDESC pSrcControl = &g_controls[i];
if ( pSrcControl->usLineID == usLineID
&& pSrcControl->dwType == dwControlType) {
break;
}
}
return i;
}
void
CopyMixerControl(PMIXERCONTROL pDst, PMXCONTROLDESC pSrc, DWORD dwIndex)
{
// all of our lines have a volume and a mute.
// in addition, the PCM_IN has a MUX control
// fill in the volume:
pDst->cbStruct = sizeof(MIXERCONTROL);
pDst->dwControlID = dwIndex;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -