wip: settings in effect

This commit is contained in:
Hane 2024-12-06 17:55:46 +01:00
commit 1ae324b68a
8 changed files with 277 additions and 158 deletions

View file

@ -1,6 +1,96 @@
#include "backlasses.h" #include "backlasses.h"
#include "backfuncs.h" #include "backfuncs.h"
std::string getPath(SettingsTargetDirectory target, bool create) {
wchar_t* settingsPath = nullptr;
wchar_t settingsFile[] = L"\\settings.ini";
uint32_t settingsFileLen = (sizeof(settingsFile) / sizeof(wchar_t)) - 1;
wchar_t maxPathBypass[] = L"\\\\?\\";
uint32_t exePathLength = 0;
wchar_t folderPath[] = L"\\mixerq";
uint32_t maxPathBypassLen = (sizeof(maxPathBypass)/ sizeof(wchar_t)) - 1;
uint32_t folderPathLen = (sizeof(folderPath) / sizeof(wchar_t)) - 1;
wchar_t* roamingPath = nullptr;
log_wdebugcpp(L"Bypass size: " + std::to_wstring((sizeof(maxPathBypass)/sizeof(maxPathBypass[0]))));
switch(target) {
case HOME_DIR:
{
if(SHGetKnownFolderPath(
FOLDERID_RoamingAppData,
0,
NULL,
&roamingPath)
== S_OK) {
//Retrieve path len
uint32_t pathLen = 0;
wchar_t currentChar = roamingPath[pathLen];
while(currentChar != '\0') {
pathLen++;
currentChar = roamingPath[pathLen];
}
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);
std::string utf8path = utf16ToUtf8(settingsPath);
free(settingsPath);
return utf8path;
}
}
}
return nullptr;
break;
case APP_PATH:
{
//Executable dir
settingsPath = (wchar_t*)calloc(UNICODE_STRING_MAX_CHARS, sizeof(wchar_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));
if((UNICODE_STRING_MAX_CHARS - exePathLength) > (settingsFileLen + 1)) {
memcpy(settingsPath + exePathLength, settingsFile, sizeof(wchar_t) * settingsFileLen);
std::string utf8path = utf16ToUtf8(settingsPath);
free(settingsPath);
return utf8path;
}
}
return nullptr;
break;
default:
return nullptr;
break;
}
return nullptr;
}
EndpointNewSessionCallback::EndpointNewSessionCallback(EndpointHandler* eph){ EndpointNewSessionCallback::EndpointNewSessionCallback(EndpointHandler* eph){
this->eph = eph; this->eph = eph;
} }

View file

@ -7,6 +7,42 @@
class EndpointVolumeCallback; class EndpointVolumeCallback;
class Session; class Session;
std::string getPath(SettingsTargetDirectory target, bool create);
// Convert a wide UTF16LE string to an UTF8 string
static inline std::string utf16ToUtf8(const wchar_t* wstr) {
if(!wstr || wstr[0] == '\0') return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8,
0,
wstr,
-1,
NULL,
0,
NULL,
NULL);
std::string str(size_needed, 0);
WideCharToMultiByte(CP_UTF8,
0,
wstr,
-1,
&str[0],
size_needed,
NULL,
NULL);
return str;
}
// Convert an UTF8 string to a wide UTF16LE String
/*
* std::wstring utf8_decode(const std::string &str)
* {
* if( str.empty() ) return std::wstring();
* int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
* std::wstring wstrTo( size_needed, 0 );
* MultiByteToWideChar (CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
* return wstrTo;
* }
*/
class Endpoint { class Endpoint {

View file

@ -1,6 +1,27 @@
#include "backlasses.h" #include "backlasses.h"
#include "contclasses.h" #include "contclasses.h"
//TODO: pragma once
void setConfigDirToDefaults() {
#define tryFileDir(dir, create) do { \
OverseerHandler::settingsPath = getPath(dir, create); \
set = ini::UserSettings::createSettings(OverseerHandler::settingsPath.c_str()); \
if(set) { \
return; \
} else OverseerHandler::settingsPath.clear(); \
} while(0)
#define tryOpenFileDir(dir) tryFileDir(dir, false)
#define tryCreateFileDir(dir) tryFileDir(dir, true)
tryOpenFileDir(SettingsTargetDirectory::APP_PATH);
tryOpenFileDir(SettingsTargetDirectory::HOME_DIR);
tryCreateFileDir(SettingsTargetDirectory::HOME_DIR);
tryCreateFileDir(SettingsTargetDirectory::APP_PATH);
return;
#undef tryOpenFileDir
#undef tryCreateFileDir
#undef tryFileDir
}
EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) { EndpointHandler::EndpointHandler(uint64_t idx, Flows flow) {
//std::vector<Endpoint*> endpoints = osh->getPlaybackEndpoints().at(idx); //std::vector<Endpoint*> endpoints = osh->getPlaybackEndpoints().at(idx);
@ -205,6 +226,14 @@ OverseerHandler::OverseerHandler() {
this->os = new Overseer(); this->os = new Overseer();
} }
void OverseerHandler::setSettingsPath(std::string path) {
OverseerHandler::settingsPath = path;
}
std::string OverseerHandler::getSettingsPath(){
return OverseerHandler::settingsPath;
}
void OverseerHandler::populateSystemValues() { void OverseerHandler::populateSystemValues() {
this->os->populateSystemValues(); this->os->populateSystemValues();
} }
@ -374,3 +403,4 @@ void OverseerHandler::setRemoveEndpointWidgetFunction(std::function<void(uint64_
void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> ephs){ void OverseerHandler::setEndpointHandlers(std::vector<EndpointHandler*> ephs){
this->playbackEndpointHandlers = ephs; this->playbackEndpointHandlers = ephs;
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "global.h" #include "global.h"
#include "settings.h"
#include "contsessionclasses.h" #include "contsessionclasses.h"
//#define invoke_mem_fn(object,ptrToMember) ((object).*(ptrToMember)) //#define invoke_mem_fn(object,ptrToMember) ((object).*(ptrToMember))
//#define pinvoke_mem_fn(object,ptrToMember) ((object)->*(ptrToMember)) //#define pinvoke_mem_fn(object,ptrToMember) ((object)->*(ptrToMember))
@ -16,11 +17,13 @@ struct BackEndpointVolumeCallbackInfo {
NGuid caller; NGuid caller;
bool muted; bool muted;
float mainVolume; float mainVolume;
size_t channels; size_t channels;
std::vector<float> channelVolumes; std::vector<float> channelVolumes;
bool updateName = false; bool updateName = false;
}; };
void setConfigDirToDefaults();
class EndpointHandler { class EndpointHandler {
public: public:
@ -97,6 +100,9 @@ class OverseerHandler {
public: public:
OverseerHandler(); OverseerHandler();
static void setSettingsPath(std::string path);
static std::string getSettingsPath();
static inline std::string settingsPath;
void populateSystemValues(); void populateSystemValues();
void openControlPanel(); void openControlPanel();
ProcessedNativeEvent processTopLevelWindowMessage(void* msg); ProcessedNativeEvent processTopLevelWindowMessage(void* msg);
@ -143,6 +149,7 @@ private:
/* Session's */ /* Session's */
std::function<void(float)> changeSessionVolume; std::function<void(float)> changeSessionVolume;
//std::function<void(uint64_t /* device */, uint32_t /* channel */, float /* value */)> updateFrontVolumeCallback; //std::function<void(uint64_t /* device */, uint32_t /* channel */, float /* value */)> updateFrontVolumeCallback;
//std::function<void(uint64_t /* device */, bool /* mute */)> updateFrontMuteCallback; //std::function<void(uint64_t /* device */, bool /* mute */)> updateFrontMuteCallback;

View file

@ -41,7 +41,11 @@
//INIT BACK //INIT BACK
enum SettingsTargetDirectory {
HOME_DIR = 0,
APP_PATH = (1 << 0),
CUSTOM = (1 << 1),
};
enum ProcessedNativeEvent { enum ProcessedNativeEvent {
NONE = 0, NONE = 0,

View file

@ -4,7 +4,6 @@
#include "qtclasses.h" #include "qtclasses.h"
#include "qtvisuals.h" #include "qtvisuals.h"
#include "settings.h" #include "settings.h"
//#include "global.h"
OverseerHandler *osh = nullptr; OverseerHandler *osh = nullptr;
ini::UserSettings *set = nullptr; ini::UserSettings *set = nullptr;
@ -56,8 +55,14 @@ 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} }; char* userSettingsPath = parseCmdArgs(argc, argv);
set = new ini::UserSettings(parseCmdArgs(argc, argv)); if (userSettingsPath)
set = ini::UserSettings::createSettings(userSettingsPath, true);
if (set)
OverseerHandler::settingsPath = std::string(userSettingsPath);
else setConfigDirToDefaults();
initialize_file_log(); initialize_file_log();
atexit(closeDebugFileLog); atexit(closeDebugFileLog);

View file

@ -3,100 +3,48 @@
namespace ini { namespace ini {
UserSettings::UserSettings(char* path) { wchar_t* utf8toUtf16(const char* str) {
wchar_t* settingsPath = nullptr; if(!str || str[0] == '\0') return nullptr;
wchar_t settingsFile[] = L"\\settings.ini"; int sizeNeeded = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
uint32_t settingsFileLen = (sizeof(settingsFile) / sizeof(wchar_t)) - 1; wchar_t* utf16 = (wchar_t*)calloc(sizeNeeded, 1);
wchar_t maxPathBypass[] = L"\\\\?\\"; MultiByteToWideChar(CP_UTF8, 0, str, -1, utf16, sizeNeeded);
log_wdebugcpp(L"Bypass size: " + std::to_wstring((sizeof(maxPathBypass)/sizeof(maxPathBypass[0])))); return utf16;
}
//Executable dir UserSettings::UserSettings(char* textContents) {
settingsPath = (wchar_t*)calloc(UNICODE_STRING_MAX_CHARS, sizeof(wchar_t)); //Parsing values
uint32_t exePathLength = GetModuleFileNameW( bool isCRLF = false;
NULL, char *curLine = textContents;
settingsPath, char *separator = nullptr, *key = nullptr, *value = nullptr;
UNICODE_STRING_MAX_CHARS while(curLine) {
); char* nextLine = strchr(curLine, '\n');
//reverse wcsstr if(nextLine == curLine + 1 || nextLine == curLine + 2)
while(exePathLength >= 0) { goto nextIteration;
if(settingsPath[exePathLength] == '\\') { if (nextLine && (isCRLF || *(nextLine - 1) == '\r')) {
memset(settingsPath + exePathLength, isCRLF = true;
0, *(nextLine - 1) = '\0';
(UNICODE_STRING_MAX_CHARS - exePathLength) * sizeof(wchar_t)); } else if (nextLine) *nextLine = '\0'; // temporarily terminate the current line
break; log_debugcpp("curLine: " + std::string(curLine) + " ");
} else exePathLength--;
}
log_wdebugcpp(L"Exe folder: " + std::wstring(settingsPath));
HANDLE settingsHandle = nullptr; separator = strchr(curLine, '=');
if((UNICODE_STRING_MAX_CHARS - exePathLength) > (settingsFileLen + 1)) { if(!separator)
memcpy(settingsPath + exePathLength, settingsFile, sizeof(wchar_t) * settingsFileLen); goto nextIteration;
settingsHandle = CreateFile2( *separator = '\0';
settingsPath, key = trimAndAllocate(curLine);
GENERIC_READ | GENERIC_WRITE, value = trimAndAllocate(separator + 1);
0, values.try_emplace(key, value);
OPEN_ALWAYS, log_debugcpp("ini Map size: " + std::to_string(values.size()));
NULL); *separator = '=';
if(settingsHandle != INVALID_HANDLE_VALUE) { log_debugcpp("Filecreated!"); }
else { CloseHandle(settingsHandle); settingsHandle = nullptr; return; }
}
//Calculating file size and reading file nextIteration:
if(settingsHandle) { if (nextLine) { // then restore newline-char, just to be tidy
uint64_t fileSize; if (isCRLF)
LARGE_INTEGER fileSizeStruct; *(nextLine - 1) = '\r';
if(!GetFileSizeEx(settingsHandle, &fileSizeStruct)) return; else *nextLine = '\n';
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); curLine = nextLine ? (nextLine + 1) : NULL;
//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.
* }
* }
*/
} }
free(textContents);
} }
//todo: buffer overflow. poc //todo: buffer overflow. poc
@ -139,70 +87,68 @@ namespace ini {
return; return;
} }
newKey = (char*)calloc(keySize, sizeof(char)); newKey = (char*)calloc(keySize, sizeof(char));
values.insert(std::make_pair(newKey, value ? pos : neg)); values.insert(std::make_pair(newKey, value ? pos : neg));
return; return;
} }
UserSettings::~UserSettings() {
//AppData path //if(textContents) free(textContents);
/* for(std::pair<char*, char*> entry : values) {
* wchar_t folderPath[] = L"\\mixerq"; free(entry.first);
* if (!(entry.second == pos || entry.second == neg))
* wchar_t* roamingPath = nullptr; free(entry.second);
* 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::createSettings(const char* path, bool create) {
UserSettings::~UserSettings() { if(!path) return nullptr;
if(textContents) free(textContents); wchar_t* utf16Path = utf8toUtf16(path);
for(std::pair<char*, char*> entry : values) { if(!utf16Path) return nullptr;
free(entry.first);
free(entry.second); #define releaseBeforeReturn() do { \
CloseHandle(settingsHandle); \
settingsHandle = nullptr; \
free(utf16Path); \
} while(0)
char* textContents;
HANDLE settingsHandle = nullptr;
settingsHandle = CreateFile2(
utf16Path,
GENERIC_READ | GENERIC_WRITE,
0,
(create ? OPEN_ALWAYS : OPEN_EXISTING),
NULL);
if(settingsHandle == INVALID_HANDLE_VALUE) {
releaseBeforeReturn();
return nullptr;
}
//Calculating file size and reading file
uint64_t fileSize;
LARGE_INTEGER fileSizeStruct;
if(!GetFileSizeEx(settingsHandle, &fileSizeStruct)) {
releaseBeforeReturn();
return nullptr;
}
fileSize = fileSizeStruct.QuadPart;
uint32_t bytesRead = 0;
uint64_t textContentsSize = fileSize + 1;
textContents = (char*)calloc(textContentsSize, sizeof(char));
if (ReadFile(settingsHandle, textContents, fileSize,
(LPDWORD)&bytesRead, NULL) != TRUE) {
releaseBeforeReturn();
return nullptr;
}
releaseBeforeReturn();
return new UserSettings(textContents);
//textContents.assign(tempTextContents);
//free(tempTextContents);
#undef releaseBeforeReturn
} }
}
} }

View file

@ -2,7 +2,7 @@
#include "global.h" #include "global.h"
namespace ini { namespace ini {
//Trims spaces, LF and CRLF //Trims spaces, LF and CRLF
static inline char* trimAndAllocate(const char* in, uint64_t len = 0) { static inline char* trimAndAllocate(const char* in, uint64_t len = 0) {
if (!in) return nullptr; if (!in) return nullptr;
@ -51,7 +51,7 @@ namespace ini {
class UserSettings { class UserSettings {
public: public:
UserSettings(char* path = nullptr); static UserSettings* createSettings(const char* path = nullptr, bool create = false);
~UserSettings(); ~UserSettings();
char* const getValue(char* key, uint64_t len = 0); char* const getValue(char* key, uint64_t len = 0);
@ -63,11 +63,12 @@ class UserSettings {
private: private:
//void* returnValue(); //void* returnValue();
UserSettings(char* text = nullptr);
//std::map<const char*, int> values{ {"show_channels", false}, {"test", 7} }; //std::map<const char*, int> values{ {"show_channels", false}, {"test", 7} };
std::unordered_map<char*, char*, Djb12Hasher, StrcmpEqual> values; std::unordered_map<char*, char*, Djb12Hasher, StrcmpEqual> values;
char* textContents = nullptr; //char* textContents = nullptr;
uint64_t textContentsSize = 0; //uint64_t textContentsSize = 0;
char* pos = "true"; char* pos = "true";
char* neg = "false"; char* neg = "false";
}; };