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
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

View file

@ -126,9 +126,12 @@ Session::Session(Endpoint* ep, IAudioSessionControl2* sessionControl, size_t idx
else {
LPWSTR sessionDisplayName;
this->sessionControl->GetDisplayName(&sessionDisplayName);
if (!wcscmp(sessionDisplayName, L""))
this->sessionName = this->fetchProcessName(pid);
else
if (!wcscmp(sessionDisplayName, L"")) {
std::wstring exePath;
if (getExePath(pid, &exePath))
fetchName(exePath, pid);
else this->sessionName = std::wstring(LSTRING_UNNAMED_SESSION);
} else
this->sessionName = std::wstring(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?")); };
}
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://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://stackoverflow.com/questions/64321036/c-win32-getting-app-name-using-pid-and-executable-path
*/
/* Executable path retrieval */
std::wstring exePath = L"";
std::wstring msixName;
//std::wstring msixName;
HANDLE processList = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
if (processList == INVALID_HANDLE_VALUE) {
log_wdebugcpp(L"aye no procname.");
return exePath;
return false;
}
MODULEENTRY32W me32w;
@ -215,7 +216,7 @@ std::wstring Session::fetchProcessName(DWORD pid) {
if(Module32FirstW(processList, &me32w)) {
do {
if (me32w.th32ProcessID == pid) {
exePath = std::wstring(me32w.szExePath);
*exePath = std::wstring(me32w.szExePath);
break;
/*
* 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));
}
CloseHandle(processList);
return true;
}
bool Session::fetchNameViaFD(std::wstring exePath, DWORD pid, std::wstring *sessionName) {
/* File description retrieval: size and available lang-codepages */
struct LANGANDCODEPAGE {
WORD wLanguage;
@ -236,16 +240,16 @@ std::wstring Session::fetchProcessName(DWORD pid) {
DWORD filler;
DWORD fileVersionInfoSize = GetFileVersionInfoSizeExW
(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL, exePath.c_str(), &filler);
if (!fileVersionInfoSize) return exePath;
if (!fileVersionInfoSize) return false;
void* fileVersionInfo = malloc(fileVersionInfoSize);
if(!GetFileVersionInfoExW(FILE_VER_GET_LOCALISED | FILE_VER_GET_NEUTRAL,
exePath.c_str(),0,fileVersionInfoSize, fileVersionInfo))
return exePath;
return false;
UINT translationArrayLen = 0;
if (!VerQueryValueW(fileVersionInfo, L"\\VarFileInfo\\Translation", (LPVOID*)&translationArray, &translationArrayLen))
return exePath;
return false;
//File descriptor parsing
//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.
*/
uint64_t availableLangs = (translationArrayLen / sizeof(LANGANDCODEPAGE));
if (!availableLangs) return exePath;
if (!availableLangs) { free(fileVersionInfo); return false; }
int8_t syslangIdx = -1;
wchar_t metadataStringKey[256];
@ -275,19 +279,30 @@ std::wstring Session::fetchProcessName(DWORD pid) {
translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage);
if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize)
&& metadataString[0] != '\0') {
return std::wstring(metadataString);
free(fileVersionInfo);
*sessionName = std::wstring(metadataString);
return true;
}
swprintf(metadataStringKey, L"\\StringFileInfo\\%04x%04x\\ProductName",
translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wLanguage,
translationArray[(syslangIdx < 0 ? 0 : syslangIdx)].wCodePage);
if (VerQueryValueW(fileVersionInfo, metadataStringKey, (LPVOID*)&metadataString, &metadataStringSize)
&& 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);
if(!process) return exePath;
if(!process) return false;
//constant missing in mingw64. TB removed when I upgrade to a mingw64 ver that has it
#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));
if(GetApplicationUserModelId(process, &length, userModelId) != ERROR_SUCCESS) {
CloseHandle(process);
return exePath;
return false;
}
CloseHandle(process);
@ -323,17 +338,190 @@ std::wstring Session::fetchProcessName(DWORD pid) {
LPWSTR humanName = nullptr;
si->GetDisplayName(SIGDN_NORMALDISPLAY, &humanName);
if(humanName && humanName[0] != '\0') {
msixName = std::wstring(humanName);
*sessionName = std::wstring(humanName);
CoTaskMemFree(humanName);
}
if(si) si->Release();
if (msixName.length() > 0)
return msixName;
else return exePath;
//free(fileVersionInfo);
if (sessionName->length() > 0)
return true;
else return false;
}
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
void Session::setState(SessionState state) {
sessionState = state;

View file

@ -4,6 +4,7 @@
#include "global.h"
#include "contclasses.h"
#include <thread>
class Endpoint;
class SessionStateCallback : public IAudioSessionEvents {
@ -47,13 +48,18 @@ class Session {
//uint32_t getChannelCount();
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;
SessionState sessionState;
Endpoint* ep;
IAudioSessionControl2* sessionControl = nullptr;
IAudioMeterInformation* meterInformation = nullptr;
ISimpleAudioVolume* sessionVolume = nullptr;
size_t idx;
size_t idx;
};

View file

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

View file

@ -326,6 +326,7 @@ SessionWidget::SessionWidget(uint64_t idx, SessionHandler* sh, QWidget *parent)
muteButton = new QCheckBox(this);
mainLabel = new QLabel(QString::fromStdWString(sh->getName()), this);
mainLabel->setToolTip(QString::fromStdWString(sh->getName()));
mainSlider = new MeterSlider(Qt::Horizontal, this);
//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](){
//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
if (sh->getVolumeInfo()->isNameChanged)
if (sh->getVolumeInfo()->isNameChanged) {
mainLabel->setText(QString::fromStdWString(sh->getName()));
mainLabel->setToolTip(QString::fromStdWString(sh->getName()));
}
const float roundingFactor = 0.005;
mainSlider->blockSignals(true);
muteButton->blockSignals(true);