The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

329 lines
9.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../jucer_Headers.h"
  20. #include "jucer_StoredSettings.h"
  21. #include "../Application/jucer_Application.h"
  22. #include "../Application/jucer_GlobalPreferences.h"
  23. //==============================================================================
  24. StoredSettings& getAppSettings()
  25. {
  26. return *ProjucerApplication::getApp().settings;
  27. }
  28. PropertiesFile& getGlobalProperties()
  29. {
  30. return getAppSettings().getGlobalProperties();
  31. }
  32. //==============================================================================
  33. StoredSettings::StoredSettings()
  34. : appearance (true), projectDefaults ("PROJECT_DEFAULT_SETTINGS")
  35. {
  36. updateOldProjectSettingsFiles();
  37. reload();
  38. projectDefaults.addListener (this);
  39. }
  40. StoredSettings::~StoredSettings()
  41. {
  42. projectDefaults.removeListener (this);
  43. flush();
  44. }
  45. PropertiesFile& StoredSettings::getGlobalProperties()
  46. {
  47. return *propertyFiles.getUnchecked (0);
  48. }
  49. static PropertiesFile* createPropsFile (const String& filename, bool isProjectSettings)
  50. {
  51. return new PropertiesFile (ProjucerApplication::getApp()
  52. .getPropertyFileOptionsFor (filename, isProjectSettings));
  53. }
  54. PropertiesFile& StoredSettings::getProjectProperties (const String& projectUID)
  55. {
  56. const auto filename = String ("Projucer_Project_" + projectUID);
  57. for (auto i = propertyFiles.size(); --i >= 0;)
  58. {
  59. auto* const props = propertyFiles.getUnchecked(i);
  60. if (props->getFile().getFileNameWithoutExtension() == filename)
  61. return *props;
  62. }
  63. auto* p = createPropsFile (filename, true);
  64. propertyFiles.add (p);
  65. return *p;
  66. }
  67. void StoredSettings::updateGlobalPreferences()
  68. {
  69. // update 'invisible' global settings
  70. updateRecentFiles();
  71. updateKeyMappings();
  72. }
  73. void StoredSettings::updateRecentFiles()
  74. {
  75. getGlobalProperties().setValue ("recentFiles", recentFiles.toString());
  76. }
  77. void StoredSettings::updateKeyMappings()
  78. {
  79. getGlobalProperties().removeValue ("keyMappings");
  80. if (auto* commandManager = ProjucerApplication::getApp().commandManager.get())
  81. {
  82. const ScopedPointer<XmlElement> keys (commandManager->getKeyMappings()->createXml (true));
  83. if (keys != nullptr)
  84. getGlobalProperties().setValue ("keyMappings", keys);
  85. }
  86. }
  87. void StoredSettings::flush()
  88. {
  89. updateGlobalPreferences();
  90. saveSwatchColours();
  91. for (auto i = propertyFiles.size(); --i >= 0;)
  92. propertyFiles.getUnchecked(i)->saveIfNeeded();
  93. }
  94. void StoredSettings::reload()
  95. {
  96. propertyFiles.clear();
  97. propertyFiles.add (createPropsFile ("Projucer", false));
  98. ScopedPointer<XmlElement> projectDefaultsXml (propertyFiles.getFirst()->getXmlValue ("PROJECT_DEFAULT_SETTINGS"));
  99. if (projectDefaultsXml != nullptr)
  100. projectDefaults = ValueTree::fromXml (*projectDefaultsXml);
  101. // recent files...
  102. recentFiles.restoreFromString (getGlobalProperties().getValue ("recentFiles"));
  103. recentFiles.removeNonExistentFiles();
  104. loadSwatchColours();
  105. }
  106. Array<File> StoredSettings::getLastProjects()
  107. {
  108. StringArray s;
  109. s.addTokens (getGlobalProperties().getValue ("lastProjects"), "|", "");
  110. Array<File> f;
  111. for (int i = 0; i < s.size(); ++i)
  112. f.add (File (s[i]));
  113. return f;
  114. }
  115. void StoredSettings::setLastProjects (const Array<File>& files)
  116. {
  117. StringArray s;
  118. for (int i = 0; i < files.size(); ++i)
  119. s.add (files.getReference(i).getFullPathName());
  120. getGlobalProperties().setValue ("lastProjects", s.joinIntoString ("|"));
  121. }
  122. void StoredSettings::updateOldProjectSettingsFiles()
  123. {
  124. // Global properties file hasn't been created yet so create a dummy file
  125. auto projucerSettingsDirectory = ProjucerApplication::getApp().getPropertyFileOptionsFor ("Dummy", false)
  126. .getDefaultFile().getParentDirectory();
  127. auto newProjectSettingsDir = projucerSettingsDirectory.getChildFile ("ProjectSettings");
  128. newProjectSettingsDir.createDirectory();
  129. DirectoryIterator iter (projucerSettingsDirectory, false, "*.settings");
  130. while (iter.next())
  131. {
  132. auto f = iter.getFile();
  133. auto oldFileName = f.getFileName();
  134. if (oldFileName.contains ("Introjucer"))
  135. {
  136. auto newFileName = oldFileName.replace ("Introjucer", "Projucer");
  137. if (oldFileName.contains ("_Project"))
  138. f.moveFileTo (f.getSiblingFile (newProjectSettingsDir.getFileName()).getChildFile (newFileName));
  139. else
  140. f.moveFileTo (f.getSiblingFile (newFileName));
  141. }
  142. }
  143. }
  144. //==============================================================================
  145. void StoredSettings::loadSwatchColours()
  146. {
  147. swatchColours.clear();
  148. #define COL(col) Colours::col,
  149. const Colour colours[] =
  150. {
  151. #include "jucer_Colours.h"
  152. Colours::transparentBlack
  153. };
  154. #undef COL
  155. const auto numSwatchColours = 24;
  156. auto& props = getGlobalProperties();
  157. for (auto i = 0; i < numSwatchColours; ++i)
  158. swatchColours.add (Colour::fromString (props.getValue ("swatchColour" + String (i),
  159. colours [2 + i].toString())));
  160. }
  161. void StoredSettings::saveSwatchColours()
  162. {
  163. auto& props = getGlobalProperties();
  164. for (auto i = 0; i < swatchColours.size(); ++i)
  165. props.setValue ("swatchColour" + String (i), swatchColours.getReference(i).toString());
  166. }
  167. int StoredSettings::ColourSelectorWithSwatches::getNumSwatches() const
  168. {
  169. return getAppSettings().swatchColours.size();
  170. }
  171. Colour StoredSettings::ColourSelectorWithSwatches::getSwatchColour (int index) const
  172. {
  173. return getAppSettings().swatchColours [index];
  174. }
  175. void StoredSettings::ColourSelectorWithSwatches::setSwatchColour (int index, const Colour& newColour)
  176. {
  177. getAppSettings().swatchColours.set (index, newColour);
  178. }
  179. //==============================================================================
  180. static bool doesSDKPathContainFile (const File& relativeTo, const String& path, const String& fileToCheckFor)
  181. {
  182. auto actualPath = path.replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());
  183. return relativeTo.getChildFile (actualPath + "/" + fileToCheckFor).existsAsFile();
  184. }
  185. Value StoredSettings::getGlobalPath (const Identifier& key, DependencyPathOS os)
  186. {
  187. auto v = projectDefaults.getPropertyAsValue (key, nullptr);
  188. if (v.toString().isEmpty())
  189. {
  190. auto defaultPath = getFallbackPath (key, os);
  191. if (os == TargetOS::getThisOS())
  192. v = defaultPath;
  193. }
  194. return v;
  195. }
  196. String StoredSettings::getFallbackPath (const Identifier& key, DependencyPathOS os)
  197. {
  198. if (key == Ids::vst3Path)
  199. return os == TargetOS::windows ? "c:\\SDKs\\VST_SDK\\VST3_SDK"
  200. : "~/SDKs/VST_SDK/VST3_SDK";
  201. if (key == Ids::rtasPath)
  202. {
  203. if (os == TargetOS::windows) return "c:\\SDKs\\PT_90_SDK";
  204. if (os == TargetOS::osx) return "~/SDKs/PT_90_SDK";
  205. // no RTAS on this OS!
  206. jassertfalse;
  207. return {};
  208. }
  209. if (key == Ids::aaxPath)
  210. {
  211. if (os == TargetOS::windows) return "c:\\SDKs\\AAX";
  212. if (os == TargetOS::osx) return "~/SDKs/AAX" ;
  213. // no AAX on this OS!
  214. jassertfalse;
  215. return {};
  216. }
  217. if (key == Ids::androidSDKPath)
  218. return "${user.home}/Library/Android/sdk";
  219. if (key == Ids::androidNDKPath)
  220. return "${user.home}/Library/Android/sdk/ndk-bundle";
  221. // didn't recognise the key provided!
  222. jassertfalse;
  223. return {};
  224. }
  225. bool StoredSettings::isGlobalPathValid (const File& relativeTo, const Identifier& key, const String& path)
  226. {
  227. String fileToCheckFor;
  228. if (key == Ids::vst3Path)
  229. {
  230. fileToCheckFor = "base/source/baseiids.cpp";
  231. }
  232. else if (key == Ids::rtasPath)
  233. {
  234. fileToCheckFor = "AlturaPorts/TDMPlugIns/PlugInLibrary/EffectClasses/CEffectProcessMIDI.cpp";
  235. }
  236. else if (key == Ids::aaxPath)
  237. {
  238. fileToCheckFor = "Interfaces/AAX_Exports.cpp";
  239. }
  240. else if (key == Ids::androidSDKPath)
  241. {
  242. #if JUCE_WINDOWS
  243. fileToCheckFor = "platform-tools/adb.exe";
  244. #else
  245. fileToCheckFor = "platform-tools/adb";
  246. #endif
  247. }
  248. else if (key == Ids::androidNDKPath)
  249. {
  250. #if JUCE_WINDOWS
  251. fileToCheckFor = "ndk-depends.cmd";
  252. #else
  253. fileToCheckFor = "ndk-depends";
  254. #endif
  255. }
  256. else
  257. {
  258. // didn't recognise the key provided!
  259. jassertfalse;
  260. return false;
  261. }
  262. return doesSDKPathContainFile (relativeTo, path, fileToCheckFor);
  263. }