Audio-gebeurtenissen voor verouderde audiotoepassingen
Verouderde audio-API's zoals DirectSound, DirectShow en de waveOutXxx--functies stellen toepassingen in staat om de volumeniveaus van audiostreams op te halen en in te stellen. Toepassingen kunnen de mogelijkheden voor volumebesturing in deze API's gebruiken om volumeschuifregelaars weer te geven in hun toepassingsvensters.
In Windows Vista, het systeem volume-control programma, Sndvol, kunnen gebruikers de audiovolumeniveaus voor afzonderlijke toepassingen beheren. De volumeschuifregelaars die door toepassingen worden weergegeven, moeten worden gekoppeld aan de bijbehorende volumeschuifregelaars in Sndvol. Als een gebruiker het toepassingsvolume aanpast via een volumeschuifregelaar in een toepassingsvenster, wordt de bijbehorende volumeschuifregelaar in Sndvol onmiddellijk verplaatst om het nieuwe volumeniveau aan te geven. Als de gebruiker daarentegen het toepassingsvolume aanpast via Sndvol, moeten de volumeschuifregelaars in het toepassingsvenster worden verplaatst om het nieuwe volumeniveau aan te geven.
In Windows Vista weerspiegelt Sndvol onmiddellijk volumewijzigingen die een toepassing maakt via aanroepen naar de methode IDirectSoundBuffer::SetVolume methode of waveOutSetVolume functie. Een verouderde audio-API, zoals DirectSound of de waveOutXxx--functies, biedt echter geen middelen om een toepassing op de hoogte te stellen wanneer de gebruiker het toepassingsvolume wijzigt via Sndvol. Als een toepassing een volumeschuifregelaar weergeeft, maar geen meldingen over volumewijzigingen ontvangt, kan de schuifregelaar geen wijzigingen weergeven die door de gebruiker in Sndvol zijn aangebracht. Om het juiste gedrag te implementeren, moet de toepassingsontwerper op een of andere manier compenseren voor het ontbreken van meldingen door de verouderde audio-API.
Een oplossing kan zijn dat de toepassing een timer instelt om het regelmatig eraan te herinneren dat het volumeniveau moet worden gecontroleerd om te zien of deze is gewijzigd.
Een elegantere oplossing is dat de toepassing de mogelijkheden voor gebeurtenismeldingen van de kernaudio-API's kan gebruiken. De toepassing kan met name een IAudioSessionEvents interface registreren om callbacks te ontvangen wanneer volumewijzigingen of andere typen audio-gebeurtenissen plaatsvinden. Wanneer het volume wordt gewijzigd, kan de callbackroutine voor volumewijzigingen onmiddellijk de volumeschuifregelaar van de toepassing bijwerken om de wijziging weer te geven.
In het volgende codevoorbeeld ziet u hoe een toepassing zich kan registreren voor het ontvangen van meldingen van volumewijzigingen en andere audio-gebeurtenissen:
//-----------------------------------------------------------
// Register the application to receive notifications when the
// volume level changes on the default process-specific audio
// session (with session GUID value GUID_NULL) on the audio
// endpoint device with the specified data-flow direction
// (eRender or eCapture) and device role.
//-----------------------------------------------------------
#define EXIT_ON_ERROR(hr) \
if (FAILED(hr)) { goto Exit; }
#define SAFE_RELEASE(punk) \
if ((punk) != NULL) \
{ (punk)->Release(); (punk) = NULL; }
class AudioVolumeEvents
{
HRESULT _hrStatus;
IAudioSessionManager *_pManager;
IAudioSessionControl *_pControl;
IAudioSessionEvents *_pAudioEvents;
public:
AudioVolumeEvents(EDataFlow, ERole, IAudioSessionEvents*);
~AudioVolumeEvents();
HRESULT GetStatus() { return _hrStatus; };
};
// Constructor
AudioVolumeEvents::AudioVolumeEvents(EDataFlow flow, ERole role,
IAudioSessionEvents *pAudioEvents)
{
IMMDeviceEnumerator *pEnumerator = NULL;
IMMDevice *pDevice = NULL;
_hrStatus = S_OK;
_pManager = NULL;
_pControl = NULL;
_pAudioEvents = pAudioEvents;
if (_pAudioEvents == NULL)
{
_hrStatus = E_POINTER;
return;
}
_pAudioEvents->AddRef();
// Get the enumerator for the audio endpoint devices
// on this system.
_hrStatus = CoCreateInstance(__uuidof(MMDeviceEnumerator),
NULL, CLSCTX_INPROC_SERVER,
__uuidof(IMMDeviceEnumerator),
(void**)&pEnumerator);
EXIT_ON_ERROR(_hrStatus)
// Get the audio endpoint device with the specified data-flow
// direction (eRender or eCapture) and device role.
_hrStatus = pEnumerator->GetDefaultAudioEndpoint(flow, role,
&pDevice);
EXIT_ON_ERROR(_hrStatus)
// Get the session manager for the endpoint device.
_hrStatus = pDevice->Activate(__uuidof(IAudioSessionManager),
CLSCTX_INPROC_SERVER, NULL,
(void**)&_pManager);
EXIT_ON_ERROR(_hrStatus)
// Get the control interface for the process-specific audio
// session with session GUID = GUID_NULL. This is the session
// that an audio stream for a DirectSound, DirectShow, waveOut,
// or PlaySound application stream belongs to by default.
_hrStatus = _pManager->GetAudioSessionControl(NULL, 0, &_pControl);
EXIT_ON_ERROR(_hrStatus)
_hrStatus = _pControl->RegisterAudioSessionNotification(_pAudioEvents);
EXIT_ON_ERROR(_hrStatus)
Exit:
SAFE_RELEASE(pEnumerator)
SAFE_RELEASE(pDevice)
}
// Destructor
AudioVolumeEvents::~AudioVolumeEvents()
{
if (_pControl != NULL)
{
_pControl->UnregisterAudioSessionNotification(_pAudioEvents);
}
SAFE_RELEASE(_pManager)
SAFE_RELEASE(_pControl)
SAFE_RELEASE(_pAudioEvents)
};
In het voorgaande codevoorbeeld wordt een klasse met de naam AudioVolumeEvents geïmplementeerd. Tijdens de initialisatie van het programma schakelt de audiotoepassing audiogebeurtenismeldingen in door een AudioVolumeEvents-object te maken. De constructor voor deze klasse heeft drie invoerparameters:
- stroom: de gegevensstroomrichting van het audio-eindpuntapparaat (een EDataFlow opsommingswaarde).
- rol: de huidige apparaatrol van het eindpuntapparaat (een ERole opsommingswaarde).
- pAudioEvents— wijs een object aan (een IAudioSessionEvents interface-exemplaar) die een set callback-routines bevat die door de toepassing worden geïmplementeerd.
De constructor levert de stroom- en rolwaarden als invoerparameters aan de methode IMMDeviceEnumerator::GetDefaultAudioEndpoint methode. De methode maakt een IMMDevice--object dat het audio-eindpuntapparaat inkapselt met de opgegeven richting van de gegevensstroom en de apparaatrol.
De toepassing implementeert het object waarnaar wordt verwezen door pAudioEvents. (De implementatie wordt niet weergegeven in het voorgaande codevoorbeeld. Zie Audiosessie-gebeurtenissenvoor een codevoorbeeld waarmee een IAudioSessionEvents interface wordt geïmplementeerd. Elke methode in deze interface ontvangt meldingen van een bepaald type audio-gebeurtenis. Als de toepassing niet geïnteresseerd is in een bepaald gebeurtenistype, moet de methode voor dat gebeurtenistype niets doen, maar S_OK retourneren.
De methode IAudioSessionEvents::OnSimpleVolumeChanged ontvangt meldingen van volumewijzigingen. Deze methode werkt doorgaans de volumeschuifregelaar van de toepassing bij.
In het voorgaande codevoorbeeld wordt de constructor voor de klasse AudioVolumeEvents geregistreerd voor meldingen over de processpecifieke audiosessie die wordt geïdentificeerd door de waarde van de sessie-GUID GUID_NULL. Standaard wijzen verouderde audio-API's zoals DirectSound, DirectShow en de waveOutXxx functies hun streams toe aan deze sessie. Een DirectSound- of DirectShow-toepassing kan echter, als optie, het standaardgedrag overschrijven en de streams toewijzen aan een sessie voor meerdere processen of aan een sessie die wordt geïdentificeerd door een andere GUID-waarde dan GUID_NULL. (Er is momenteel geen mechanisme beschikbaar voor een waveOutXxx toepassing om het standaardgedrag op een vergelijkbare manier te overschrijven.) Zie Apparaatrollen voor DirectShow-toepassingenvoor een codevoorbeeld van een DirectShow-toepassing met dit gedrag. Als u een dergelijke toepassing wilt gebruiken, kunt u de constructor in het voorgaande codevoorbeeld wijzigen om twee extra invoerparameters te accepteren: een sessie-GUID en een vlag om aan te geven of de sessie die moet worden bewaakt, een proces- of processpecifieke sessie is. Geef deze parameters door aan de aanroep van de IAudioSessionManager::GetAudioSessionControl methode in de constructor.
Nadat de constructor de methode IAudioSessionControl::RegisterAudioSessionNotification methode voor registratie voor meldingen heeft aangeroepen, blijft de toepassing alleen meldingen ontvangen zolang de IAudioSessionControl of IAudioSessionManager interface bestaat. Het Object AudioVolumeEvents in het voorgaande codevoorbeeld bevat verwijzingen naar deze interfaces totdat destructor wordt aangeroepen. Dit gedrag zorgt ervoor dat de toepassing meldingen blijft ontvangen voor de levensduur van het AudioVolumeEvents-object.
In plaats van impliciet een audioapparaat te selecteren op basis van de apparaatrol, kan de gebruiker met een DirectSound- of verouderde Windows-multimediatoepassing expliciet een apparaat selecteren in een lijst met beschikbare apparaten die worden geïdentificeerd door hun beschrijvende namen. Ter ondersteuning van dit gedrag moet het voorgaande codevoorbeeld worden gewijzigd om audiogebeurtenismeldingen voor het geselecteerde apparaat te genereren. Er zijn twee wijzigingen vereist. Wijzig eerst de constructordefinitie om een eindpunt-id-tekenreeks te accepteren als invoerparameter (in plaats van de stroom- en rolparameters in het codevoorbeeld). Deze tekenreeks identificeert het audio-eindpuntapparaat dat overeenkomt met het geselecteerde DirectSound- of legacy waveform-apparaat. Vervang vervolgens de aanroep van de methode IMMDeviceEnumerator::GetDefaultAudioEndpoint door een aanroep naar de methode IMMDeviceEnumerator::GetDevice methode. De aanroep GetDevice neemt de eindpunt-id-tekenreeks als invoerparameter en maakt een exemplaar van het eindpuntapparaat dat wordt geïdentificeerd door de tekenreeks.
De techniek voor het verkrijgen van de eindpunt-id-tekenreeks voor een DirectSound-apparaat of een verouderd waveform-apparaat is als volgt.
Ten eerste levert DirectSound tijdens de opsomming van het apparaat de eindpunt-id-tekenreeks voor elk geïnventariseerd apparaat. Om apparaatinventarisatie te starten, geeft de toepassing een callback-functieaanwijzer door als invoerparameter aan de functie DirectSoundCreate of DirectSoundCaptureCreate functie. De definitie van de callback-functie is:
BOOL DSEnumCallback(
LPGUID lpGuid,
LPCSTR lpcstrDescription,
LPCSTR lpcstrModule,
LPVOID lpContext
);
In Windows Vista verwijst de lpcstrModule parameter naar de eindpunt-id-tekenreeks. (In eerdere versies van Windows, waaronder Windows Server 2003, Windows XP en Windows 2000, verwijst de parameter lpcstrModule naar de naam van de stuurprogrammamodule voor het apparaat.) De parameter lpcstrDescription verwijst naar een tekenreeks die de beschrijvende naam van het apparaat bevat. Zie de Windows SDK-documentatie voor meer informatie over De opsomming van DirectSound-apparaten.
Ten tweede gebruikt u de waveOutMessage- of waveIn Message-functie om een DRV_QUERYFUNCTIONINSTANCEID bericht te verzenden naar het waveform-apparaatstuurprogramma om de eindpunt-id-tekenreeks voor een verouderd waveform-apparaat te verkrijgen. Zie Apparaatrollen voor oudere Windows Multimedia-toepassingenvoor een codevoorbeeld waarin het gebruik van dit bericht wordt weergegeven.
Verwante onderwerpen