Как глобально отключить и включить звук в Vista и 7 и получить состояние отключения звука?
-
23-09-2019 - |
Вопрос
Прямо сейчас я использую старый добрый Mixer API, но он работает не так, как ожидалось, в Windows Vista и 7 в обычном режиме, а не в режиме совместимости с XP.Это отключает звук только для текущего приложения, но мне нужно глобальное (аппаратное) отключение звука.Как переориентировать цель?Есть ли какой-нибудь способ закодировать это без COM-интерфейсов и странных вызовов на чистом C / C ++?
Решение
Аудиостек был значительно переписан для Vista.Управление громкостью и отключением звука для каждого приложения действительно было одной из новых функций.Странные вызовы потребуются для использования Интерфейс IAudioEndpointVolume.
Другие советы
Недавно я столкнулся с этой же проблемой.У нас есть приложение для 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;
}
}