J'utilise l'ancienne bonne API Mixer pour l'instant, mais elle ne fonctionne pas comme prévu sous Windows Vista & 7 en mode normal, pas en mode de compatibilité XP. Il coupe le son pour l'application actuelle uniquement, mais j'ai besoin d'un son global (matériel). Comment chercher l'objectif? Est-il possible de coder ceci sans interfaces COM et appels étranges, en C/C++ pur?Comment couper et rétablir le son de façon globale dans Vista et 7, et obtenir un état muet?
Répondre
La pile audio a été significativement réécrite pour Vista. Le volume par application et le contrôle muet étaient en effet l'une des nouvelles fonctionnalités. Des appels étranges seront nécessaires pour utiliser le IAudioEndpointVolume interface.
J'ai récemment traité ce même problème. Nous avons une application Windows qui utilise le système de son pour les alarmes. Nous ne pouvons pas tolérer que l'utilisateur coupe le son par inadvertance. Voici comment j'ai pu utiliser l'interface suggérée ci-dessus pour résoudre ce problème:
Lors de l'initialisation, j'ai ajouté une fonction pour initialiser un membre de type IAudioEndpointVolume. C'était un peu compliqué et l'aide n'était pas aussi utile que possible. Voici comment faire:
/****************************************************************************
** 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();
}
}
...
Environ une fois par seconde j'ai ajouté un simple appel à ce qui suit:
////////////////////////////////////////////////////////////////////////
// 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);
}
}
}
}
Enfin, lorsque le programme se termine n'oubliez pas de libérer la ressource allouée.
////////////////////////////////////////////////////////////////////////
// De-initialize the watchdog
void CMuteWatchdog::OnClose(void)
{
if(m_pIaudEndPt)
{
m_pIaudEndPt->Release();
m_pIaudEndPt = NULL;
}
}
Pourriez-vous donner un échantillon de travail pour le problème indiqué ci-dessus? Est-il possible de s'abstenir de COM, et d'écrire le code en C pur ou C++? –
Vous avez vécu une vie bénie si vous n'avez jamais écrit de code COM auparavant. Il n'y a pas moyen de contourner cela. Vous pouvez obtenir un exemple de code du gars qui a conçu l'interface. Lien: http://blogs.msdn.com/larryosterman/archive/2007/03/06/how-do-i-change-the-master-volume-in-windows-vista.aspx –