WASAPI_Notification_Interfaces/IAudioSessionNotification.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;
}