| @@ -134,7 +134,17 @@ int main(int argc, char* argv[]) { | |||||
| if (!settings::devMode) { | if (!settings::devMode) { | ||||
| logger::logPath = asset::user("log.txt"); | logger::logPath = asset::user("log.txt"); | ||||
| } | } | ||||
| logger::init(); | |||||
| if (!logger::init()) { | |||||
| std::string msg = "Cannot access Rack's user folder " + asset::userDir; | |||||
| #if defined ARCH_MAC | |||||
| // The user likely clicked "Don't Allow" on the Documents Folder permissions dialog, so tell them how to allow it. | |||||
| msg += "\n\nMake sure Rack has permission by opening Apple's System Settings and enabling Privacy & Security > Files and Folders > " + APP_NAME + " " + APP_VERSION_MAJOR + " " + APP_EDITION_NAME + " > Documents Folder."; | |||||
| // Launch Apple's Privacy & Security settings | |||||
| std::system("open x-apple.systempreferences:com.apple.preference.security"); | |||||
| #endif | |||||
| osdialog_message(OSDIALOG_ERROR, OSDIALOG_OK, msg.c_str()); | |||||
| exit(1); | |||||
| } | |||||
| random::init(); | random::init(); | ||||
| // Test code | // Test code | ||||
| @@ -31,7 +31,8 @@ enum Level { | |||||
| FATAL_LEVEL | FATAL_LEVEL | ||||
| }; | }; | ||||
| PRIVATE void init(); | |||||
| /** Returns whether logger was successfully initialized. */ | |||||
| PRIVATE bool init(); | |||||
| PRIVATE void destroy(); | PRIVATE void destroy(); | ||||
| /** Do not use this function directly. Use the macros above. | /** Do not use this function directly. Use the macros above. | ||||
| Thread-safe, meaning messages cannot overlap each other in the log. | Thread-safe, meaning messages cannot overlap each other in the log. | ||||
| @@ -46,8 +46,10 @@ static bool isTruncated() { | |||||
| } | } | ||||
| void init() { | |||||
| assert(!outputFile); | |||||
| bool init() { | |||||
| if (outputFile) | |||||
| return true; | |||||
| std::lock_guard<std::mutex> lock(mutex); | std::lock_guard<std::mutex> lock(mutex); | ||||
| truncated = false; | truncated = false; | ||||
| @@ -61,13 +63,11 @@ void init() { | |||||
| outputFile = std::fopen(logPath.c_str(), "w"); | outputFile = std::fopen(logPath.c_str(), "w"); | ||||
| if (!outputFile) { | if (!outputFile) { | ||||
| std::fprintf(stderr, "Could not open log at %s\n", logPath.c_str()); | std::fprintf(stderr, "Could not open log at %s\n", logPath.c_str()); | ||||
| return false; | |||||
| } | } | ||||
| } | } | ||||
| // Redirect stdout and stderr to the file | |||||
| // Actually, disable this because we don't want to steal stdout/stderr from the DAW in Rack for DAWs. | |||||
| // dup2(fileno(outputFile), fileno(stdout)); | |||||
| // dup2(fileno(outputFile), fileno(stderr)); | |||||
| return true; | |||||
| } | } | ||||
| void destroy() { | void destroy() { | ||||