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.

166 lines
4.2KB

  1. #include <asset.hpp>
  2. #include <system.hpp>
  3. #include <settings.hpp>
  4. #include <string.hpp>
  5. #include <plugin/Plugin.hpp>
  6. #include <app/common.hpp>
  7. #if defined ARCH_MAC
  8. #include <CoreFoundation/CoreFoundation.h>
  9. #include <CoreServices/CoreServices.h>
  10. #include <pwd.h>
  11. #endif
  12. #if defined ARCH_WIN
  13. #include <Windows.h>
  14. #include <Shlobj.h>
  15. #include <Shlwapi.h>
  16. #endif
  17. #if defined ARCH_LIN
  18. #include <unistd.h>
  19. #include <sys/types.h>
  20. #include <pwd.h>
  21. #endif
  22. namespace rack {
  23. namespace asset {
  24. void init() {
  25. // Get system dir
  26. if (systemDir.empty()) {
  27. if (settings::devMode) {
  28. systemDir = ".";
  29. }
  30. else {
  31. #if defined ARCH_MAC
  32. CFBundleRef bundle = CFBundleGetMainBundle();
  33. assert(bundle);
  34. // Check if we're running as a command-line program or an app bundle.
  35. CFURLRef bundleUrl = CFBundleCopyBundleURL(bundle);
  36. // Thanks Ken Thomases! https://stackoverflow.com/a/58369256/272642
  37. CFStringRef uti;
  38. if (CFURLCopyResourcePropertyForKey(bundleUrl, kCFURLTypeIdentifierKey, &uti, NULL) && uti && UTTypeConformsTo(uti, kUTTypeApplicationBundle)) {
  39. char bundleBuf[PATH_MAX];
  40. Boolean success = CFURLGetFileSystemRepresentation(bundleUrl, TRUE, (UInt8*) bundleBuf, sizeof(bundleBuf));
  41. assert(success);
  42. bundlePath = bundleBuf;
  43. }
  44. CFURLRef resourcesUrl = CFBundleCopyResourcesDirectoryURL(bundle);
  45. char resourcesBuf[PATH_MAX];
  46. Boolean success = CFURLGetFileSystemRepresentation(resourcesUrl, TRUE, (UInt8*) resourcesBuf, sizeof(resourcesBuf));
  47. assert(success);
  48. CFRelease(resourcesUrl);
  49. systemDir = resourcesBuf;
  50. #endif
  51. #if defined ARCH_WIN
  52. // Get path to executable
  53. wchar_t moduleBufW[MAX_PATH];
  54. DWORD length = GetModuleFileNameW(NULL, moduleBufW, LENGTHOF(moduleBufW));
  55. assert(length > 0);
  56. // Get folder of executable
  57. PathRemoveFileSpecW(moduleBufW);
  58. // Convert to short path to avoid Unicode
  59. wchar_t moduleBufShortW[MAX_PATH];
  60. GetShortPathNameW(moduleBufW, moduleBufShortW, LENGTHOF(moduleBufShortW));
  61. systemDir = string::fromWstring(moduleBufShortW);
  62. #endif
  63. #if defined ARCH_LIN
  64. // Users should launch Rack from their terminal in the system directory
  65. systemDir = ".";
  66. #endif
  67. }
  68. }
  69. // Get user dir
  70. if (userDir.empty()) {
  71. if (settings::devMode) {
  72. userDir = ".";
  73. }
  74. else {
  75. #if defined ARCH_WIN
  76. // Get "My Documents" folder
  77. wchar_t documentsBufW[MAX_PATH] = L".";
  78. HRESULT result = SHGetFolderPathW(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, documentsBufW);
  79. assert(result == S_OK);
  80. // Convert to short path to avoid Unicode
  81. wchar_t documentsBufShortW[MAX_PATH];
  82. GetShortPathNameW(documentsBufW, documentsBufShortW, LENGTHOF(documentsBufShortW));
  83. userDir = string::fromWstring(documentsBufShortW);
  84. userDir += "/Rack";
  85. #endif
  86. #if defined ARCH_MAC
  87. // Get home directory
  88. struct passwd* pw = getpwuid(getuid());
  89. assert(pw);
  90. userDir = pw->pw_dir;
  91. userDir += "/Documents/Rack";
  92. #endif
  93. #if defined ARCH_LIN
  94. // Get home directory
  95. const char* homeBuf = getenv("HOME");
  96. if (!homeBuf) {
  97. struct passwd* pw = getpwuid(getuid());
  98. assert(pw);
  99. homeBuf = pw->pw_dir;
  100. }
  101. userDir = homeBuf;
  102. userDir += "/.Rack";
  103. #endif
  104. }
  105. }
  106. system::createDirectory(systemDir);
  107. system::createDirectory(userDir);
  108. // Set paths
  109. if (settings::devMode) {
  110. pluginsPath = userDir + "/plugins";
  111. settingsPath = userDir + "/settings.json";
  112. autosavePath = userDir + "/autosave.vcv";
  113. templatePath = userDir + "/template.vcv";
  114. }
  115. else {
  116. logPath = userDir + "/log.txt";
  117. pluginsPath = userDir + "/plugins-v" + app::ABI_VERSION;
  118. settingsPath = userDir + "/settings-v" + app::ABI_VERSION + ".json";
  119. autosavePath = userDir + "/autosave-v" + app::ABI_VERSION + ".vcv";
  120. templatePath = userDir + "/template-v" + app::ABI_VERSION + ".vcv";
  121. }
  122. }
  123. std::string system(std::string filename) {
  124. return systemDir + "/" + filename;
  125. }
  126. std::string user(std::string filename) {
  127. return userDir + "/" + filename;
  128. }
  129. std::string plugin(plugin::Plugin* plugin, std::string filename) {
  130. assert(plugin);
  131. return plugin->path + "/" + filename;
  132. }
  133. std::string systemDir;
  134. std::string userDir;
  135. std::string logPath;
  136. std::string pluginsPath;
  137. std::string settingsPath;
  138. std::string autosavePath;
  139. std::string templatePath;
  140. std::string bundlePath;
  141. } // namespace asset
  142. } // namespace rack