我现在正在使用旧的好的 Mixer API,但它在 Windows Vista 和 7 上不能正常工作,而不是在 XP 兼容模式下。它只为当前应用程序静音,但我需要一个全局(硬件)静音。如何达到目标?有没有办法在纯 C/C++ 中编写这个没有 COM 接口和奇怪调用的代码?
问问题
2785 次
2 回答
4
为 Vista 重写了音频堆栈。每个应用程序的音量和静音控制确实是新功能之一。使用IAudioEndpointVolume 接口需要奇怪的调用。
于 2010-02-27T15:04:05.703 回答
0
我最近处理了同样的问题。我们有一个使用声音系统进行警报的 Windows 应用程序。我们不能容忍用户无意中将音响系统静音。以下是我如何能够使用上面建议的界面来解决这个问题:
在初始化期间,我添加了一个函数来初始化 IAudioEndpointVolume 类型的成员。这有点棘手,而且帮助也没有得到应有的帮助。这是如何做到的:
/****************************************************************************
** Initialize the Audio Endpoint (Only for post XP systems)
****************************************************************************/
void CMuteWatchdog::InitAudioEndPoint(void)
{
HRESULT hr;
IMMDeviceEnumerator * pDevEnum;
IMMDevice * pDev;
const CLSID CLSID_MMDeviceEnumerator = __uuidof(MMDeviceEnumerator);
const IID IID_IMMDeviceEnumerator = __uuidof(IMMDeviceEnumerator);
hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL,
CLSCTX_ALL, IID_IMMDeviceEnumerator,
(void**)&pDevEnum);
m_pIaudEndPt = NULL;
if(hr == S_OK)
{
hr = pDevEnum->GetDefaultAudioEndpoint(eRender, eConsole, &pDev);
if(hr == S_OK)
{
DWORD dwClsCtx;
const IID iidAEV = __uuidof(IAudioEndpointVolume);
dwClsCtx = 0;
hr = pDev->Activate(iidAEV, dwClsCtx, NULL, (void**) &m_pIaudEndPt);
if(hr == S_OK)
{
// Everything is groovy.
}
else
{
m_pIaudEndPt = NULL; // Might mean it's running on XP or something. Don't use.
}
pDev->Release();
}
pDevEnum->Release();
}
}
...
大约每秒一次,我添加了一个对以下内容的简单调用:
////////////////////////////////////////////////////////////////////////
// Watchdog function for mute.
void CMuteWatchdog::GuardMute(void)
{
if(m_pIaudEndPt)
{
BOOL bMute;
HRESULT hr;
bMute = FALSE;
hr = m_pIaudEndPt->GetMute(&bMute);
if(hr == S_OK)
{
if(bMute)
{
m_pIaudEndPt->SetMute(FALSE, NULL);
}
}
}
}
最后,当程序退出时,请记住释放分配的资源。
////////////////////////////////////////////////////////////////////////
// De-initialize the watchdog
void CMuteWatchdog::OnClose(void)
{
if(m_pIaudEndPt)
{
m_pIaudEndPt->Release();
m_pIaudEndPt = NULL;
}
}
于 2014-06-17T17:01:57.500 回答