You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

159 lines
3.6KB

  1. #if defined ARCH_MAC
  2. #include <CoreFoundation/CoreFoundation.h>
  3. #include <CoreServices/CoreServices.h>
  4. #include <pwd.h>
  5. #endif
  6. #if defined ARCH_WIN
  7. #include <Windows.h>
  8. #include <Shlobj.h>
  9. #include <Shlwapi.h>
  10. #endif
  11. #if defined ARCH_LIN
  12. #include <unistd.h>
  13. #include <sys/types.h>
  14. #include <pwd.h>
  15. #endif
  16. #include <asset.hpp>
  17. #include <system.hpp>
  18. #include <settings.hpp>
  19. #include <string.hpp>
  20. #include <plugin/Plugin.hpp>
  21. #include <engine/Module.hpp>
  22. #include <app/common.hpp>
  23. namespace rack {
  24. namespace asset {
  25. static void initSystemDir() {
  26. if (!systemDir.empty())
  27. return;
  28. if (settings::devMode) {
  29. systemDir = system::getWorkingDirectory();
  30. return;
  31. }
  32. // Environment variable overrides
  33. const char* env = getenv("RACK_SYSTEM_DIR");
  34. if (env) {
  35. systemDir = env;
  36. return;
  37. }
  38. #if defined ARCH_MAC
  39. CFBundleRef bundle = CFBundleGetMainBundle();
  40. assert(bundle);
  41. // Check if we're running as a command-line program or an app bundle.
  42. CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
  43. // Thanks Ken Thomases! https://stackoverflow.com/a/58369256/272642
  44. CFStringRef uti;
  45. if (CFURLCopyResourcePropertyForKey(bundleUrl, kCFURLTypeIdentifierKey, &uti, NULL) && uti && UTTypeConformsTo(uti, kUTTypeApplicationBundle)) {
  46. char bundleBuf[PATH_MAX];
  47. Boolean success = CFURLGetFileSystemRepresentation(bundleUrl, TRUE, (UInt8*) bundleBuf, sizeof(bundleBuf));
  48. assert(success);
  49. bundlePath = bundleBuf;
  50. }
  51. CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle);
  52. char resourcesBuf[PATH_MAX];
  53. Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf));
  54. assert(success);
  55. CFRelease(resourcesUrl);
  56. systemDir = resourcesBuf;
  57. #endif
  58. #if defined ARCH_WIN
  59. // Get path to executable
  60. wchar_t moduleBufW[MAX_PATH] = L"";
  61. DWORD length = GetModuleFileNameW(NULL, moduleBufW, LENGTHOF(moduleBufW));
  62. assert(length > 0);
  63. // Get directory of executable
  64. PathRemoveFileSpecW(moduleBufW);
  65. systemDir = string::UTF16toUTF8(moduleBufW);
  66. #endif
  67. #if defined ARCH_LIN
  68. // Use the current working directory as the default path on Linux.
  69. systemDir = system::getWorkingDirectory();
  70. #endif
  71. }
  72. static void initUserDir() {
  73. if (!userDir.empty())
  74. return;
  75. if (settings::devMode) {
  76. userDir = systemDir;
  77. return;
  78. }
  79. // Environment variable overrides
  80. const char* env = getenv("RACK_USER_DIR");
  81. if (env) {
  82. userDir = env;
  83. return;
  84. }
  85. #if defined ARCH_WIN
  86. // Get "My Documents" path
  87. wchar_t documentsBufW[MAX_PATH] = L".";
  88. HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW);
  89. assert(result == S_OK);
  90. userDir = system::join(string::UTF16toUTF8(documentsBufW), "Rack" + APP_VERSION_MAJOR);
  91. #endif
  92. #if defined ARCH_MAC
  93. // Get home directory
  94. struct passwd* pw = getpwuid(getuid());
  95. assert(pw);
  96. userDir = system::join(pw->pw_dir, "Documents", "Rack" + APP_VERSION_MAJOR);
  97. #endif
  98. #if defined ARCH_LIN
  99. // Get home directory
  100. const char* homeBuf = getenv("HOME");
  101. if (!homeBuf) {
  102. struct passwd* pw = getpwuid(getuid());
  103. assert(pw);
  104. homeBuf = pw->pw_dir;
  105. }
  106. userDir = system::join(homeBuf, ".Rack" + APP_VERSION_MAJOR);
  107. #endif
  108. }
  109. void init() {
  110. initSystemDir();
  111. initUserDir();
  112. system::createDirectory(userDir);
  113. }
  114. std::string system(std::string filename) {
  115. return system::join(systemDir, filename);
  116. }
  117. std::string user(std::string filename) {
  118. return system::join(userDir, filename);
  119. }
  120. std::string plugin(plugin::Plugin* plugin, std::string filename) {
  121. assert(plugin);
  122. return system::join(plugin->path, filename);
  123. }
  124. std::string systemDir;
  125. std::string userDir;
  126. std::string bundlePath;
  127. } // namespace asset
  128. } // namespace rack