wip: ini parse baseline

This commit is contained in:
Hane 2024-12-03 21:13:42 +01:00
commit 8e07b1efdd
9 changed files with 356 additions and 27 deletions

View file

@ -2,7 +2,7 @@ QMAKE_CXXFLAGS += --target=x86_64-w64-mingw32 -g -gcodeview -O0 -Werror=return-t
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
DEFINES += DEBUG QT_LOGGING_TO_CONSOLE=1 WIN32_LEAN_AND_MEAN DEFINES += DEBUG QT_LOGGING_TO_CONSOLE=1 WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0602
CONFIG += debug CONFIG += debug
QT += widgets network QT += widgets network
@ -10,8 +10,8 @@ INCLUDEPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimp
DESTPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont" DESTPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont"
VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont" VPATH += "$$PWD\src" "$$PWD\src\qt" "$$PWD\src\back" "$$PWD\src\back\reimpl" "$$PWD\src\cont"
SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp backsessionclasses.cpp contclasses.cpp contsessionclasses.cpp SOURCES += qtestmain.cpp qtclasses.cpp backlasses.cpp backsessionclasses.cpp contclasses.cpp contsessionclasses.cpp settings.cpp
HEADERS += qtclasses.h backlasses.h backsessionclasses.h contclasses.h contsessionclasses.h global.h debug.h backfuncs.h ipolicyconfig.h msinclude.h meterslider.h qtvisuals.h HEADERS += qtclasses.h backlasses.h backsessionclasses.h contclasses.h contsessionclasses.h global.h debug.h backfuncs.h ipolicyconfig.h msinclude.h meterslider.h qtvisuals.h settings.h
RESOURCES = assets.qrc RESOURCES = assets.qrc
RC_ICONS += assets/logo.ico RC_ICONS += assets/logo.ico

View file

@ -4,7 +4,6 @@
#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 {

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#define _WIN32_WINNT 0x0A00
#include <sdkddkver.h> #include <sdkddkver.h>
//done by qt by def #define UNICODE //done by qt by def #define UNICODE
@ -9,6 +7,8 @@
#include <Windows.h> #include <Windows.h>
#include <shellapi.h> #include <shellapi.h>
#include <Shobjidl.h> #include <Shobjidl.h>
#include <Shlobj.h>
#include <fileapi.h>
#include <appmodel.h> #include <appmodel.h>
#include <processthreadsapi.h> #include <processthreadsapi.h>
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
@ -28,6 +28,7 @@
#include <stringapiset.h> #include <stringapiset.h>
#include <Mmreg.h> #include <Mmreg.h>
#include <tlhelp32.h> #include <tlhelp32.h>
#include <Knownfolders.h>
#include "ipolicyconfig.h" #include "ipolicyconfig.h"
#include "audiometerinfo.h" #include "audiometerinfo.h"

View file

@ -10,8 +10,10 @@
#include <string> #include <string>
#include <bitset> #include <bitset>
#include <locale> #include <locale>
#include <map>
#include "debug.h" #include "debug.h"
//#include "settings.h"
//TODO: Use tr();? QTranslator //TODO: Use tr();? QTranslator
#define STRING_MUTE "Mute" #define STRING_MUTE "Mute"
@ -30,12 +32,17 @@
#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 STRING_CHANNELS "Show endpoint channels"
#define STRING_NOENDPOINT "No active endpoints" #define STRING_NOENDPOINT "No active endpoints"
#define LSTRING_UNNAMED_SESSION L"Unnamed session" #define LSTRING_UNNAMED_SESSION L"Unnamed session"
//INIT BACK //INIT BACK
enum ProcessedNativeEvent { enum ProcessedNativeEvent {
NONE = 0, NONE = 0,
COLORS = (1 << 0), COLORS = (1 << 0),
@ -92,7 +99,11 @@ struct NGuid {
/* }while (i < 8); */ /* }while (i < 8); */
/* } */ /* } */
}; };
namespace ini {
class UserSettings;
}
extern ini::UserSettings *set;
class OverseerHandler; class OverseerHandler;
extern OverseerHandler *osh; extern OverseerHandler *osh;

View file

@ -296,7 +296,7 @@ void MainWindow::compose() {
this->mainMenuBar->setMaximumWidth((int)windowWidth); this->mainMenuBar->setMaximumWidth((int)windowWidth);
for (auto *epw : ews) { for (auto *epw : ews) {
if (!epw) continue; if (!epw) continue;
epw->updateChannelsVisibility();
epw->calculateSize(windowWidth - scrollArea->verticalScrollBar()->sizeHint().width() epw->calculateSize(windowWidth - scrollArea->verticalScrollBar()->sizeHint().width()
- widgetLayout->contentsMargins().left() - widgetLayout->contentsMargins().left()
, screenHeight); , screenHeight);
@ -605,8 +605,12 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i
if(epChannelCount > 1) { if(epChannelCount > 1) {
cw = new ChannelWidget(epChannelCount, eph, nullptr); cw = new ChannelWidget(epChannelCount, eph, nullptr);
cw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); cw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//cw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
widgetLayout->addWidget(cw, row++, 0, 1, 4 /*colmax*/, Qt::AlignTop); widgetLayout->addWidget(cw, row++, 0, 1, 4 /*colmax*/, Qt::AlignTop);
cw->setVisible(false);
char* const channelSettings = set->getValue("show_channels");
if(channelSettings && !(strcmp(channelSettings, "true"))){
cw->setVisible(true);
}
} }
/* /*
@ -889,6 +893,13 @@ void EndpointWidget::updateMainVolume(int newValue){
* } * }
*/ */
void EndpointWidget::updateChannelsVisibility() {
char* const channelSettings = set->getValue("show_channels");
if(channelSettings && !(strcmp(channelSettings, "true"))){
cw->setVisible(true);
} else cw->setVisible(false);
}
EndpointHandler* EndpointWidget::getEndpointHandler(){ EndpointHandler* EndpointWidget::getEndpointHandler(){
return this->eph; return this->eph;
} }
@ -915,19 +926,36 @@ std::map<Roles, ExtendedCheckBox*> EndpointWidget::getDefaultRolesWidgets() {
HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) { HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) {
widgetLayout = new QGridLayout(this); widgetLayout = new QGridLayout(this);
QString text = "&" STRING_ABOUT; QString text; //= "&" STRING_ABOUT;
about = new QPushButton(text, this); //about = new QPushButton(text, this);
#ifdef WIN32 #ifdef WIN32
text = "&" STRING_CP; text = "&" STRING_CP;
openCP = new QPushButton(text, this); openCP = new QPushButton(text, this);
connect(openCP, &QPushButton::clicked, [](){ osh->openControlPanel(); }); connect(openCP, &QPushButton::clicked, [](){ osh->openControlPanel(); });
text = "&" STRING_STARTUP;
startup = new QPushButton(text, this);
widgetLayout->addWidget(openCP , 0, 0); text = "&" STRING_CHANNELS;
widgetLayout->addWidget(startup, 0, 1); channels = new QCheckBox(text, this);
char* const channelSettings = set->getValue("show_channels");
if(channelSettings && !(strcmp(channelSettings, "true"))){
channels->setChecked(true);
}
connect(channels, &QCheckBox::stateChanged, [this, parent](){
set->setValue("show_channels", channels->isChecked(), sizeof("show_channels"));
if(parent)
QCoreApplication::instance()->postEvent
(parent, new QEvent((QEvent::Type)CustomQEvent::RecomposeMainWindow));
});
text = "&" STRING_STARTUP;
startup = new QCheckBox(text, this);
//connect(openCP, &QPushButton::clicked, [](){ osh->openControlPanel(); });
widgetLayout->addWidget(openCP , 0, 0, 2, 2);
widgetLayout->addWidget(channels, 0, 2, 1, 2);
widgetLayout->addWidget(startup , 1, 2, 1, 2);
#endif #endif
widgetLayout->addWidget(about , 0, 2); //widgetLayout->addWidget(about , 0, 2);
this->setLayout(widgetLayout); this->setLayout(widgetLayout);
} }
@ -1034,19 +1062,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
* Menu bar code * Menu bar code
*/ */
mainMenuBar = new QToolBar(this); mainMenuBar = new QToolBar(this);
/*
* QPalette pal;
* pal.setColor(QPalette::Window, Qt::transparent);
* mainMenuBar->setPalette(pal);
*/
hw = new HeaderWidget(this); hw = new HeaderWidget(this);
mainMenuBar->addWidget(hw); mainMenuBar->addWidget(hw);
mainMenuBar->setMovable(false); mainMenuBar->setMovable(false);
this->addToolBar(Qt::BottomToolBarArea, mainMenuBar); this->addToolBar(Qt::BottomToolBarArea, mainMenuBar);
reloadEndpointWidgets(); reloadEndpointWidgets();
//scrollArea->setMinimumWidth(ews.at(0)->minimumWidth());
log_debugcpp(std::to_string(scrollArea->minimumWidth()));
/* /*
* Tray Icon code * Tray Icon code

View file

@ -2,6 +2,7 @@
#include "qtcommon.h" #include "qtcommon.h"
#include "contclasses.h" #include "contclasses.h"
#include "settings.h"
class MeterSlider; class MeterSlider;
@ -100,7 +101,7 @@ public:
EndpointWidget(EndpointHandler* eph, QWidget *parent = nullptr, uint64_t idx = INT_MAX); EndpointWidget(EndpointHandler* eph, QWidget *parent = nullptr, uint64_t idx = INT_MAX);
//QSize minimumSizeHint() const override; //QSize minimumSizeHint() const override;
//void setMinimum(uint64_t height, double heightRatio); //void setMinimum(uint64_t height, double heightRatio);
void updateChannelsVisibility();
EndpointHandler* getEndpointHandler(); EndpointHandler* getEndpointHandler();
std::map<Roles, ExtendedCheckBox*> getDefaultRolesWidgets(); std::map<Roles, ExtendedCheckBox*> getDefaultRolesWidgets();
@ -167,10 +168,11 @@ public:
private: private:
QGridLayout *widgetLayout; QGridLayout *widgetLayout;
QPushButton *about; //QPushButton *about;
#ifdef WIN32 #ifdef WIN32
QPushButton *openCP; QPushButton *openCP;
QPushButton *startup; QCheckBox *startup;
QCheckBox *channels;
#endif #endif
}; };

View file

@ -3,9 +3,11 @@
#include "qtcommon.h" #include "qtcommon.h"
#include "qtclasses.h" #include "qtclasses.h"
#include "qtvisuals.h" #include "qtvisuals.h"
#include "settings.h"
//#include "global.h" //#include "global.h"
OverseerHandler *osh = nullptr; OverseerHandler *osh = nullptr;
ini::UserSettings *set = nullptr;
QApplication* createApplication(int &argc, char *argv[]) QApplication* createApplication(int &argc, char *argv[])
{ {
@ -31,6 +33,14 @@ void closeDebugFileLog() {
close_file_log_buffer(); close_file_log_buffer();
} }
char* parseCmdArgs(int argc, char* argv[]) {
if(argc == 1) return nullptr;
char arg[] = "--config-path=";
if(strstr(argv[1], arg)) {
return argv[1] + (sizeof(arg) / sizeof(arg[0])) - 1;
} else return nullptr;
}
/* set_terminate /* set_terminate
* void closeDebugFileLog2() { * void closeDebugFileLog2() {
* close_file_log_buffer(); * close_file_log_buffer();
@ -46,6 +56,8 @@ int main (int argc, char* argv[]) {
* log_debugcpp(a.toStdString()); * log_debugcpp(a.toStdString());
* } * }
*/ */
//std::map<const char*, cha>* values = new std::map<const char*, int>{ {"show_channels", false}, {"test", 7} };
set = new ini::UserSettings(parseCmdArgs(argc, argv));
initialize_file_log(); initialize_file_log();
atexit(closeDebugFileLog); atexit(closeDebugFileLog);

208
src/settings.cpp Normal file
View file

@ -0,0 +1,208 @@
#include "settings.h"
#include "msinclude.h"
namespace ini {
UserSettings::UserSettings(char* path) {
wchar_t* settingsPath = nullptr;
wchar_t settingsFile[] = L"\\settings.ini";
uint32_t settingsFileLen = (sizeof(settingsFile) / sizeof(wchar_t)) - 1;
wchar_t maxPathBypass[] = L"\\\\?\\";
log_wdebugcpp(L"Bypass size: " + std::to_wstring((sizeof(maxPathBypass)/sizeof(maxPathBypass[0]))));
//Executable dir
settingsPath = (wchar_t*)calloc(UNICODE_STRING_MAX_CHARS, sizeof(wchar_t));
uint32_t exePathLength = GetModuleFileNameW(
NULL,
settingsPath,
UNICODE_STRING_MAX_CHARS
);
//reverse wcsstr
while(exePathLength >= 0) {
if(settingsPath[exePathLength] == '\\') {
memset(settingsPath + exePathLength,
0,
(UNICODE_STRING_MAX_CHARS - exePathLength) * sizeof(wchar_t));
break;
} else exePathLength--;
}
log_wdebugcpp(L"Exe folder: " + std::wstring(settingsPath));
HANDLE settingsHandle = nullptr;
if((UNICODE_STRING_MAX_CHARS - exePathLength) > (settingsFileLen + 1)) {
memcpy(settingsPath + exePathLength, settingsFile, sizeof(wchar_t) * settingsFileLen);
settingsHandle = CreateFile2(
settingsPath,
GENERIC_READ | GENERIC_WRITE,
0,
OPEN_ALWAYS,
NULL);
if(settingsHandle != INVALID_HANDLE_VALUE) { log_debugcpp("Filecreated!"); }
else { CloseHandle(settingsHandle); settingsHandle = nullptr; return; }
}
//Calculating file size and reading file
if(settingsHandle) {
uint64_t fileSize;
LARGE_INTEGER fileSizeStruct;
if(!GetFileSizeEx(settingsHandle, &fileSizeStruct)) return;
fileSize = fileSizeStruct.QuadPart;
uint32_t bytesRead = 0;
textContentsSize = fileSize + 1;
textContents = (char*)calloc(textContentsSize, sizeof(char));
if (ReadFile(settingsHandle, textContents, fileSize,
(LPDWORD)&bytesRead, NULL) != TRUE) {
free(textContents);
return;
}
//textContents.assign(tempTextContents);
//free(tempTextContents);
//Parsing values
bool isCRLF = false;
char *curLine = textContents;
char *separator = nullptr, *key = nullptr, *value = nullptr;
while(curLine) {
char* nextLine = strchr(curLine, '\n');
if(nextLine == curLine + 1 || nextLine == curLine + 2) goto nextIteration;
if (nextLine && (isCRLF || *(nextLine - 1) == '\r')) {
isCRLF = true;
*(nextLine - 1) = '\0';
} else if (nextLine) *nextLine = '\0'; // temporarily terminate the current line
log_debugcpp("curLine: " + std::string(curLine) + " ");
separator = strchr(curLine, '=');
if(!separator) goto nextIteration;
*separator = '\0';
key = trimAndAllocate(curLine);
value = trimAndAllocate(separator + 1);
values.try_emplace(key, value);
log_debugcpp("ini Map size: " + std::to_string(values.size()));
*separator = '=';
nextIteration:
if (nextLine) { // then restore newline-char, just to be tidy
if (isCRLF)
*(nextLine - 1) = '\r';
else *nextLine = '\n';
}
curLine = nextLine ? (nextLine + 1) : NULL;
}
/*
* for(const std::pair<char[], int> keyVal : defaultValues) {
* if (textContents.find(keyVal.first) {
* if (keyVal.
* }
* }
*/
}
}
//todo: buffer overflow. poc
char* const UserSettings::getValue(char* key, uint64_t len) {
if (auto search = values.find(key); search != values.end())
return (char* const) search->second;
return nullptr;
}
void UserSettings::setValue(char* key, char* value, uint64_t valueSize, uint64_t keySize) {
char *newValue, *newKey;
if (auto search = values.find(key); search != values.end()) {
if(!(strcmp(value, search->second))) return;
newValue = (char*)calloc(valueSize, sizeof(char));
if (!(search->second == pos || search->second == neg)) {
free(search->second);
}
search->second = newValue;
return;
}
newValue = (char*)calloc(valueSize, sizeof(char));
newKey = (char*)calloc(keySize, sizeof(char));
values.insert(std::make_pair(newKey, newValue));
return;
}
void UserSettings::setValue(char* key, bool value, uint64_t keySize) {
char *newKey;
log_debugcpp("Pos value: " + std::to_string((intptr_t)pos));
log_debugcpp("Neg value: " + std::to_string((intptr_t)neg));
if (auto search = values.find(key); search != values.end()) {
log_debugcpp("Previous value: " + std::to_string((intptr_t)values[key]));
if (!(search->second == pos || search->second == neg)) {
free(search->second);
}
if (value)
search->second = pos;
else search->second = neg;
return;
}
newKey = (char*)calloc(keySize, sizeof(char));
values.insert(std::make_pair(newKey, value ? pos : neg));
return;
}
//AppData path
/*
* wchar_t folderPath[] = L"\\mixerq";
*
* wchar_t* roamingPath = nullptr;
* if(SHGetKnownFolderPath(
* FOLDERID_RoamingAppData,
* 0,
* NULL,
* &roamingPath)
* == S_OK) {
* uint32_t pathLen = 0;
* wchar_t currentChar = roamingPath[pathLen];
* while(currentChar != '\0') {
* pathLen++;
* currentChar = roamingPath[pathLen];
* }
*
* uint32_t maxPathBypassLen = (sizeof(maxPathBypass)/ sizeof(wchar_t)) - 1;
* uint32_t folderPathLen = (sizeof(folderPath) / sizeof(wchar_t)) - 1;
* settingsPath = (wchar_t*)calloc(pathLen +
* maxPathBypassLen +
* folderPathLen +
* settingsFileLen,
* sizeof(wchar_t));
* memcpy(settingsPath, maxPathBypass, sizeof(wchar_t) * maxPathBypassLen);
* memcpy(settingsPath + (maxPathBypassLen), roamingPath, sizeof(wchar_t) * pathLen);
* CoTaskMemFree(roamingPath);
* memcpy(settingsPath + (maxPathBypassLen + pathLen),
* folderPath, sizeof(wchar_t) * folderPathLen);
* log_wdebugcpp(L"Settings folder path: " + std::wstring(settingsPath));
*
* if(CreateDirectoryW(settingsPath, NULL) || GetLastError() == ERROR_ALREADY_EXISTS) {
* memcpy(settingsPath + (maxPathBypassLen + pathLen + folderPathLen),
* settingsFile, sizeof(wchar_t) * settingsFileLen);
*
* HANDLE settingsHandle = CreateFile2(
* settingsPath,
* GENERIC_READ | GENERIC_WRITE,
* 0,
* OPEN_ALWAYS,
* NULL);
* if(settingsHandle != INVALID_HANDLE_VALUE) log_debugcpp("Filecreated!");
*
* }
* //End AppData
*/
UserSettings::~UserSettings() {
if(textContents) free(textContents);
for(std::pair<char*, char*> entry : values) {
free(entry.first);
free(entry.second);
}
}
}

75
src/settings.h Normal file
View file

@ -0,0 +1,75 @@
#pragma once
#include "global.h"
namespace ini {
//Trims spaces, LF and CRLF
static inline char* trimAndAllocate(const char* in, uint64_t len = 0) {
if (!in) return nullptr;
uint64_t startingPos = 0, lastPos = 0;
bool foundStart = false;
for(int i = 0; ;i++) {
char c = in[i];
if ((len > 0 && startingPos == (len - 1)) || (len > 0 && lastPos == (len - 1))) return nullptr;
if ((c != ' ' || c != '\r' || c != '\n') && !foundStart) {
foundStart = true;
lastPos = startingPos;
}
if (foundStart && (c == ' ' || c == '\r' || c == '\n')) {
break;
}
if(!foundStart)
startingPos++;
else lastPos++;
}
if(!(lastPos - startingPos)) return nullptr;
char* trimmedString = (char*)calloc(lastPos - startingPos + 1, sizeof(char));
memcpy(trimmedString, in + startingPos, lastPos - startingPos);
return trimmedString;
}
struct Djb12Hasher {
size_t operator()(char* str) const {
unsigned long hash = 5381;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
return hash;
}
};
struct StrcmpEqual {
bool operator()(char* key1, char* key2) const {
return (!strcmp(key1, key2));
}
};
class UserSettings {
public:
UserSettings(char* path = nullptr);
~UserSettings();
char* const getValue(char* key, uint64_t len = 0);
void setValue(char* key, char* value, uint64_t valueSize, uint64_t keySize); //'\0' included
void setValue(char* key, bool value, uint64_t keySize); //'\0' included
//void setValue(char* key, uint64_t value, uint64_t valueSize, uint64_t keySize); //'\0' included
protected:
private:
//void* returnValue();
//std::map<const char*, int> values{ {"show_channels", false}, {"test", 7} };
std::unordered_map<char*, char*, Djb12Hasher, StrcmpEqual> values;
char* textContents = nullptr;
uint64_t textContentsSize = 0;
char* pos = "true";
char* neg = "false";
};
}