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
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
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
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"
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
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
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 settings.h
RESOURCES = assets.qrc
RC_ICONS += assets/logo.ico

View file

@ -4,7 +4,6 @@
#include "global.h"
#include "contclasses.h"
#include <thread>
class Endpoint;
class SessionStateCallback : public IAudioSessionEvents {

View file

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

View file

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

View file

@ -296,7 +296,7 @@ void MainWindow::compose() {
this->mainMenuBar->setMaximumWidth((int)windowWidth);
for (auto *epw : ews) {
if (!epw) continue;
epw->updateChannelsVisibility();
epw->calculateSize(windowWidth - scrollArea->verticalScrollBar()->sizeHint().width()
- widgetLayout->contentsMargins().left()
, screenHeight);
@ -605,8 +605,12 @@ EndpointWidget::EndpointWidget(EndpointHandler* eph, QWidget *parent, uint64_t i
if(epChannelCount > 1) {
cw = new ChannelWidget(epChannelCount, eph, nullptr);
cw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//cw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
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(){
return this->eph;
}
@ -915,19 +926,36 @@ std::map<Roles, ExtendedCheckBox*> EndpointWidget::getDefaultRolesWidgets() {
HeaderWidget::HeaderWidget(QWidget *parent) : QWidget(parent) {
widgetLayout = new QGridLayout(this);
QString text = "&" STRING_ABOUT;
about = new QPushButton(text, this);
QString text; //= "&" STRING_ABOUT;
//about = new QPushButton(text, this);
#ifdef WIN32
text = "&" STRING_CP;
openCP = new QPushButton(text, this);
connect(openCP, &QPushButton::clicked, [](){ osh->openControlPanel(); });
text = "&" STRING_STARTUP;
startup = new QPushButton(text, this);
widgetLayout->addWidget(openCP , 0, 0);
widgetLayout->addWidget(startup, 0, 1);
text = "&" STRING_CHANNELS;
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
widgetLayout->addWidget(about , 0, 2);
//widgetLayout->addWidget(about , 0, 2);
this->setLayout(widgetLayout);
}
@ -1034,19 +1062,12 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
* Menu bar code
*/
mainMenuBar = new QToolBar(this);
/*
* QPalette pal;
* pal.setColor(QPalette::Window, Qt::transparent);
* mainMenuBar->setPalette(pal);
*/
hw = new HeaderWidget(this);
mainMenuBar->addWidget(hw);
mainMenuBar->setMovable(false);
this->addToolBar(Qt::BottomToolBarArea, mainMenuBar);
reloadEndpointWidgets();
//scrollArea->setMinimumWidth(ews.at(0)->minimumWidth());
log_debugcpp(std::to_string(scrollArea->minimumWidth()));
/*
* Tray Icon code

View file

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

View file

@ -3,9 +3,11 @@
#include "qtcommon.h"
#include "qtclasses.h"
#include "qtvisuals.h"
#include "settings.h"
//#include "global.h"
OverseerHandler *osh = nullptr;
ini::UserSettings *set = nullptr;
QApplication* createApplication(int &argc, char *argv[])
{
@ -31,6 +33,14 @@ void closeDebugFileLog() {
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
* void closeDebugFileLog2() {
* close_file_log_buffer();
@ -46,6 +56,8 @@ int main (int argc, char* argv[]) {
* 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();
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";
};
}