From 412759de29d404fa65e1050654fe59cfb96df0c7 Mon Sep 17 00:00:00 2001 From: Andrew Belt Date: Wed, 8 Mar 2017 13:25:57 -0500 Subject: [PATCH] Fixed current working directory on macOS Sierra, probably http://stackoverflow.com/questions/42600770/chdir-to-the-location-of-the-app-bundle-in-c-macos-application#comment72481655_42637115 --- src/main.cpp | 92 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 75 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 24fa27ab..719a1096 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,30 +1,88 @@ -#if defined(APPLE) - #include "CoreFoundation/CoreFoundation.h" - #include - #include -#endif - #include "engine.hpp" #include "gui.hpp" #include "app.hpp" #include "plugin.hpp" +#if defined(APPLE) +#include +#include // for chdir and access +#include // for dirname +// #include +#include // for _NSGetExecutablePath +#include // for PATH_MAX? +#include // for opendir + +void alert(std::string header, std::string message, int level) { + CFStringRef headerRef = CFStringCreateWithCString(NULL, header.c_str(), header.size()); + CFStringRef messageRef = CFStringCreateWithCString(NULL, message.c_str(), message.size()); + CFOptionFlags result; + + CFUserNotificationDisplayAlert( + 0, // no timeout + level, // flags for alert level + NULL, // iconURL + NULL, // soundURL + NULL, // localizationURL + headerRef, + messageRef, + NULL, // default "OK" + NULL, // alternative button + NULL, // other button + &result + ); + + CFRelease(headerRef); + CFRelease(messageRef); +} + +bool isCorrectCwd() { + DIR *dir = opendir("res"); + if (dir) { + closedir(dir); + return true; + } + else { + return false; + } +} + +/** macOS workaround for setting the working directory to the location of the .app */ +void fixCwd() { + // Check if the cwd is already set correctly (e.g. launched from the command line or gdb) + if (isCorrectCwd()) + return; + + // Get path of binary inside the app bundle + // It should be something like */Rack.app/Contents/MacOS + char path[PATH_MAX]; + uint32_t pathLen = sizeof(path); + int err = _NSGetExecutablePath(path, &pathLen); + assert(!err); + + // Switch to the directory of the actual binary + chdir(dirname(path)); + // and then go up three directories to get to the parent directory + chdir("../../../"); + if (isCorrectCwd()) + return; + + // Switch to a default absolute path + chdir("/Applications/Rack"); + if (isCorrectCwd()) + return; + + alert("Install Rack", "To install Rack, please move the Rack directory to your /Applications folder.", 2); + exit(1); +} +#endif + + using namespace rack; int main() { #if defined(APPLE) - // macOS workaround for setting the working directory to the location of the .app - { - CFBundleRef bundle = CFBundleGetMainBundle(); - CFURLRef bundleURL = CFBundleCopyBundleURL(bundle); - char path[PATH_MAX]; - Boolean success = CFURLGetFileSystemRepresentation(bundleURL, TRUE, (UInt8 *)path, PATH_MAX); - assert(success); - CFRelease(bundleURL); - - chdir(dirname(path)); - } + fixCwd(); #endif pluginInit();