144 lines
6.5 KiB
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));
|
|
|
|
} |