Og & wip: names

This commit is contained in:
Hane 2024-08-06 09:45:25 +02:00
commit 42b30b1bf8
5 changed files with 227 additions and 28 deletions

View file

@ -1,4 +1,4 @@
QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview -Og
QMAKE_LFLAGS += --target=x86_64-w64-mingw32 -g -Wl,-pdb= -v QMAKE_LFLAGS += --target=x86_64-w64-mingw32 -g -Wl,-pdb= -v
LIBS += -LC:/capybara/libclang/x86_64-w64-mingw32/lib -lWinmm -lodbc32 -lodbccp32 -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32 -lpropsys -static -stdlib=libc++ -lunwind LIBS += -LC:/capybara/libclang/x86_64-w64-mingw32/lib -lWinmm -lodbc32 -lodbccp32 -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32 -lpropsys -static -stdlib=libc++ -lunwind
#"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32 #"kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" -luuid -loleaut32 -lole32 -lshell32 -ladvapi32 -lcomdlg32 -lwinspool -lgdi32 -luser32 -lkernel32

View file

@ -126,9 +126,12 @@ Session::Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx
else { else {
LPWSTR sessionDisplayName; LPWSTR sessionDisplayName;
this->sessionControl->GetDisplayName(&sessionDisplayName); this->sessionControl->GetDisplayName(&sessionDisplayName);
if (!wcscmp(sessionDisplayName, L"")) if (!wcscmp(sessionDisplayName, L"")) {
this->sessionName = this->fetchProcessName(pid); std::wstring exePath;
else if (getExePath(pid, &exePath))
fetchName(exePath, pid);
else this->sessionName = std::wstring(LSTRING_UNNAMED_SESSION);
} else
this->sessionName = std::wstring(sessionDisplayName); this->sessionName = std::wstring(sessionDisplayName);
CoTaskMemFree(sessionDisplayName); CoTaskMemFree(sessionDisplayName);
} }
@ -192,22 +195,20 @@ void Session::setMute(NGuid guid, bool muted) {
if(FAILED(sessionVolume->SetMute(muted, &tempMsGuid))) { log_wdebugcpp(std::wstring(L"SessionVolume null?")); }; if(FAILED(sessionVolume->SetMute(muted, &tempMsGuid))) { log_wdebugcpp(std::wstring(L"SessionVolume null?")); };
} }
std::wstring Session::fetchProcessName(DWORD pid) { bool Session::getExePath(DWORD pid, std::wstring *exePath) {
/* /*
* https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot * https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
* https://stackoverflow.com/questions/11843368/how-to-get-process-description * https://stackoverflow.com/questions/11843368/how-to-get-process-description
* https://notes.indezine.com/2018/05/microsoft-locale-ids.html#:~:text=Wait%2C%201033%20is%20the%20decimal,ID%20for%20English%20%E2%80%93%20United%20States. * https://notes.indezine.com/2018/05/microsoft-locale-ids.html#:~:text=Wait%2C%201033%20is%20the%20decimal,ID%20for%20English%20%E2%80%93%20United%20States.
* https://stackoverflow.com/questions/64321036/c-win32-getting-app-name-using-pid-and-executable-path * https://stackoverflow.com/questions/64321036/c-win32-getting-app-name-using-pid-and-executable-path
*/ */
/* Executable path retrieval */ //std::wstring msixName;
std::wstring exePath = L"";
std::wstring msixName;
HANDLE processList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid); HANDLE processList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
if (processList == INVALID_HANDLE_VALUE) { if (processList == INVALID_HANDLE_VALUE) {
log_wdebugcpp(L"aye no procname."); log_wdebugcpp(L"aye no procname.");
return exePath; return false;
} }
MODULEENTRY32W me32w; MODULEENTRY32W me32w;
@ -215,7 +216,7 @@ std::wstring Session::fetchProcessName(DWORD pid) {
if(Module32FirstW(processList, &me32w)) { if(Module32FirstW(processList, &me32w)) {
do { do {
if (me32w.th32ProcessID == pid) { if (me32w.th32ProcessID == pid) {
exePath = std::wstring(me32w.szExePath); *exePath = std::wstring(me32w.szExePath);
break; break;
/* /*
* However, if the calling process is a 32-bit process, you must call the * However, if the calling process is a 32-bit process, you must call the
@ -226,7 +227,10 @@ std::wstring Session::fetchProcessName(DWORD pid) {
} while(Module32NextW(processList, &me32w)); } while(Module32NextW(processList, &me32w));
} }
CloseHandle(processList); CloseHandle(processList);
return true;
}
bool Session::fetchNameViaFD(std::wstring exePath, DWORD pid, std::wstring *sessionName) {
/* File description retrieval: size and available lang-codepages */ /* File description retrieval: size and available lang-codepages */
struct LANGANDCODEPAGE { struct LANGANDCODEPAGE {
WORD wLanguage; WORD wLanguage;
@ -236,16 +240,16 @@ std::wstring Session::fetchProcessName(DWORD pid) {
DWORD filler; DWORD filler;
DWORD fileVersionInfoSize = GetFileVersionInfoSizeExW DWORD fileVersionInfoSize = GetFileVersionInfoSizeExW
(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, exePath.c_str(), &filler); (FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, exePath.c_str(), &filler);
if (!fileVersionInfoSize) return exePath; if (!fileVersionInfoSize) return false;
void* fileVersionInfo = malloc(fileVersionInfoSize); void* fileVersionInfo = malloc(fileVersionInfoSize);
if(!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, if(!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL,
exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo)) exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo))
return exePath; return false;
UINT translationArrayLen = 0; UINT translationArrayLen = 0;
if (!VerQueryValueW(fileVersionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayLen)) if (!VerQueryValueW(fileVersionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayLen))
return exePath; return false;
//File descriptor parsing //File descriptor parsing
//TODO: https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getuserpreferreduilanguages //TODO: https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-getuserpreferreduilanguages
@ -254,7 +258,7 @@ std::wstring Session::fetchProcessName(DWORD pid) {
* sysem is put in place, I'll come finish this up. * sysem is put in place, I'll come finish this up.
*/ */
uint64_t availableLangs = (translationArrayLen / sizeof(LANGANDCODEPAGE)); uint64_t availableLangs = (translationArrayLen / sizeof(LANGANDCODEPAGE));
if (!availableLangs) return exePath; if (!availableLangs) { free(fileVersionInfo); return false; }
int8_t syslangIdx = -1; int8_t syslangIdx = -1;
wchar_t metadataStringKey[256]; wchar_t metadataStringKey[256];
@ -275,19 +279,30 @@ std::wstring Session::fetchProcessName(DWORD pid) {
translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage); translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage);
if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize) if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize)
&& metadataString[0] != '\0') { && metadataString[0] != '\0') {
return std::wstring(metadataString); free(fileVersionInfo);
*sessionName = std::wstring(metadataString);
return true;
} }
swprintf(metadataStringKey, L"\\StringFileInfo\\%04x%04x\\ProductName", swprintf(metadataStringKey, L"\\StringFileInfo\\%04x%04x\\ProductName",
translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wLanguage, translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wLanguage,
translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage); translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage);
if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize) if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize)
&& metadataString[0] != '\0') { && metadataString[0] != '\0') {
return std::wstring(metadataString); free(fileVersionInfo);
*sessionName = std::wstring(metadataString);
return true;
} }
//MSIX? if(fileVersionInfo)
free(fileVersionInfo);
return false;
}
bool Session::fetchNameViaMSIX(std::wstring exePath, DWORD pid, std::wstring *sessionName) {
HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid); HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if(!process) return exePath; if(!process) return false;
//constant missing in mingw64. TB removed when I upgrade to a mingw64 ver that has it //constant missing in mingw64. TB removed when I upgrade to a mingw64 ver that has it
#define APPLICATION_USER_MODEL_ID_MAX_LENGTH 130 #define APPLICATION_USER_MODEL_ID_MAX_LENGTH 130
@ -295,7 +310,7 @@ std::wstring Session::fetchProcessName(DWORD pid) {
PWSTR userModelId = (PWSTR)malloc(length * sizeof(wchar_t)); PWSTR userModelId = (PWSTR)malloc(length * sizeof(wchar_t));
if(GetApplicationUserModelId(process, &length, userModelId) != ERROR_SUCCESS) { if(GetApplicationUserModelId(process, &length, userModelId) != ERROR_SUCCESS) {
CloseHandle(process); CloseHandle(process);
return exePath; return false;
} }
CloseHandle(process); CloseHandle(process);
@ -323,17 +338,190 @@ std::wstring Session::fetchProcessName(DWORD pid) {
LPWSTR humanName = nullptr; LPWSTR humanName = nullptr;
si->GetDisplayName(SIGDN_NORMALDISPLAY, &humanName); si->GetDisplayName(SIGDN_NORMALDISPLAY, &humanName);
if(humanName && humanName[0] != '\0') { if(humanName && humanName[0] != '\0') {
msixName = std::wstring(humanName); *sessionName = std::wstring(humanName);
CoTaskMemFree(humanName); CoTaskMemFree(humanName);
} }
if(si) si->Release(); if(si) si->Release();
if (msixName.length() > 0) if (sessionName->length() > 0)
return msixName; return true;
else return exePath; else return false;
//free(fileVersionInfo);
} }
BOOL test(HWND hwnd, LPARAM lParam) {
int length = GetWindowTextLength(hwnd);
wchar_t* buffer = new wchar_t[length + 1];
GetWindowTextW(hwnd, buffer, length + 1);
std::wstring windowTitle(buffer);
delete[] buffer;
// List visible windows with a non-empty title
if (IsWindowVisible(hwnd) && length != 0) {
//std::wcout << hwnd << ": " << windowTitle << std::endl;
log_wdebugcpp(windowTitle);
return FALSE;
}
return TRUE;
/*
* auto pParams = (DWORD)(lParam);
*
* DWORD processId;
* if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams) {
* // Stop enumerating
* //SetLastError(-1);
* //pParams->first = hwnd;
* //return FALSE;
* }
*
* // Continue enumerating
* return TRUE;
*/
}
bool Session::fetchNameViaWindowName(std::wstring exePath, DWORD pid, std::wstring *sessionName) {
std::pair<HWND, DWORD> params = { 0, pid };
BOOL result = EnumWindows(test, NULL);
/*
* if (!params.first) goto msix;
*/
/*
* if (!result && GetLastError() == -1 && params.first) {
* return params.first;
* }
*/
}
void Session::fetchName(std::wstring exePath, DWORD pid) {
if(fetchNameViaWindowName(exePath, pid, &this->sessionName))
return;
else if(fetchNameViaMSIX(exePath, pid, &this->sessionName))
return;
else if(!fetchNameViaFD(exePath, pid, &this->sessionName))
this->sessionName = exePath;
/*
* std::thread ttest(&Session::fetchNameViaWindowName, this, exePath, pid, &this->sessionName);
* ttest.join();
*/
}
/*
* std::wstring Session::fetchProcessName(DWORD pid) {
* /\* Executable path retrieval *\/
* std::wstring exePath = L"";
* std::wstring msixName;
*
* HANDLE processList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
* if (processList == INVALID_HANDLE_VALUE) {
* log_wdebugcpp(L"aye no procname.");
* return exePath;
* }
*
* MODULEENTRY32W me32w;
* me32w.dwSize = sizeof(MODULEENTRY32W);
* if(Module32FirstW(processList, &me32w)) {
* do {
* if (me32w.th32ProcessID == pid) {
* exePath = std::wstring(me32w.szExePath);
* break;
* /\*
* * However, if the calling process is a 32-bit process, you must call the
* * QueryFullProcessImageName function to retrieve the full path of the
* * executable file for a 64-bit process.
* *\/
* }
* } while(Module32NextW(processList, &me32w));
* }
* CloseHandle(processList);
*
*
* //No FD info available. Window name?
* nofdinfo:
* if(fileVersionInfo)
* free(fileVersionInfo);
*
* std::pair<HWND, DWORD> params = { 0, pid };
* BOOL result = EnumWindows([](HWND hwnd, LPARAM lParam) -> BOOL {
* auto pParams = (std::pair<HWND, DWORD>*)(lParam);
*
* DWORD processId;
* if (GetWindowThreadProcessId(hwnd, &processId) && processId == pParams->second) {
* // Stop enumerating
* SetLastError(-1);
* pParams->first = hwnd;
* return FALSE;
* }
*
* // Continue enumerating
* return TRUE;
* }, (LPARAM)&params);
*
* if (!params.first) goto msix;
*
*
* /\*
* * if (!result && GetLastError() == -1 && params.first) {
* * return params.first;
* * }
* *\/
*
* //No window info. MSIX?
* HANDLE process = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
* if(!process) return exePath;
*
* //constant missing in mingw64. TB removed when I upgrade to a mingw64 ver that has it
* #define APPLICATION_USER_MODEL_ID_MAX_LENGTH 130
* uint32_t length = APPLICATION_USER_MODEL_ID_MAX_LENGTH;
* PWSTR userModelId = (PWSTR)malloc(length * sizeof(wchar_t));
* if(GetApplicationUserModelId(process, &length, userModelId) != ERROR_SUCCESS) {
* CloseHandle(process);
* return exePath;
* }
* CloseHandle(process);
*
* static constexpr wchar_t* prefix = L"shell:appsfolder\\";
* uint32_t prefixLen = wcslen(prefix);
* uint32_t userModelIdLen = wcslen(userModelId);
* wchar_t* fullName;
* fullName = (prefixLen + userModelIdLen < length)
* ? (wchar_t*)malloc(length * sizeof(wchar_t))
* : (wchar_t*)malloc((length * 2) * sizeof(wchar_t));
* for (int32_t i = prefixLen - 1; i >= 0; i--) {
* fullName[i] = prefix[i];
* }
* for (uint32_t i = 0; i < userModelIdLen + 1; i++) {
* fullName[prefixLen + i] = userModelId[i];
* }
*
* IShellItem* si;
* HRESULT hr = SHCreateItemFromParsingName(fullName,
* nullptr,
* IID_IShellItem,
* (void**)&si
* );
* free(fullName);
* LPWSTR humanName = nullptr;
* si->GetDisplayName(SIGDN_NORMALDISPLAY, &humanName);
* if(humanName && humanName[0] != '\0') {
* msixName = std::wstring(humanName);
* CoTaskMemFree(humanName);
* }
* if(si) si->Release();
*
* if (msixName.length() > 0)
* return msixName;
* else return exePath;
* }
*/
//todo: conflicting names. change callback name //todo: conflicting names. change callback name
void Session::setState(SessionState state) { void Session::setState(SessionState state) {
sessionState = state; sessionState = state;

View file

@ -4,6 +4,7 @@
#include "global.h" #include "global.h"
#include "contclasses.h" #include "contclasses.h"
#include <thread>
class Endpoint; class Endpoint;
class SessionStateCallback : public IAudioSessionEvents { class SessionStateCallback : public IAudioSessionEvents {
@ -47,13 +48,18 @@ class Session {
//uint32_t getChannelCount(); //uint32_t getChannelCount();
private: private:
std::wstring fetchProcessName(DWORD pid); bool getExePath(DWORD pid, /*out*/ std::wstring *exePath);
void fetchName(std::wstring exePath, DWORD pid);
bool fetchNameViaFD(std::wstring exePath, DWORD pid, /*out*/ std::wstring *sessionName);
bool fetchNameViaMSIX(std::wstring exePath, DWORD pid, /*out*/ std::wstring *sessionName);
bool fetchNameViaWindowName(std::wstring exePath, DWORD pid, /*out*/ std::wstring *sessionName);
/* std::wstring fetchProcessName(DWORD pid); */
std::wstring sessionName; std::wstring sessionName;
SessionState sessionState; SessionState sessionState;
Endpoint* ep; Endpoint* ep;
IAudioSessionControl2* sessionControl = nullptr; IAudioSessionControl2* sessionControl = nullptr;
IAudioMeterInformation* meterInformation = nullptr; IAudioMeterInformation* meterInformation = nullptr;
ISimpleAudioVolume* sessionVolume = nullptr; ISimpleAudioVolume* sessionVolume = nullptr;
size_t idx; size_t idx;
}; };

View file

@ -30,6 +30,8 @@
#define STRING_CP "Open Control Panel" #define STRING_CP "Open Control Panel"
#define STRING_ABOUT "About" #define STRING_ABOUT "About"
#define STRING_STARTUP "Run at startup" #define STRING_STARTUP "Run at startup"
#define LSTRING_UNNAMED_SESSION L"Unnamed session"
//INIT BACK //INIT BACK
enum AudioChannel { enum AudioChannel {

View file

@ -326,6 +326,7 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent)
muteButton = new QCheckBox(this); muteButton = new QCheckBox(this);
mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this); mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this);
mainLabel->setToolTip(QString::fromStdWString(sh->getName()));
mainSlider = new MeterSlider(Qt::Horizontal, this); mainSlider = new MeterSlider(Qt::Horizontal, this);
//mainLabel->setMaximumWidth(150 /*1/16ish 1080p*/); //mainLabel->setMaximumWidth(150 /*1/16ish 1080p*/);
@ -368,8 +369,10 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent)
connect(volumePoller, &QTimer::timeout, [this, sh](){ connect(volumePoller, &QTimer::timeout, [this, sh](){
//if (memcmp(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)) == 0) return; CHECK IF THIS PROGRAM GENERATED THE FUNSIES IS NO LONGER IN USE FOR NOW. //if (memcmp(osh->callbackInfo[idx]->caller, osh->getGuid(), sizeof(NGuid)) == 0) return; CHECK IF THIS PROGRAM GENERATED THE FUNSIES IS NO LONGER IN USE FOR NOW.
//todo: global + constexpr + ratio //todo: global + constexpr + ratio
if (sh->getVolumeInfo()->isNameChanged) if (sh->getVolumeInfo()->isNameChanged) {
mainLabel->setText(QString::fromStdWString(sh->getName())); mainLabel->setText(QString::fromStdWString(sh->getName()));
mainLabel->setToolTip(QString::fromStdWString(sh->getName()));
}
const float roundingFactor = 0.005; const float roundingFactor = 0.005;
mainSlider->blockSignals(true); mainSlider->blockSignals(true);
muteButton->blockSignals(true); muteButton->blockSignals(true);