Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Common/Cpp/Filesystem/FilePath.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ class Path{


public:
Path& replace_extension(const Path& replacement){
Path& replace_extension(const Path& replacement = Path()){
m_path.replace_extension(replacement);
return *this;
}
Expand Down
6 changes: 6 additions & 0 deletions Common/Cpp/Filesystem/Filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ Path current_path(){
return std::filesystem::current_path();
}

Path application_binary_name(){
return application_binary_path().filename();
}
Path application_binary_directory(){
return application_binary_path().parent_path();
}



Expand Down
11 changes: 11 additions & 0 deletions Common/Cpp/Filesystem/Filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ void rename(const Path& old_path, const Path& new_path, std::error_code& ec);
Path current_path();

// The path to the actual binary that is running.
Path application_binary_name();
Path application_binary_path();
Path application_binary_directory();

// Path to where the application is installed.
// All immutable resources are relative to this.
Expand All @@ -76,6 +78,15 @@ Path application_install_path();
Path application_scratch_path();


// Set a profile for program settings (/UserSettings/PROFILE_NAME/) on MacOS.
// Have to run the program with command-line argument "open -n PATH_TO_APP --args --profile PROFILE_NAME" to set the profile and launch a new window.
// This allows multiple instances of the program to run since settings are no longer shared.
#if defined(__APPLE__)
void set_startup_profile(int& argc, char* argv[]);
const std::string& STARTUP_PROFILE();
#endif



}
}
Expand Down
6 changes: 3 additions & 3 deletions Common/Cpp/Filesystem/Filesystem_Linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Path application_binary_path(){
char buffer[PATH_MAX];
ssize_t count = readlink("/proc/self/exe", buffer, PATH_MAX);
if (count != -1) {
return Path(std::string(buffer, count)).parent_path();
return Path(std::string(buffer, count));
}
return Path();
}
Expand Down Expand Up @@ -94,10 +94,10 @@ Path application_install_path(){
}

// Fallback
return application_binary_path();
return application_binary_directory();
}
Path application_scratch_path(){
return current_path();
return current_path().string_slash_normalized() + "/";
}


Expand Down
79 changes: 75 additions & 4 deletions Common/Cpp/Filesystem/Filesystem_Mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

#include <limits.h>
#include <vector>
#include <unistd.h>
#include <libproc.h>
#include <mach-o/dyld.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFBundle.h>
Expand All @@ -16,11 +18,58 @@ namespace PokemonAutomation{
namespace Filesystem{



static std::string g_startup_profile;

void set_startup_profile(int& argc, char* argv[]){
for (int i = 1; i + 1 < argc; i++){
if (strcmp(argv[i], "--profile") == 0){
std::string profile = argv[i + 1];
for (char c : profile){
if (!(std::isalpha(c) || std::isdigit(c)) && c != u'_' && c != u'-') c = u'_';
}
g_startup_profile = std::move(profile);
// Shift everything after --profile <name> down by 2.
for (int j = i; j + 2 < argc; j++){
argv[j] = argv[j + 2];
}
argc -= 2;
return;
}
}
}

const std::string& STARTUP_PROFILE(){
return g_startup_profile;
}


// Helper function to safely get the current executable's name on macOS
std::string get_macos_executable_name() {
char path_buffer[PROC_PIDPATHINFO_MAXSIZE];
pid_t pid = getpid();

if (proc_pidpath(pid, path_buffer, sizeof(path_buffer)) > 0) {
Filesystem::Path full_path(path_buffer);
return full_path.filename().string(); // Returns the binary name (e.g., "SerialPrograms")
}

return "UnknownApp"; // Worst-case fallback
}









Path application_binary_path(){
char buffer[PATH_MAX];
uint32_t size = sizeof(buffer);
if (_NSGetExecutablePath(buffer, &size) == 0) {
return std::filesystem::canonical(std::filesystem::path(buffer)).parent_path();
return std::filesystem::canonical(std::filesystem::path(buffer));
}
return Path();
}
Expand Down Expand Up @@ -71,11 +120,33 @@ Path application_install_path(){
}

// Fallback
return application_binary_path();
return application_binary_directory();
}
Path application_scratch_path(){
// TODO: This is just a placeholder.
return current_path();
// 1. Replicate Home folder resolution (~/)
const char* home_env = std::getenv("HOME");
Filesystem::Path app_support_path;

if (home_env != nullptr) {
app_support_path = Filesystem::Path(home_env);
} else {
app_support_path = Filesystem::current_path();
}

// 2. Replicate standard macOS AppDataLocation structure programmatically
std::string app_name = get_macos_executable_name();
app_support_path = app_support_path / "Library" / "Application Support" / app_name;

// 3. Append your profile path
if (!g_startup_profile.empty()) {
app_support_path /= "Profiles";
app_support_path /= g_startup_profile;
}

// 4. Create directory structure
Filesystem::create_directories(app_support_path);

return app_support_path.string() + "/";
}


Expand Down
6 changes: 3 additions & 3 deletions Common/Cpp/Filesystem/Filesystem_Qt.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ namespace Filesystem{


Path application_binary_path(){
QString application_dir_path = qApp->applicationDirPath();
QString application_dir_path = qApp->applicationFilePath();
return Path(application_dir_path.toStdString());
}
Path application_install_path(){
return application_binary_path();
return application_binary_directory();
}
Path application_scratch_path(){
return current_path();
return current_path().string_slash_normalized() + "/";
}


Expand Down
6 changes: 3 additions & 3 deletions Common/Cpp/Filesystem/Filesystem_Windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ namespace Filesystem{
Path application_binary_path(){
wchar_t buffer[MAX_PATH];
GetModuleFileNameW(nullptr, buffer, MAX_PATH);
return std::filesystem::path(buffer).parent_path();
return std::filesystem::path(buffer);
}
Path application_install_path(){
return application_binary_path();
return application_binary_directory();
}
Path application_scratch_path(){
return current_path();
return current_path().string_slash_normalized() + "/";
}


Expand Down
60 changes: 5 additions & 55 deletions SerialPrograms/Source/CommonFramework/GlobalAutoPaths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@
*
*/

#include <QCoreApplication>
#include <QString>
#include <QFile>
#include <QStandardPaths>
#include <QFile>
#include <QFileInfo>
#include <QDir>
#include "Common/Cpp/Filesystem/Filesystem.h"
#include "GlobalAutoPaths.h"

Expand All @@ -21,40 +14,9 @@
namespace PokemonAutomation{





#if defined(__APPLE__)
static std::string g_startup_profile;

void set_startup_profile(int& argc, char* argv[]){
for (int i = 1; i + 1 < argc; i++){
if (strcmp(argv[i], "--profile") == 0){
std::string profile = argv[i + 1];
for (char c : profile){
if (!(std::isalpha(c) || std::isdigit(c)) && c != u'_' && c != u'-') c = u'_';
}
g_startup_profile = std::move(profile);
// Shift everything after --profile <name> down by 2.
for (int j = i; j + 2 < argc; j++){
argv[j] = argv[j + 2];
}
argc -= 2;
return;
}
}
}

const std::string& STARTUP_PROFILE(){
return g_startup_profile;
}
#endif

namespace{




std::string get_resource_path(){
// Find the resource directory.
Filesystem::Path base = Filesystem::application_install_path();
Expand Down Expand Up @@ -110,21 +72,6 @@ std::string get_training_path(){
return (base / "TrainingData/").string_slash_normalized();
}

std::string get_runtime_base_path(){
#if defined(__APPLE__)
// QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) returns
// "/Users/$USERNAME/Library/Application Support/SerialPrograms"
QString appSupportPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
if (!g_startup_profile.empty()){
appSupportPath += "/Profiles/" + QString::fromStdString(g_startup_profile);
}
QDir().mkpath(appSupportPath);
return appSupportPath.toStdString() + "/";
#else
return Filesystem::application_scratch_path().string_slash_normalized() + "/";
#endif
}

std::string get_setting_path(){
return RUNTIME_BASE_PATH() + "UserSettings/";
}
Expand All @@ -143,8 +90,11 @@ std::string get_user_file_path(){

} // anonymous namespace




const std::string& RUNTIME_BASE_PATH(){
static std::string path = get_runtime_base_path();
static std::string path = Filesystem::application_scratch_path().string();
return path;
}

Expand All @@ -153,7 +103,7 @@ const std::string& SETTINGS_PATH(){
return path;
}
const std::string& PROGRAM_SETTING_JSON_PATH(){
static std::string path = SETTINGS_PATH() + QCoreApplication::applicationName().toStdString() + "-Settings.json";
static std::string path = SETTINGS_PATH() + Filesystem::application_binary_name().replace_extension().string() + "-Settings.json";
return path;
}
const std::string& SCREENSHOTS_PATH(){
Expand Down
9 changes: 0 additions & 9 deletions SerialPrograms/Source/CommonFramework/GlobalAutoPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,6 @@
namespace PokemonAutomation{



// Set a profile for program settings (/UserSettings/PROFILE_NAME/) on MacOS.
// Have to run the program with command-line argument "open -n PATH_TO_APP --args --profile PROFILE_NAME" to set the profile and launch a new window.
// This allows multiple instances of the program to run since settings are no longer shared.
#if defined(__APPLE__)
void set_startup_profile(int& argc, char* argv[]);
const std::string& STARTUP_PROFILE();
#endif

// Path to the parent folder that holds all other folders, e.g. settings folder, screenshot folder, etc.
const std::string& RUNTIME_BASE_PATH();

Expand Down
7 changes: 4 additions & 3 deletions SerialPrograms/Source/CommonFramework/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ FileLogger& global_file_logger(){

int run_program(int argc, char *argv[]){
#if defined(__APPLE__)
PokemonAutomation::set_startup_profile(argc, argv);
Filesystem::set_startup_profile(argc, argv);
QApplication application(argc, argv);
#else
QApplication application(argc, argv);
Expand All @@ -109,7 +109,7 @@ int run_program(int argc, char *argv[]){
logger.log("================================================================================");
logger.log("Starting Program...");
logger.log("Current path: " + Filesystem::current_path().string_slash_normalized());
logger.log("Executable path: " + Filesystem::application_binary_path().string_slash_normalized());
logger.log("Executable path: " + Filesystem::application_binary_directory().string_slash_normalized());
logger.log("Program setting folder: " + SETTINGS_PATH());
logger.log("Program resources folder: " + RESOURCE_PATH());

Expand Down Expand Up @@ -240,8 +240,9 @@ int main(int argc, char *argv[]){
// Qt multimedia, default to gstreamer to prevent flickering
// Easier than the alternative which is compiling qt6multimedia with QT_DEFAULT_MEDIA_BACKEND
// See: https://doc.qt.io/qt-6.5/qtmultimedia-index.html
if (qEnvironmentVariableIsEmpty("QT_MEDIA_BACKEND"))
if (qEnvironmentVariableIsEmpty("QT_MEDIA_BACKEND")){
qputenv("QT_MEDIA_BACKEND", "gstreamer");
}
#endif

// So far, this is only needed on Mac where static initialization is fucked up.
Expand Down
7 changes: 4 additions & 3 deletions SerialPrograms/Source/CommonFramework/Windows/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
#include <QPushButton>
#include <QMessageBox>
#include "Common/Cpp/ScopeExit.h"
#include "Common/Cpp/Exceptions.h"
#include "Common/Cpp/Logging/MultiOutputLogger.h"
#include "Common/Cpp/Filesystem/Filesystem.h"
#include "Common/Cpp/CpuId/CpuId.h"
#include "Common/Cpp/Exceptions.h"
#include "CommonFramework/Globals.h"
#include "CommonFramework/GlobalAutoPaths.h"
#include "CommonFramework/GlobalSettingsPanel.h"
Expand Down Expand Up @@ -72,8 +73,8 @@ MainWindow::MainWindow(QWidget* parent)
// setStatusBar(statusbar);
std::string title = PROGRAM_NAME + " Computer-Control Programs (" + PROGRAM_VERSION + ")";
#if defined(__APPLE__)
if (!STARTUP_PROFILE().empty()){
setWindowTitle(QString::fromStdString(title + " [Profile: " + STARTUP_PROFILE() + "]"));
if (!Filesystem::STARTUP_PROFILE().empty()){
setWindowTitle(QString::fromStdString(title + " [Profile: " + Filesystem::STARTUP_PROFILE() + "]"));
}else{
setWindowTitle(QString::fromStdString(title));
}
Expand Down
Loading