WASAPI_Notification_Interfaces/AudioSessions_framework.c

144 lines
6.5 KiB
C

#include "AudioSesssions_framework.h"
static inline HRESULT getDefaultAudioEndpoint(AudioSessionsInformation*);
static inline HRESULT refreshIMMEnumerator(AudioSessionsInformation*);
static HRESULT releaseControlInterfaces(AudioSessionsInformation*);
/*
* \brief Initilises Co in multithreaded and gets IMM devices & default device interfaces.
*/
HRESULT initialiseSessionsFramework(AudioSessionsInformation * pSessionInformation)
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
// Gets a new enumerator of all the multimedia devices
refreshIMMEnumerator(pSessionInformation);
// Gets the device interface for the default audio endpoint
getDefaultAudioEndpoint(pSessionInformation);
InitializeAudioSessionNotification(&pSessionInformation->AudioSessionNotification,
&pSessionInformation->AudioSessionControlsCollection,
&pSessionInformation->NumberAudioSessionsActive);
refreshOpenSessions(pSessionInformation);
return S_OK;
}
HRESULT refreshOpenSessions(AudioSessionsInformation* pSessionInformation)
{
// Throw an error if the IMMDevice pointer has not been initialised
if (!pSessionInformation->IMMDevice) return CO_E_NOTINITIALIZED;
// Get a session manager 2 interface and use it to get a session enumerator
IAudioSessionManager2* myAudioSessionManager2 = NULL;
pSessionInformation->IMMDevice->lpVtbl->Activate(pSessionInformation->IMMDevice,
&IID_IAudioSessionManager2,
CLSCTX_ALL,
NULL,
&myAudioSessionManager2);
IAudioSessionEnumerator* myAudioSessionEnumerator;
myAudioSessionManager2->lpVtbl->GetSessionEnumerator(myAudioSessionManager2,
&myAudioSessionEnumerator);
// Then release the notifications interface
pSessionInformation->AudioSessionNotification->lpVtbl->Release(pSessionInformation->AudioSessionNotification);
// And register a new one, I think this may be necessary if the endpoint has changed
myAudioSessionManager2->lpVtbl->RegisterSessionNotification(myAudioSessionManager2, pSessionInformation->AudioSessionNotification);
// Once we have the number of open sessions memory can be allocated for the control interfaces
// First; release any control interfaces left over and free the memory
releaseControlInterfaces(pSessionInformation);
// Then get the number of sessions active and save it in the session information stuct
myAudioSessionEnumerator->lpVtbl->GetCount(myAudioSessionEnumerator,
&pSessionInformation->NumberAudioSessionsActive);
// Allocate memory
pSessionInformation->AudioSessionControlsCollection = malloc(sizeof(IAudioSessionControl) * pSessionInformation->NumberAudioSessionsActive);
// Print to console if the memory cannot be allocated
if (!pSessionInformation->AudioSessionControlsCollection) printf("\nMemory allocation error.");
// Put all the sessions into the array along with an index for each, also register the events
for (int i = 0; i < pSessionInformation->NumberAudioSessionsActive; i++)
{
//TODO: This should really be a simple audio interface rather then an audio session control interface
IAudioSessionControl* sessionControl;
// Get the session control interface from the enumerator
myAudioSessionEnumerator->lpVtbl->GetSession(myAudioSessionEnumerator, i, &sessionControl);
pSessionInformation->AudioSessionControlsCollection[i] = sessionControl;
// Register the events interface for the session
// This is complicated slightly because I want to be able to identify the disconnected session in the disconnection handler
// This requires putting the address of the control interface into the events interface
// The problem with this is that there is an events interface created for each control session
// Although they all share a virtual table
myIAudioSessionEvents* AudioSessionEvents;
// The virtual table will be created on the first call to this function and then used for all future calls
// Also takes the address of the pointer to the array of control interface pointers
// This address should be constant whereas the pointer to the array of interface pointers will change every time an interface is add/destroyed and new memory is allocated
InitializeAudioSessionEvents(&AudioSessionEvents, sessionControl, pSessionInformation->AudioSessionControlsCollection);
// Now the events interface has been setup, register it
// This requires casting my session events interface to the interface expected by the api
sessionControl->lpVtbl->RegisterAudioSessionNotification(sessionControl, AudioSessionEvents);
AudioSessionState sessionState = 3;
sessionControl->lpVtbl->GetState(sessionControl, &sessionState);
printf("\nRegistered session %d with control iterface at %p and events interface at %p", i, sessionControl, &AudioSessionEvents);
printf("with state ");
switch (sessionState)
{
case(2):
printf("Expired");
break;
case(1):
printf("Active");
break;
case(0):
printf("Inactive");
break;
default:
printf("Unknown");
break;
}
}
// Release the session manager and enumerator
myAudioSessionManager2->lpVtbl->Release(myAudioSessionManager2);
myAudioSessionEnumerator->lpVtbl->Release(myAudioSessionEnumerator);
return S_OK;
}
// Releases the audio control interfaces in the session information structure.
// Also releases the memory allocated to the array of pointers to the control interfaces
HRESULT releaseControlInterfaces(AudioSessionsInformation * pSessionInformation)
{
// Goes through and releases all the control interfaces left over.
for (int i = 0; i < pSessionInformation->NumberAudioSessionsActive; i++)
{
//ControlInterfaces[i]->lpVtbl->Release(ControlInterfaces[i]);
IAudioSessionControl* nextInterface = (pSessionInformation->AudioSessionControlsCollection[i]);
nextInterface->lpVtbl->Release(nextInterface);
}
if (!pSessionInformation->AudioSessionControlsCollection) free(pSessionInformation->AudioSessionControlsCollection);
return S_OK;
}
// Updates the IMM Device default audio endpoint in the session information structure
HRESULT getDefaultAudioEndpoint(AudioSessionsInformation* pSessionInformation)
{
return pSessionInformation->IMMEnumerator->lpVtbl->GetDefaultAudioEndpoint(pSessionInformation->IMMEnumerator,
eRender,
eMultimedia,
&(pSessionInformation->IMMDevice));
}
// Refreshes the list of IMM devices
HRESULT refreshIMMEnumerator(AudioSessionsInformation* pSessionInformation)
{
return CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, &(pSessionInformation->IMMEnumerator));
}