190 lines
6.1 KiB
C
190 lines
6.1 KiB
C
#include "IAudioSessionEvents.h"
|
|
|
|
static IAudioSessionEventsVtbl* pvtbl = NULL;
|
|
static HRESULT CreateVTBL(void);
|
|
|
|
|
|
// Creates a session events interface and gives it the relevant information
|
|
HRESULT InitializeAudioSessionEvents(myIAudioSessionEvents** this, IAudioSessionControl * pParentInterface, IAudioSessionControl *** pControlInterfaceArrayAddress)
|
|
{
|
|
// If the vtbl of all the events functions hasn't already been created then make it now
|
|
// Return the error from the vtbl creation if there is a problem
|
|
HRESULT result = S_OK;
|
|
if (!pvtbl) result = CreateVTBL();
|
|
if (result) return result;
|
|
|
|
// The VTBL is constant for all events interfaces
|
|
// There are different interfaces with different parent interfaces and refernce numbers
|
|
//Assign memory for the events struct. Cast the pointer returned from malloc to the correct type
|
|
myIAudioSessionEvents* AudioSessionEvents;
|
|
AudioSessionEvents = (myIAudioSessionEvents*) malloc(sizeof(myIAudioSessionEvents));
|
|
//printf("\nMalloc: %p", AudioSessionEvents);
|
|
if (!AudioSessionEvents)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Add the virtual table to the strut
|
|
AudioSessionEvents->lpVtbl = pvtbl;
|
|
AudioSessionEvents->cRef = 0;
|
|
AudioSessionEvents->pParentAudioSessionControl = pParentInterface;
|
|
AudioSessionEvents->pControlInterfaceArrayAddress = pControlInterfaceArrayAddress;
|
|
|
|
*this = AudioSessionEvents;
|
|
//printf("\nSession events: %p", *this);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CreateVTBL(void)
|
|
{
|
|
// 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
|
|
pvtbl = malloc(sizeof(IAudioSessionEventsVtbl));
|
|
|
|
if (!pvtbl)
|
|
{
|
|
// If the vtable memory cannot be assigned
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// Asign all the functions
|
|
pvtbl->AddRef = (*IAudioSessionEventsAddRef);
|
|
pvtbl->QueryInterface = (*IAudioSessionEventsQueryInterface);
|
|
pvtbl->Release = (*IAudioSessionEventsRelease);
|
|
pvtbl->OnChannelVolumeChanged = (*IAudioSessionEventsOnChannelVolumeChanged);
|
|
pvtbl->OnDisplayNameChanged = (*IAudioSessionEventsOnDisplayNameChanged);
|
|
pvtbl->OnGroupingParamChanged = (*IAudioSessionEventsOnGroupingParamChanged);
|
|
pvtbl->OnIconPathChanged = (*IAudioSessionEventsOnIconPathChanged);
|
|
pvtbl->OnSessionDisconnected = (*IAudioSessionEventsOnSessionDisconnected);
|
|
pvtbl->OnSimpleVolumeChanged = (*IAudioSessionEventsOnSimpleVolumeChanged);
|
|
pvtbl->OnStateChanged = (*IAudioSessionEventsOnStateChanged);
|
|
//printf("\nEvents VTBL at %p", pvtbl);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE IAudioSessionEventsQueryInterface(IAudioSessionEvents* this, REFIID riid, void** ppvoid)
|
|
{
|
|
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 IAudioSessionEventsAddRef(IAudioSessionEvents* this)
|
|
{
|
|
// Cast the standard interface to my interface to allow access to cRef
|
|
myIAudioSessionEvents* castInterface = (myIAudioSessionEvents*)this;
|
|
|
|
return InterlockedIncrement(&castInterface->cRef);
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE IAudioSessionEventsRelease(IAudioSessionEvents* this)
|
|
{
|
|
// Cast the standard interface to my interface to allow access to cRef
|
|
myIAudioSessionEvents* castInterface = (myIAudioSessionEvents*)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;
|
|
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnChannelVolumeChanged(IAudioSessionEvents* this, DWORD ChannelCount, float* NewChannelVolumeArray, DWORD ChangedChannel, LPCGUID EventContext)
|
|
{
|
|
printf("\nChannel %d volume changed to %f.3", ChangedChannel, NewChannelVolumeArray[ChangedChannel]);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnDisplayNameChanged(IAudioSessionEvents* this, LPCWSTR NewDisplayName, LPCGUID EventContext)
|
|
{
|
|
printf("\nNew session display name: %ws", NewDisplayName);
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnGroupingParamChanged(IAudioSessionEvents* this, LPCGUID NewGroupingParam, LPCGUID EventContext)
|
|
{
|
|
printf("\nNew grouping param");
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnIconPathChanged(IAudioSessionEvents* this, LPCWSTR NewIconPath, LPCGUID EventContext)
|
|
{
|
|
printf("\nNew icon path");
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnSessionDisconnected(IAudioSessionEvents* this, AudioSessionDisconnectReason DisconnectReason)
|
|
{
|
|
myIAudioSessionEvents* castInterface = (myIAudioSessionEvents*)this;
|
|
printf("\nSession with control interface at %p disconnected.", castInterface->pParentAudioSessionControl);
|
|
|
|
// Delete the unused control interface from the array of interfaces
|
|
// It seems like the session is not disconnected generally, instead it is marked as inactive and IAudioSessionEventsOnStateChanged() is called
|
|
// Seems like the best option would be to have the control interface deleted and released when that is called and then just a confirmation when this function is called
|
|
// Supposedly releasing the interface in the state change callback should make this unnecessary but just in case I think it is worth doing
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnSimpleVolumeChanged(IAudioSessionEvents* this, float NewVolume, BOOL NewMute, LPCGUID EventContext)
|
|
{
|
|
printf("\nSession simple volume changed to %f. Session is ", NewVolume);
|
|
if (NewMute) printf("muted");
|
|
else printf("ummuted");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT IAudioSessionEventsOnStateChanged(IAudioSessionEvents* this, AudioSessionState NewState)
|
|
{
|
|
printf("\nSession state changed to ");
|
|
switch (NewState)
|
|
{
|
|
case(2):
|
|
printf("Expired");
|
|
break;
|
|
case(1):
|
|
printf("Active");
|
|
break;
|
|
case(0):
|
|
printf("Inactive");
|
|
break;
|
|
default:
|
|
printf("Unknown");
|
|
break;
|
|
}
|
|
return S_OK;
|
|
|
|
}
|
|
|