155 lines
6.0 KiB
C
155 lines
6.0 KiB
C
#include "IAudioSessionNotification.h"
|
|
|
|
HRESULT InitializeAudioSessionNotification(IAudioSessionNotification** this, IAudioSessionControl *** pppAudioSessionControlInterfaces, int* pNumberSessionControls)
|
|
{
|
|
// Initializes the IAudioSessionNotification struct, this involves creating it, allocating memory, setting initial vaules and assigning the functions to be used
|
|
//Allocate memory for the vtable
|
|
IAudioSessionNotificationVtbl* pvtbl = malloc(sizeof(IAudioSessionNotificationVtbl));
|
|
|
|
if (!pvtbl)
|
|
{
|
|
// If the vtable memory cannot be assigned
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Asign all the functions
|
|
pvtbl->AddRef = (*IAudioSessionNotificationAddRef);
|
|
pvtbl->OnSessionCreated = (*IAudioSessionNotificationOnSessionCreated);
|
|
pvtbl->QueryInterface = (*IAudioSessionNotificationQueryInterface);
|
|
pvtbl->Release = (*IAudioSessionNotificationRelease);
|
|
|
|
//Assign memory for the notifications struct. Cast the pointer returned from malloc to the correct type
|
|
myIAudioSessionNotification * AudioSessionNotification;
|
|
AudioSessionNotification = (myIAudioSessionNotification*) malloc(sizeof(myIAudioSessionNotification));
|
|
if (!AudioSessionNotification)
|
|
{
|
|
// If the struct memory cannot be assigned free the memory previously assigned to the vtable and return
|
|
free(pvtbl);
|
|
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Add the virtual table to the strut
|
|
AudioSessionNotification->lpVtbl = pvtbl;
|
|
AudioSessionNotification->cRef = 0;
|
|
// pppAudioSessionControlInterfaces is a pointer to an array of control interface pointers
|
|
AudioSessionNotification->pppAudioSessionControlInterfaces = pppAudioSessionControlInterfaces;
|
|
AudioSessionNotification->pNumberAudioSessionControls = pNumberSessionControls;
|
|
|
|
// Update the pointer address passed into the function
|
|
*this = (IAudioSessionNotification*) AudioSessionNotification;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE IAudioSessionNotificationQueryInterface(IAudioSessionNotification* this, REFIID riid, void** ppvoid)
|
|
{
|
|
//printf("\nQuery interface audio session notification\n");
|
|
// Validate the object pointer.
|
|
if (!this)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Validate other parameters.
|
|
if (!ppvoid)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Set the output pointer to NULL.
|
|
*ppvoid = NULL;
|
|
// Check the interface identifier. memcmp() returns 0 if they are equal.
|
|
if (memcmp(riid, &IID_IUnknown, sizeof(IID)) && memcmp(riid, &IID_IAudioSessionNotification, sizeof(IID)))
|
|
{
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
// The interface is supported. Increment the reference count and return.
|
|
this->lpVtbl->AddRef(this);
|
|
*ppvoid = this;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE IAudioSessionNotificationRelease(IAudioSessionNotification* this)
|
|
{
|
|
// Cast the standard interface to my interface to allow access to cRef
|
|
myIAudioSessionNotification* castInterface = (myIAudioSessionNotification*) this;
|
|
|
|
ULONG cRef = InterlockedDecrement(&castInterface->cRef);
|
|
|
|
if (cRef == 0)
|
|
{
|
|
free(castInterface->lpVtbl);
|
|
free(castInterface);
|
|
//printf("\nAudio session notification memory freed");
|
|
}
|
|
|
|
//printf("\nNotification release, ref count : %ld\n", cRef);
|
|
return cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE IAudioSessionNotificationAddRef(IAudioSessionNotification* this)
|
|
{
|
|
// Cast the standard interface to my interface to allow access to cRef
|
|
myIAudioSessionNotification* castInterface = (myIAudioSessionNotification*)this;
|
|
return InterlockedIncrement(&castInterface->cRef);
|
|
}
|
|
|
|
HRESULT IAudioSessionNotificationOnSessionCreated(IAudioSessionNotification* this, IAudioSessionControl* pNewSessionControl)
|
|
{
|
|
printf("\nNew session created");
|
|
|
|
// First thing is to add a ref to the control interface so it isn't released by the system
|
|
pNewSessionControl->lpVtbl->AddRef(pNewSessionControl);
|
|
|
|
// Add the new session to the array of IAudioSessionControl interfaces
|
|
// A pointer to pointer to the array is stored in the interface, along with a pointer to the number of current interfaces
|
|
// Cast IAudioSessionNotification to my implementation to access those variables
|
|
myIAudioSessionNotification* pCastInterface = (myIAudioSessionNotification*)this;
|
|
// ppCurrentInterfacesAddress is a pointer to the array of interface pointers
|
|
IAudioSessionControl ** ppCurrentInterfacesAddress = *(pCastInterface->pppAudioSessionControlInterfaces);
|
|
// The number of currently stored IAudioSessionControl interfaces
|
|
int numberOfInterfaces = *pCastInterface->pNumberAudioSessionControls;
|
|
|
|
// This is a pointer to the first element of the array of pointers to session control objects
|
|
IAudioSessionControl** pNewArray = NULL;
|
|
|
|
// Realloc memory for the new pointer
|
|
if (numberOfInterfaces)
|
|
{
|
|
pNewArray = (IAudioSessionControl**)realloc(ppCurrentInterfacesAddress, sizeof(IAudioSessionControl*) * (numberOfInterfaces + 1));
|
|
}
|
|
|
|
if (!pNewArray)
|
|
{
|
|
// Realloc has failed, have to use malloc and memcpy
|
|
pNewArray = (IAudioSessionControl **) malloc(sizeof(IAudioSessionControl*) * (numberOfInterfaces + 1));
|
|
|
|
if (!pNewArray)
|
|
{
|
|
printf("\nNot able to allocate new memory for array of control interfaces.");
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Copy the contents of the array (pointers to control interfaces) to the new memory location
|
|
memcpy(pNewArray, ppCurrentInterfacesAddress, sizeof(IAudioSessionControl*) * numberOfInterfaces);
|
|
}
|
|
|
|
// At this point the memory has been allocated through realloc or malloc and the last pointer needs to be added to the array at the final location
|
|
*(pNewArray + numberOfInterfaces) = pNewSessionControl;
|
|
|
|
// Send the pointer to the new array back up the chain so it is seen by the main program thread
|
|
*(pCastInterface->pppAudioSessionControlInterfaces) = pNewArray;
|
|
|
|
// Increment the number of interfaces and send it back up the chain ready for the next one.
|
|
*(pCastInterface->pNumberAudioSessionControls) = numberOfInterfaces + 1;
|
|
|
|
// The new IAudioSessionControl interface should now have been appended to the array
|
|
// Final step is to register the sesssion events
|
|
IAudioSessionEvents AudioSessionEvents;
|
|
//InitializeAudioSessionEvents(&AudioSessionEvents, pNewSessionControl, pSessionInformation->AudioSessionControlsCollection);
|
|
|
|
return S_OK;
|
|
} |