First commit

This commit is contained in:
Thomas Wilkie 2023-09-15 16:31:30 +09:00
commit cd2cc84f53
16 changed files with 1063 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
x64/
.vs/

72
AudioSessionEvents.c Normal file
View File

@ -0,0 +1,72 @@
#include "AudioSessionEvents.h"
HRESULT QueryInterface(IAudioSessionEvents* this)
{
printf("IAudioSessionEvents->lpVtbl->QueryInterface()\n");
return S_OK;
}
ULONG STDMETHODCALLTYPE Release(IAudioSessionEvents * this)
{
printf("IAudioSesssionEvents->lpVtbl-Release()\n");
return S_OK;
/*
ULONG ulRef = InterlockedDecrement(&this->m_cRefAll);
if (0 == ulRef)
{
free(this);
//TODO "delete" is from C++, what is it's equivalent in C?
//delete this;
}
return ulRef;
*/
}
ULONG STDMETHODCALLTYPE AddRef(IAudioSessionEvents * this)
{
printf("IAudioSessionEvents->lpVtbl->AddRef()\n");
return S_OK;
//return InterlockedIncrement(&this->m_cRefAll);
}
HRESULT OnChannelVolumeChanged(IAudioSessionEvents* this, DWORD ChannelCount, float* NewChannelVolumeArray, DWORD ChangedChannel, LPCGUID EventContext)
{
printf("IAudioSessionEvents->lpVtbl->OnChannelVolumeChanged()\n");
return S_OK;
}
HRESULT OnDisplayNameChanged(IAudioSessionEvents* this, LPCWSTR NewDisplayName, LPCGUID EventContext)
{
printf("IAudioSessionEvents->lpVtbl->OnDisplayNameChanged()\n");
return S_OK;
}
HRESULT OnGroupingParamChanged(IAudioSessionEvents* this, LPCGUID NewGroupingParam, LPCGUID EventContext)
{
printf("IAudioSessionEvents->lpVtbl->OnGroupingParamChanged()\n");
return S_OK;
}
HRESULT OnIconPathChanged(IAudioSessionEvents* this, LPCWSTR NewIconPath, LPCGUID EventContext)
{
printf("IAudioSessionEvents->lpVtbl->OnIconPathChanged()\n");
return S_OK;
}
HRESULT OnSessionDisconnected(IAudioSessionEvents* this, AudioSessionDisconnectReason DisconnectReason)
{
printf("IAudioSessionEvents->lpVtbl->OnSessionDisconnected()\n");
return S_OK;
}
HRESULT OnSimpleVolumeChanged(IAudioSessionEvents* this, float NewVolume, BOOL NewMute, LPCGUID EventContext)
{
printf("IAudioSessionEvents->lpVtbl->OnSimpleVolumeChanged()\n");
return S_OK;
}
HRESULT OnStateChanged(IAudioSessionEvents* this, AudioSessionState NewState)
{
printf("IAudioSessionEvents->lpVtbl->OnStateChanged()\n");
return S_OK;
}

113
AudioSessionEvents.h Normal file
View File

@ -0,0 +1,113 @@
#ifndef _AUDIOSESSIONECENTS_H_
#define _AUDIOSESSIONECENTS_H_
#include <combaseapi.h>
#include <audiopolicy.h>
#include <cstdbool>
#include <stdio.h>
#ifndef __IAudioSessionEvents_FWD_DEFINED__
#define __IAudioSessionEvents_FWD_DEFINED__
typedef interface IAudioSessionEvents IAudioSessionEvents;
#endif /* __IAudioSessionEvents_FWD_DEFINED__ */
HRESULT STDMETHODCALLTYPE QueryInterface(IAudioSessionNotification*, REFIID, void**);
ULONG STDMETHODCALLTYPE AddRef(IAudioSessionEvents*);
ULONG STDMETHODCALLTYPE Release(IAudioSessionEvents*);
HRESULT OnChannelVolumeChanged(IAudioSessionEvents*, DWORD, float*, DWORD, LPCGUID);
HRESULT OnDisplayNameChanged(IAudioSessionEvents*, LPCWSTR, LPCGUID);
HRESULT OnGroupingParamChanged(IAudioSessionEvents*, LPCGUID, LPCGUID);
HRESULT OnIconPathChanged(IAudioSessionEvents*, LPCWSTR, LPCGUID);
HRESULT OnSessionDisconnected(IAudioSessionEvents*, AudioSessionDisconnectReason);
HRESULT OnSimpleVolumeChanged(IAudioSessionEvents*, float, BOOL, LPCGUID);
HRESULT OnStateChanged(IAudioSessionEvents*, AudioSessionState);
typedef struct IAudioSessionEventsVtbl
{
BEGIN_INTERFACE
DECLSPEC_XFGVIRT(IUnknown, QueryInterface)
HRESULT(STDMETHODCALLTYPE* QueryInterface)(
IAudioSessionEvents* This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void** ppvObject);
DECLSPEC_XFGVIRT(IUnknown, AddRef)
ULONG(STDMETHODCALLTYPE* AddRef)(
IAudioSessionEvents* This);
DECLSPEC_XFGVIRT(IUnknown, Release)
ULONG(STDMETHODCALLTYPE* Release)(
IAudioSessionEvents* This);
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnChannelVolumeChange)
HRESULT(STDMETHODCALLTYPE* OnChannelVolumeChange)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ DWORD ChannelCount,
/* [annotation][in] */
_In_ float* NewChannelVolumeArray,
/* [annotation][in] */
_In_ DWORD ChangedChannel,
/* [annotation][in] */
_In_ LPCGUID EventContext );
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnDisplayNameChanged)
HRESULT(STDMETHODCALLTYPE* OnDisplayNameChanged)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ LPCWSTR NewDisplayName,
/* [annotation][in] */
_In_ LPCGUID EventContext);
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnGroupingParamChanged)
HRESULT(STDMETHODCALLTYPE* OnGroupingParamChanged)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ LPCGUID NewGroupingParam,
/* [annotation][in] */
_In_ LPCGUID EventContext);
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnIconPathChanged)
HRESULT(STDMETHODCALLTYPE* OnIconPathChanged)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ LPCWSTR NewIconPath,
/* [annotation][in] */
_In_ LPCGUID EventContext);
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnSessionDisconnected)
HRESULT(STDMETHODCALLTYPE* OnSessionDisconnected)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ AudioSessionDisconnectReason DisconnectReason );
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnSimpleVolumeChanged)
HRESULT(STDMETHODCALLTYPE* OnSimpleVolumeChanged)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ float NewVolume,
/* [annotation][in] */
_In_ BOOL NewMute,
/* [annotation][in] */
_In_ LPCGUID EventContext );
DECLSPEC_XFGVIRT(IAudioSessionEvents, OnStateChanged)
HRESULT(STDMETHODCALLTYPE* OnStateChanged)(
IAudioSessionEvents* This,
/* [annotation][in] */
_In_ AudioSessionState NewState );
END_INTERFACE
} IAudioSessionEventsVtbl;
interface IAudioSessionEvents
{
CONST_VTBL struct IAudioSessionEventsVtbl* lpVtbl;
LONG m_cRefAll;
};
#endif

27
CLSIDs_and_IIDs.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef _CLSIDS_AND_IIDS_H_
#define _CLSIDS_AND_IIDS_H_
// For whatever reason IID's and CLSID's are not easily accessible with C, C++ can use __uuidof() or something.
// I am unclear on wht the proper fix is supposed to be but this works to fix the LNK2001 error for underfined externals
//#include <initguid.h>
//BCDE0395-E52F-467C-8E3D-C4579291692E
const CLSID CLSID_MMDeviceEnumerator = { 0xBCDE0395, 0xE52F, 0x467C, { 0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E } };
//const IID IID_IMMDeviceEnumerator= {0xA95664D, 0x9614, 0x4F35, 0xA746, 0xDE8DB63617E6};
//A95664D2-9614-4F35-A746-DE8DB63617E6
const IID IID_IMMDeviceEnumerator = { 0xA95664D2, 0x9614, 0x4F35, { 0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6 } };
//BFA971F1-4D5E-40BB-935E-967039BFBEE4
const IID IID_IAudioSessionManager = { 0xBFA971F1, 0x4D5E, 0x40BB, { 0x93, 0x5E, 0x96, 0x70, 0x39, 0xBF, 0xBE, 0xE4 } };
//1CB9AD4C-DBFA-4c32-B178-C2F568A703B2
const IID IID_IAudioClient = { 0x1CB9AD4C, 0xDBFA, 0x4C32, { 0xB1, 0x78, 0xC2, 0xF5, 0x68, 0xA7, 0x03, 0xB2 } };
//F4B1A599-7266-4319-A8CA-E70ACB11E8CD
const IID IID_IAudioSessionControl = { 0xF4B1A599, 0x7266, 0x4319, { 0xA8, 0xCA, 0xE7, 0x0A, 0xCB, 0x11, 0xE8, 0xCD } };
//5CDF2C82 - 841E-4546 - 9722 - 0CF74078229A
const IID IID_IAudioEndpointVolume = { 0x5CDF2C82, 0x841E, 0x4546, { 0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A } };
//77AA99A0 - 1BD6 - 484F - 8BC7 - 2C654C9A9B6F
const IID IID_IAudioSessionManager2 = { 0x77AA99A0, 0x1BD6, 0x484F, { 0x8B, 0xC7, 0x2C, 0x65, 0x4C, 0x9A, 0x9B, 0x6F } };
//BFB7FF88-7239-4FC9-8FA2-07C950BE9C6D
const IID IID_IAudioSessionControl2 = { 0xBFB7FF88, 0x7239, 0x4FC9, {0x8F, 0xA2, 0x07, 0xC9, 0x50, 0xBE, 0x9C, 0x6D } };
//641DD20B - 4D41 - 49CC - ABA3 - 174B9477BB08
const IID IID_IAudioSessionNotification = { 0x641DD20B, 0x4D41, 0x49CC, { 0xAB, 0xA3, 0x17, 0x4B, 0x94, 0x77, 0xBB, 0x08 } };
#endif

149
IAudioSessionEvents.c Normal file
View File

@ -0,0 +1,149 @@
#include "IAudioSessionEvents.h"
HRESULT InitializeAudioSessionEvents(IAudioSessionEvents** this)
{
// 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
IAudioSessionEventsVtbl* vtbl = malloc(sizeof(IAudioSessionEventsVtbl));
if (!vtbl)
{
// If the vtable memory cannot be assigned
return E_OUTOFMEMORY;
}
// Asign all the functions
vtbl->AddRef = (*IAudioSessionEventsAddRef);
vtbl->QueryInterface = (*IAudioSessionEventsQueryInterface);
vtbl->Release = (*IAudioSessionEventsRelease);
vtbl->OnChannelVolumeChanged = (*IAudioSessionEventsOnChannelVolumeChanged);
vtbl->OnDisplayNameChanged = (*IAudioSessionEventsOnDisplayNameChanged);
vtbl->OnGroupingParamChanged = (*IAudioSessionEventsOnGroupingParamChanged);
vtbl->OnIconPathChanged = (*IAudioSessionEventsOnIconPathChanged);
vtbl->OnSessionDisconnected = (*IAudioSessionEventsOnSessionDisconnected);
vtbl->OnSimpleVolumeChanged = (*IAudioSessionEventsOnSimpleVolumeChanged);
vtbl->OnStateChanged = (*IAudioSessionEventsOnStateChanged);
//Assign memory for the notifications struct. Cast the pointer returned from malloc to the correct type ??
myIAudioSessionEvents* AudioSessionEvents;
AudioSessionEvents = (myIAudioSessionEvents*) malloc(sizeof(myIAudioSessionEvents));
if (!AudioSessionEvents)
{
// If the struct memory cannot be assigned free the memory previously assigned to the vtable and return
free(vtbl);
return E_OUTOFMEMORY;
}
// Add the virtual table to the strut
AudioSessionEvents->lpVtbl = vtbl;
AudioSessionEvents->cRef = 0;
// Update the pointer address passed into the function
*this = (*IAudioSessionEvents) AudioSessionEvents;
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 &ld 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)
{
printf("\nSession disconnect reason &d", (int) DisconnectReason);
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");
return S_OK;
}

37
IAudioSessionEvents.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef _IAUDIOSESSIONEVENTS_H_
#define _IAUDIOSESSIONEVENTS_H_
#include <combaseapi.h>
#include <audiopolicy.h>
#include <stdio.h>
#include <Windows.h>
#ifndef __myIAudioSessionEvents_FWD_DEFINED__
#define __myIAudioSessionEvents_FWD_DEFINED__
typedef interface myIAudioSessionEvents myIAudioSessionEvents;
#endif /* __myIAudioSessionEvents_FWD_DEFINED__ */
HRESULT InitializeAudioSessionEvents(IAudioSessionEvents**);
HRESULT STDMETHODCALLTYPE IAudioSessionEventsQueryInterface(IAudioSessionEvents*, REFIID, void**);
ULONG STDMETHODCALLTYPE IAudioSessionEventsAddRef(IAudioSessionEvents*);
ULONG STDMETHODCALLTYPE IAudioSessionEventsRelease(IAudioSessionEvents*);
HRESULT IAudioSessionEventsOnChannelVolumeChanged(IAudioSessionEvents*, DWORD, float*,DWORD, LPCGUID);
HRESULT IAudioSessionEventsOnDisplayNameChanged(IAudioSessionEvents*, LPCWSTR, LPCGUID);
HRESULT IAudioSessionEventsOnGroupingParamChanged(IAudioSessionEvents*, LPCGUID, LPCGUID);
HRESULT IAudioSessionEventsOnIconPathChanged(IAudioSessionEvents*, LPCWSTR, LPCGUID);
HRESULT IAudioSessionEventsOnSessionDisconnected(IAudioSessionEvents*, AudioSessionDisconnectReason);
HRESULT IAudioSessionEventsOnSimpleVolumeChanged(IAudioSessionEvents*, float, BOOL, LPCGUID);
HRESULT IAudioSessionEventsOnStateChanged(IAudioSessionEvents*, AudioSessionState);
interface myIAudioSessionEvents
{
CONST_VTBL struct IAudioSessionEventsVtbl* lpVtbl;
ULONG cRef;
};
#endif

169
IAudioSessionNotification.c Normal file
View File

@ -0,0 +1,169 @@
#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* vtbl = malloc(sizeof(IAudioSessionNotificationVtbl));
if (!vtbl)
{
// If the vtable memory cannot be assigned
return E_OUTOFMEMORY;
}
// Asign all the functions
vtbl->AddRef = (*IAudioSessionNotificationAddRef);
vtbl->OnSessionCreated = (*IAudioSessionNotificationOnSessionCreated);
vtbl->QueryInterface = (*IAudioSessionNotificationQueryInterface);
vtbl->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(vtbl);
return E_OUTOFMEMORY;
}
// Add the virtual table to the strut
AudioSessionNotification->lpVtbl = vtbl;
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* pNewSession)
{
printf("\nNew session created");
// Simpler version with fixed size array of pointers declared in the main thread and put onto the stack.
myIAudioSessionNotification* castInterface = (myIAudioSessionNotification*)this;
int numberInterfaces = *(castInterface->pNumberAudioSessionControls);
IAudioSessionControl ** audioSessionControlArray = castInterface->pppAudioSessionControlInterfaces + numberInterfaces;
*audioSessionControlArray = pNewSession;
*(castInterface->pNumberAudioSessionControls) = numberInterfaces + 1;
return S_OK;
/*
*
* This is using realloc and malloc to dynamically change the size of the array of pointers to interfaces.
* It doesn't work, I don't know why at this point.
*
// 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;
if (numberOfInterfaces)
{
printf("");
}
// 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) = pNewSession;
// 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
return S_OK;
*/
}

View File

@ -0,0 +1,32 @@
#ifndef _IAUDIOSESSIONNOTIFICATION_H_
#define _IAUDIOSESSIONNOTIFICATION_H_
#include <combaseapi.h>
#include <audiopolicy.h>
#include <stdio.h>
#include <Windows.h>
#ifndef __myIAudioSessionNotification_FWD_DEFINED__
#define __myIAudioSessionNotification_FWD_DEFINED__
typedef interface myIAudioSessionNotification myIAudioSessionNotification;
#endif /* __myIAudioSessionNotification_FWD_DEFINED__ */
HRESULT STDMETHODCALLTYPE IAudioSessionNotificationQueryInterface(IAudioSessionNotification*, REFIID, void**);
ULONG STDMETHODCALLTYPE IAudioSessionNotificationAddRef(IAudioSessionNotification*);
ULONG STDMETHODCALLTYPE IAudioSessionNotificationRelease(IAudioSessionNotification*);
HRESULT IAudioSessionNotificationOnSessionCreated(IAudioSessionNotification*, IAudioSessionControl*);
//HRESULT InitializeAudioSessionNotification(IAudioSessionNotification**, IAudioSessionControl***, int*);
HRESULT InitializeAudioSessionNotification(IAudioSessionNotification**, IAudioSessionControl***, int*);
interface myIAudioSessionNotification
{
CONST_VTBL struct IAudioSessionNotificationVtbl* lpVtbl;
ULONG cRef;
const IAudioSessionControl *** pppAudioSessionControlInterfaces;
int * pNumberAudioSessionControls;
};
#endif

0
IUknownInterface.c Normal file
View File

55
IUknownInterface.cpp Normal file
View File

@ -0,0 +1,55 @@
#include "IUknownInterface.h"
class CSessionNotifications : public IAudioSessionNotification
{
private:
LONG m_cRefAll;
HWND m_hwndMain;
~CSessionManager() {};
public:
CSessionManager(HWND hWnd) :
m_cRefAll(1),
m_hwndMain(hWnd)
{}
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppv)
{
if (IID_IUnknown == riid)
{
AddRef();
*ppvInterface = (IUnknown*)this;
}
else if (__uuidof(IAudioSessionNotification) == riid)
{
AddRef();
*ppvInterface = (IAudioSessionNotification*)this;
}
else
{
*ppvInterface = NULL;
return E_NOINTERFACE;
}
return S_OK;
}
ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&m_cRefAll);
}
ULONG STDMETHODCALLTYPE Release)()
{
ULONG ulRef = InterlockedDecrement(&m_cRefAll);
if (0 == ulRef)
{
delete this;
}
return ulRef;
}
HRESULT OnSessionCreated(IAudioSessionControl* pNewSession)
{
if (pNewSession)
{
PostMessage(m_hwndMain, WM_SESSION_CREATED, 0, 0);
}
}
};

1
IUknownInterface.h Normal file
View File

@ -0,0 +1 @@
#pragma once

View File

@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.6.33801.468
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WASAPI Notification Interfaces", "WASAPI Notification Interfaces.vcxproj", "{46D8D311-8E84-468E-B7EA-7699443913BA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{46D8D311-8E84-468E-B7EA-7699443913BA}.Debug|x64.ActiveCfg = Debug|x64
{46D8D311-8E84-468E-B7EA-7699443913BA}.Debug|x64.Build.0 = Debug|x64
{46D8D311-8E84-468E-B7EA-7699443913BA}.Debug|x86.ActiveCfg = Debug|Win32
{46D8D311-8E84-468E-B7EA-7699443913BA}.Debug|x86.Build.0 = Debug|Win32
{46D8D311-8E84-468E-B7EA-7699443913BA}.Release|x64.ActiveCfg = Release|x64
{46D8D311-8E84-468E-B7EA-7699443913BA}.Release|x64.Build.0 = Release|x64
{46D8D311-8E84-468E-B7EA-7699443913BA}.Release|x86.ActiveCfg = Release|Win32
{46D8D311-8E84-468E-B7EA-7699443913BA}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F3927660-367F-4C60-8E0E-964E87EF9716}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{46d8d311-8e84-468e-b7ea-7699443913ba}</ProjectGuid>
<RootNamespace>WASAPINotificationInterfaces</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="IAudioSessionNotification.c" />
<ClCompile Include="main.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="IAudioSessionNotification.h" />
<ClInclude Include="CLSIDs_and_IIDs.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IAudioSessionNotification.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CLSIDs_and_IIDs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IAudioSessionNotification.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ShowAllFiles>false</ShowAllFiles>
</PropertyGroup>
</Project>

196
main.c Normal file
View File

@ -0,0 +1,196 @@
#include <stdio.h>
#include <Windows.h>
#include "CLSIDs_and_IIDs.h"
#include <combaseapi.h>
#include <mmdeviceapi.h>
#include <audiopolicy.h>
#include"IAudioSessionNotification.h"
void printLoadingTicker( void );
// This expects HRESULT from the function to be called result
//#define checkHRESULT(func) if((func) != S_OK) printf("\nError on line %d of %s. Result value is %lx.\n", __LINE__, __FILE__, result);
#define checkHRESULT if(result != S_OK) printf("\nError on line %d of %s. Result value is %lx.\n", __LINE__ - 1, __FILE__, result);
int main(void)
{
printf("Compiled %s", __TIME__);
printf("\nStarting");
HRESULT result = 1;
result = CoInitializeEx(NULL, COINIT_MULTITHREADED);
//result = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
checkHRESULT;
// Have a look at this at a later date
//checkHRESULT(CoInitializeEx(NULL, COINIT_MULTITHREADED));
IAudioSessionControl* AudioSessionControls[10];
// I can't seem to get this to work dynamically assigning the memory
//IAudioSessionControl** AudioSessionControls;
int numberSessionControls = 0;
while (1)
{
IMMDeviceEnumerator* myIMMDeviceEnumerator = NULL;
result = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, &IID_IMMDeviceEnumerator, &myIMMDeviceEnumerator);
checkHRESULT;
IMMDevice* myIMMDevice;
myIMMDeviceEnumerator->lpVtbl->GetDefaultAudioEndpoint(myIMMDeviceEnumerator, eRender, eMultimedia, &myIMMDevice);
checkHRESULT;
IAudioSessionManager2* myAudioSessionManager2 = NULL;
result = myIMMDevice->lpVtbl->Activate(myIMMDevice, &IID_IAudioSessionManager2, CLSCTX_ALL, NULL, &myAudioSessionManager2);
checkHRESULT;
IAudioSessionEnumerator* myAudioSessionEnumerator;
result = myAudioSessionManager2->lpVtbl->GetSessionEnumerator(myAudioSessionManager2, &myAudioSessionEnumerator);
checkHRESULT;
int sessions;
result = myAudioSessionEnumerator->lpVtbl->GetCount(myAudioSessionEnumerator, &sessions);
checkHRESULT;
IAudioSessionNotification* myAudioSessionNotification;
result = InitializeAudioSessionNotification(&myAudioSessionNotification, &AudioSessionControls, &numberSessionControls);
checkHRESULT;
result = myAudioSessionManager2->lpVtbl->RegisterSessionNotification(myAudioSessionManager2, myAudioSessionNotification);
checkHRESULT;
int i = 0;
int newSessionCount = 0;
while (1)
{
Sleep(50);
//printLoadingTicker();
i++;
if (i > 20000)
{
break;
}
if (newSessionCount != numberSessionControls)
{
printf("\nNew Session control added");
newSessionCount = numberSessionControls;
for (int ii = 0; ii < numberSessionControls; ii++)
{
IAudioSessionControl * ActiveSessionControl = *(AudioSessionControls + ii);
LPWSTR iconPath;
result = ActiveSessionControl->lpVtbl->GetIconPath(ActiveSessionControl, &iconPath);
printf("\nSession iconPath = %ls", iconPath);
IAudioSessionControl2* myAudioSessionControl2;
result = ActiveSessionControl->lpVtbl->QueryInterface(ActiveSessionControl, &IID_IAudioSessionControl2, &myAudioSessionControl2);
checkHRESULT;
DWORD processID = 0;
result = myAudioSessionControl2->lpVtbl->GetProcessId(myAudioSessionControl2, &processID);
checkHRESULT;
printf("Process ID of control instance %d is %d", ii, processID);
}
}
}
// The session manager notification unregister function also calls release on the audio session notification interface
result = myAudioSessionManager2->lpVtbl->UnregisterSessionNotification(myAudioSessionManager2, myAudioSessionNotification);
checkHRESULT;
myAudioSessionManager2->lpVtbl->Release(myAudioSessionManager2);
myAudioSessionEnumerator->lpVtbl->Release(myAudioSessionEnumerator);
myIMMDevice->lpVtbl->Release(myIMMDevice);
//printf("\rNext \n");
}
printf("\nFinished");
return S_OK;
}
void printLoadingTicker(void)
{
static count = 0;
char loadChar = ' ';
switch (count % 8)
{
case(0):
loadChar = '|';
break;
case(1):
loadChar = '/';
break;
case(2):
loadChar = '-';
break;
case(3):
loadChar = '\\';
break;
case(4):
loadChar = '|';
break;
case(5):
loadChar = '/';
break;
case(6):
loadChar = '-';
break;
case(7):
loadChar = '\\';
break;
default:
break;
}
printf("Checking for new sessions [%c]\r", loadChar);
count++;
return;
}
/*
HRESULT checkSessions(IAudioSessionManager2* myAudioSessionManager2)
{
static int sessionCount = 0;
// Gets a new enumerator object with all the sessions
IAudioSessionEnumerator* myAudioSessionEnumerator;
HRESULT result = myAudioSessionManager2->lpVtbl->GetSessionEnumerator(myAudioSessionManager2, &myAudioSessionEnumerator);
// Checks how many sessions there are now
int newSessionCount = -1;
result = myAudioSessionEnumerator->lpVtbl->GetCount(myAudioSessionEnumerator, &newSessionCount);
if (newSessionCount != sessionCount)
{
sessionCount = newSessionCount;
result = getNewSessions(sessionCount, &myAudioSessionEnumerator);
}
printLoadingTicker();
return S_OK;
}
HRESULT getNewSessions(int numberOfSessions, IAudioSessionEnumerator* myAudioSessionEnumerator)
{
for (int i = 0; i < numberOfSessions; i++)
{
IAudioSessionControl* myAudioSessionControl;
HRESULT result = myAudioSessionEnumerator->lpVtbl->GetSession(myAudioSessionEnumerator, i, &myAudioSessionControl);
IAudioSessionControl2* myAudioSessionControl2;
result = myAudioSessionControl->lpVtbl->QueryInterface(myAudioSessionControl, &IID_IAudioSessionControl2, CLSCTX_ALL, &myAudioSessionControl2);
}
return S_OK;
}
*/