From 9806f046bd03f0b542c4e96ea7ba90414a00ab6f Mon Sep 17 00:00:00 2001 From: Hane Date: Thu, 18 Jan 2024 22:25:44 +0100 Subject: [PATCH] fixed IAudioSessionControl2 invocation, modified README --- README.md | 93 +++++-------------------------------- graph.gv | 26 +++++++++++ output.svg | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++ testmain.cpp | 114 ++++++++------------------------------------- 4 files changed, 183 insertions(+), 178 deletions(-) create mode 100644 graph.gv create mode 100644 output.svg diff --git a/README.md b/README.md index ace9ddc..6858985 100644 --- a/README.md +++ b/README.md @@ -1,89 +1,18 @@ -# Atonsio -**enberda filipas con esta mierda**, eh. Increible que esto lo haya hecho alguien digno de ser big techie. +**Small prototype showing how to register as a COM application and reaching endpoint and session manipulation**. -Anyway, al caso: +# Class graph -``` -IMMDeviceEnumerator -| -| -| -| -| -IMMDeviceCollection -| -| -| -| -| -IMMDevice--------------------------------------| -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -| \ | -IMMEndpoint IAudioEndpointVolume IAudioSessionManager2 -(No demostrado) (Columen endpoint) (Manager de sesiones) - | - | - | - | - | - | - | - | - | - | - | - | - | - IAudioSessionEnumerator - (Handle de sesiones) - | - | - | - | - | - | - | - | - | - | - | - | - | - IAudioSessionControl2 - (Cast a padre, 1 x sesion) - | - | - | - | - | - | - | - | - | - | - | - | - | - ISimpleAudioVolume - (Via QueryInterface(), 1 x sesion ofc) -``` +![Test](output.svg) -Ezpz microsoft comeme los cojones +# Notes + + - Name might appear blank. This is not a bug, but rather an inconvenience due to the fact that many programs create unnamed sessions. Mixers, such as `SndVol` or mine, overcome this fact by fetching its parent process' name. # Build -llvm-mingw 06 2022: -clang++ testmain.cpp -o si.exe -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -L D:/Contenido/Capybara/llvm-mingw/x86_64-w64-mingw32/bin -L C:\capybara\libclang\x86_64-w64-mingw32\lib -l Ole32 -static -lc++ -lunwind --verbose \ No newline at end of file + - Built using `clang` using [**llvm-mingw UCRT 20220906**](https://github.com/mstorsjo/llvm-mingw/releases/tag/20220906). + +``` + clang++ testmain.cpp -o test.exe -Wall -Wextra -Wpedantic -std=c++11 -l Ole32 -static -lc++ -lunwind --verbose +``` \ No newline at end of file diff --git a/graph.gv b/graph.gv new file mode 100644 index 0000000..d961627 --- /dev/null +++ b/graph.gv @@ -0,0 +1,26 @@ +digraph coreaudiodemo { + fontname="Helvetica,Arial,sans-serif" + node [color=black, style=bold, fontname="Helvetica,Arial,sans-serif",shape="record"] + edge [color=blue, style=bold, fontname="Helvetica,Arial,sans-serif"] + + de [label=" class IMMDeviceEnumerator\n(Retrieves current endpoints)",labelloc=b]; + dc [label=" class IMMDeviceCollection\n(Endpoint collection)",labelloc=b]; + ie [label=" class IMMDevice (Deceitful name, actual endpoint)",labelloc=b]; + ieroutes [label=" class IMMEndpoint \n(Just Playback/Capture flag) + | class IAudioEndpointVolume \n(Endpoint volume/balance) + | class IAudioSessionManager \n(Entry point to endpoint's session management)",labelloc=b]; + iase [label=" class IAudioSessionEnumerator \n(Retrieves endpoint's current sessions)",labelloc=b]; + iasc [label=" class IAudioSessionControl \n(Used to call derived class)",labelloc=b]; + iasc2 [label=" class IAudioSessionControl2 \n(Session management. Called via `QueryInterface())",labelloc=b]; + isav [label=" class ISimpleAudioVolume \n(Session volume controls. Called via `QueryInterface())`",labelloc=b]; + + de -> dc; + dc -> ie; + ie -> ieroutes:p0 [label=""]; + ie -> ieroutes:p1; + ie -> ieroutes:p2; + ieroutes:p2 -> iase; + iase -> iasc; + iasc -> iasc2; + iasc2 -> isav; +} diff --git a/output.svg b/output.svg new file mode 100644 index 0000000..55bbb83 --- /dev/null +++ b/output.svg @@ -0,0 +1,128 @@ + + + + + + +coreaudiodemo + + + +de + +class IMMDeviceEnumerator +(Retrieves current endpoints) + + + +dc + +class IMMDeviceCollection +(Endpoint collection) + + + +de->dc + + + + + +ie + +class IMMDevice (Deceitful name, actual endpoint) + + + +dc->ie + + + + + +ieroutes + +class IMMEndpoint +(Just Playback/Capture flag) + +class IAudioEndpointVolume +(Endpoint volume/balance) + +class IAudioSessionManager +(Entry point to endpoint's session management) + + + +ie->ieroutes:p0 + + + + + +ie->ieroutes:p1 + + + + + +ie->ieroutes:p2 + + + + + +iase + +class IAudioSessionEnumerator +(Retrieves endpoint's current sessions) + + + +ieroutes:p2->iase + + + + + +iasc + +class IAudioSessionControl +(Used to call derived class) + + + +iase->iasc + + + + + +iasc2 + +class IAudioSessionControl2 +(Session management. Called via `QueryInterface()) + + + +iasc->iasc2 + + + + + +isav + +class ISimpleAudioVolume +(Session volume controls. Called via `QueryInterface())` + + + +iasc2->isav + + + + + diff --git a/testmain.cpp b/testmain.cpp index 3aba0f9..5b9f0c2 100644 --- a/testmain.cpp +++ b/testmain.cpp @@ -1,29 +1,17 @@ #define WIN32_LEAN_AND_MEAN -#include -#include - #include -#include #include #include #include #include #include - #include #include #include -//#include -//#include #include - -//#define EXIT_ON_ERROR(hres, className) \ - if (FAILED(hres)) { printf("%s\n", #className); goto Exit; } - - #define EXIT_ON_ERROR(hres) \ if (FAILED(hres)) { printf("%s - %d\n", __FILE__, __LINE__); goto Exit; } @@ -32,15 +20,6 @@ if ((punk) != NULL) \ { (punk)->Release(); (punk) = NULL; } -//#pragma once - -/* - * Comentarios patrocinados por David - * Enviar mensaje a @Phireh - */ - -// const IID IntID_IAudioEndpointVolume = __uuidof(IAudioEndpointVolume); - IMMDeviceEnumerator *deviceEnumeratorPtr = NULL; IMMDeviceCollection *deviceCollectionPtr = NULL; IMMDevice *endpointPtr = NULL; @@ -49,6 +28,7 @@ IAudioEndpointVolume *endpointVolumePtr = NULL; IAudioSessionManager2 *sessionManagerPtr = NULL; IAudioSessionEnumerator *sessionEnumeratorPtr = NULL; +IAudioSessionControl* sessionControlPtr = NULL; IAudioSessionControl2 *sessionControl2Ptr = NULL; ISimpleAudioVolume *sessionVolumePtr = NULL; @@ -68,22 +48,11 @@ void PrintEndpointNames() { (void**)&deviceEnumeratorPtr); EXIT_ON_ERROR(hr) - //hr = deviceEnumeratorPtr->EnumAudioEndpoints(eRender, DEVICE_STATE_&deviceCollectionPtr); + //hr = deviceEnumeratorPtr->EnumAudioEndpoints(eRender, DEVICE_STATE_&deviceCollectionPtr); << Elegimos a mano para ahorrar código de iteración //Llamar a dispositivo por defecto. 2o param no importa lmao hr = deviceEnumeratorPtr->GetDefaultAudioEndpoint(eRender, eConsole, &endpointPtr); EXIT_ON_ERROR(hr) - // UINT count; - // hr = deviceCollectionPtr->GetCount(&count); - // EXIT_ON_ERROR(hr) - - // if (count == 0) { - // printf("No endpoints found.\n"); - // } - - // hr = deviceCollectionPtr->Item(i, &endpointPtr); - // EXIT_ON_ERROR(hr) - //RECUPERAR ENDPOINT ID hr = endpointPtr->GetId(&endpointID); EXIT_ON_ERROR(hr) @@ -94,10 +63,10 @@ void PrintEndpointNames() { PROPVARIANT varName; - // Initialize container for property value. + // Inicializar el struct para poder extraer la información. PropVariantInit(&varName); - // Get the endpoint's friendly-name property. + // Cogemos el nombre humano hr = deviceEndpointPropertiesPtr->GetValue(PKEY_Device_FriendlyName , &varName); EXIT_ON_ERROR(hr) @@ -113,36 +82,34 @@ void PrintEndpointNames() { EXIT_ON_ERROR(hr); //Registramos el gestor de sesiones para conseguir el handle que da el handle de sesiones a nivel informativo - //Y justo despues, el que da control a nivel sonoro xdddddddddddddddddddddddddddddddddddddddddddddd + //Y justo despues, el que da control a nivel sonoro hr = endpointPtr->Activate(__uuidof(IAudioSessionManager2), CLSCTX_ALL, NULL, (void**) &sessionManagerPtr); EXIT_ON_ERROR(hr); - - //Ahora si viene el handle de las sesiones xdddddddddd + //Ahora si viene el handle de las sesiones hr = sessionManagerPtr->GetSessionEnumerator(&sessionEnumeratorPtr); EXIT_ON_ERROR(hr); - //Cogemos el numero de sesiones y recorremos para coger cada una - //Luego tho, que soy una puta vaga y hay que probar cositas + //Cogemos el numero de sesiones y recorreríamos para coger cada una. Aquí, se elige la 0 para, una vez más, no enmarañar el código. INT sessionCount; hr = sessionEnumeratorPtr->GetCount(&sessionCount); EXIT_ON_ERROR(hr); - hr = sessionEnumeratorPtr->GetSession(2, (IAudioSessionControl**)&sessionControl2Ptr); - EXIT_ON_ERROR(hr); - - LPWSTR sessionDisplayName; - hr = sessionControl2Ptr->GetDisplayName(&sessionDisplayName); + hr = sessionEnumeratorPtr->GetSession(0, (IAudioSessionControl**)&sessionControlPtr); EXIT_ON_ERROR(hr); + hr = sessionControlPtr->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl2Ptr); + EXIT_ON_ERROR(hr); + + //Puede que el nombre no se rellene. Esto se debe a que no todos los programas registran su sesión con un nombre humano. SndVol.exe se toma la libertad de pesquisar el nombre a través de los metadatos del ejecutable que la ha creado si es una aplicación Win32, y otro campo si es una aplicación .appx. + LPWSTR sessionDisplayName; + hr = sessionControl2Ptr->IsSystemSoundsSession(); + if(hr) + hr = sessionControl2Ptr->GetDisplayName(&sessionDisplayName); + else + sessionDisplayName = L"System Sounds"; printf("Sesion 0 de endpoint %S: \"%S\" \n Num sesiones: (%d)\n", varName.pwszVal, sessionDisplayName, sessionCount); - - //hr = sessionControlPtr->QueryInterface(__uuidof(IAudioSessionControl2), (void**)&sessionControl2Ptr); - //EXIT_ON_ERROR(hr); - - //hr = sessionControl2Ptr->GetProcessId(&foundProcessId); - //EXIT_ON_ERROR(hr); hr = sessionControl2Ptr->QueryInterface(__uuidof(ISimpleAudioVolume), (void**)&sessionVolumePtr); EXIT_ON_ERROR(hr); @@ -162,42 +129,7 @@ void PrintEndpointNames() { //SAFE_RELEASE(sessionControlPtr); SAFE_RELEASE(sessionControl2Ptr); SAFE_RELEASE(sessionVolumePtr); -/* - // Each loop prints the name of an endpoint device. - for (ULONG i = 0; i < count; i++) { - // Get pointer to endpoint number i. - hr = deviceCollectionPtr->Item(i, &endpointPtr); - EXIT_ON_ERROR(hr) - // Get the endpoint ID string. - hr = endpointPtr->GetId(&endpointID); - EXIT_ON_ERROR(hr) - - hr = endpointPtr->OpenPropertyStore(STGM_READ, &deviceEndpointPropertiesPtr); - EXIT_ON_ERROR(hr) - - PROPVARIANT varName; - // Initialize container for property value. - PropVariantInit(&varName); - - // Get the endpoint's friendly-name property.2 - hr = deviceEndpointPropertiesPtr->GetValue(PKEY_Device_FriendlyName , &varName); - EXIT_ON_ERROR(hr) - - // Print endpoint friendly name and endpoint ID. - printf("Endpoint %lu: \"%S\" (%S)\n", i, varName.pwszVal, endpointID); - - - - - - CoTaskMemFree(endpointID); - endpointID = NULL; - PropVariantClear(&varName); - SAFE_RELEASE(deviceEndpointPropertiesPtr) - SAFE_RELEASE(endpointPtr) - } -*/ SAFE_RELEASE(deviceEnumeratorPtr) SAFE_RELEASE(deviceCollectionPtr) return; @@ -212,16 +144,6 @@ Exit: CoUninitialize(); } -void onExit(){ - - - - - -} - - - int main (int argc, char* argv[]) { PrintEndpointNames(); }