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.

301 lines
8.6KB

  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. reload();
  37. projectDefaults.addListener (this);
  38. }
  39. StoredSettings::~StoredSettings()
  40. {
  41. projectDefaults.removeListener (this);
  42. flush();
  43. }
  44. PropertiesFile& StoredSettings::getGlobalProperties()
  45. {
  46. return *propertyFiles.getUnchecked (0);
  47. }
  48. static PropertiesFile* createPropsFile (const String& filename)
  49. {
  50. return new PropertiesFile (ProjucerApplication::getApp()
  51. .getPropertyFileOptionsFor (filename));
  52. }
  53. PropertiesFile& StoredSettings::getProjectProperties (const String& projectUID)
  54. {
  55. const String filename ("Introjucer_Project_" + projectUID);
  56. for (int i = propertyFiles.size(); --i >= 0;)
  57. {
  58. PropertiesFile* const props = propertyFiles.getUnchecked(i);
  59. if (props->getFile().getFileNameWithoutExtension() == filename)
  60. return *props;
  61. }
  62. PropertiesFile* p = createPropsFile (filename);
  63. propertyFiles.add (p);
  64. return *p;
  65. }
  66. void StoredSettings::updateGlobalPreferences()
  67. {
  68. // update 'invisible' global settings
  69. updateRecentFiles();
  70. updateKeyMappings();
  71. }
  72. void StoredSettings::updateRecentFiles()
  73. {
  74. getGlobalProperties().setValue ("recentFiles", recentFiles.toString());
  75. }
  76. void StoredSettings::updateKeyMappings()
  77. {
  78. getGlobalProperties().removeValue ("keyMappings");
  79. if (ApplicationCommandManager* commandManager = ProjucerApplication::getApp().commandManager)
  80. {
  81. const ScopedPointer<XmlElement> keys (commandManager->getKeyMappings()->createXml (true));
  82. if (keys != nullptr)
  83. getGlobalProperties().setValue ("keyMappings", keys);
  84. }
  85. }
  86. void StoredSettings::flush()
  87. {
  88. updateGlobalPreferences();
  89. saveSwatchColours();
  90. for (int i = propertyFiles.size(); --i >= 0;)
  91. propertyFiles.getUnchecked(i)->saveIfNeeded();
  92. }
  93. void StoredSettings::reload()
  94. {
  95. propertyFiles.clear();
  96. propertyFiles.add (createPropsFile ("Introjucer"));
  97. ScopedPointer<XmlElement> projectDefaultsXml (propertyFiles.getFirst()->getXmlValue ("PROJECT_DEFAULT_SETTINGS"));
  98. if (projectDefaultsXml != nullptr)
  99. projectDefaults = ValueTree::fromXml (*projectDefaultsXml);
  100. // recent files...
  101. recentFiles.restoreFromString (getGlobalProperties().getValue ("recentFiles"));
  102. recentFiles.removeNonExistentFiles();
  103. loadSwatchColours();
  104. }
  105. Array<File> StoredSettings::getLastProjects()
  106. {
  107. StringArray s;
  108. s.addTokens (getGlobalProperties().getValue ("lastProjects"), "|", "");
  109. Array<File> f;
  110. for (int i = 0; i < s.size(); ++i)
  111. f.add (File (s[i]));
  112. return f;
  113. }
  114. void StoredSettings::setLastProjects (const Array<File>& files)
  115. {
  116. StringArray s;
  117. for (int i = 0; i < files.size(); ++i)
  118. s.add (files.getReference(i).getFullPathName());
  119. getGlobalProperties().setValue ("lastProjects", s.joinIntoString ("|"));
  120. }
  121. //==============================================================================
  122. void StoredSettings::loadSwatchColours()
  123. {
  124. swatchColours.clear();
  125. #define COL(col) Colours::col,
  126. const Colour colours[] =
  127. {
  128. #include "jucer_Colours.h"
  129. Colours::transparentBlack
  130. };
  131. #undef COL
  132. const int numSwatchColours = 24;
  133. PropertiesFile& props = getGlobalProperties();
  134. for (int i = 0; i < numSwatchColours; ++i)
  135. swatchColours.add (Colour::fromString (props.getValue ("swatchColour" + String (i),
  136. colours [2 + i].toString())));
  137. }
  138. void StoredSettings::saveSwatchColours()
  139. {
  140. PropertiesFile& props = getGlobalProperties();
  141. for (int i = 0; i < swatchColours.size(); ++i)
  142. props.setValue ("swatchColour" + String (i), swatchColours.getReference(i).toString());
  143. }
  144. int StoredSettings::ColourSelectorWithSwatches::getNumSwatches() const
  145. {
  146. return getAppSettings().swatchColours.size();
  147. }
  148. Colour StoredSettings::ColourSelectorWithSwatches::getSwatchColour (int index) const
  149. {
  150. return getAppSettings().swatchColours [index];
  151. }
  152. void StoredSettings::ColourSelectorWithSwatches::setSwatchColour (int index, const Colour& newColour)
  153. {
  154. getAppSettings().swatchColours.set (index, newColour);
  155. }
  156. //==============================================================================
  157. static bool doesSDKPathContainFile (const File& relativeTo, const String& path, const String& fileToCheckFor)
  158. {
  159. String actualPath = path.replace ("${user.home}", File::getSpecialLocation (File::userHomeDirectory).getFullPathName());
  160. return relativeTo.getChildFile (actualPath + "/" + fileToCheckFor).existsAsFile();
  161. }
  162. Value StoredSettings::getGlobalPath (const Identifier& key, DependencyPathOS os)
  163. {
  164. Value v (projectDefaults.getPropertyAsValue (key, nullptr));
  165. if (v.toString().isEmpty())
  166. {
  167. auto defaultPath = getFallbackPath (key, os);
  168. if (os == TargetOS::getThisOS())
  169. v = defaultPath;
  170. }
  171. return v;
  172. }
  173. String StoredSettings::getFallbackPath (const Identifier& key, DependencyPathOS os)
  174. {
  175. if (key == Ids::vst3Path)
  176. return os == TargetOS::windows ? "c:\\SDKs\\VST_SDK\\VST3_SDK"
  177. : "~/SDKs/VST_SDK/VST3_SDK";
  178. if (key == Ids::rtasPath)
  179. {
  180. if (os == TargetOS::windows) return "c:\\SDKs\\PT_90_SDK";
  181. if (os == TargetOS::osx) return "~/SDKs/PT_90_SDK";
  182. // no RTAS on this OS!
  183. jassertfalse;
  184. return {};
  185. }
  186. if (key == Ids::aaxPath)
  187. {
  188. if (os == TargetOS::windows) return "c:\\SDKs\\AAX";
  189. if (os == TargetOS::osx) return "~/SDKs/AAX" ;
  190. // no AAX on this OS!
  191. jassertfalse;
  192. return {};
  193. }
  194. if (key == Ids::androidSDKPath)
  195. return "${user.home}/Library/Android/sdk";
  196. if (key == Ids::androidNDKPath)
  197. return "${user.home}/Library/Android/sdk/ndk-bundle";
  198. // didn't recognise the key provided!
  199. jassertfalse;
  200. return {};
  201. }
  202. bool StoredSettings::isGlobalPathValid (const File& relativeTo, const Identifier& key, const String& path)
  203. {
  204. String fileToCheckFor;
  205. if (key == Ids::vst3Path)
  206. {
  207. fileToCheckFor = "base/source/baseiids.cpp";
  208. }
  209. else if (key == Ids::rtasPath)
  210. {
  211. fileToCheckFor = "AlturaPorts/TDMPlugIns/PlugInLibrary/EffectClasses/CEffectProcessMIDI.cpp";
  212. }
  213. else if (key == Ids::aaxPath)
  214. {
  215. fileToCheckFor = "Interfaces/AAX_Exports.cpp";
  216. }
  217. else if (key == Ids::androidSDKPath)
  218. {
  219. #if JUCE_WINDOWS
  220. fileToCheckFor = "platform-tools/adb.exe";
  221. #else
  222. fileToCheckFor = "platform-tools/adb";
  223. #endif
  224. }
  225. else if (key == Ids::androidNDKPath)
  226. {
  227. #if JUCE_WINDOWS
  228. fileToCheckFor = "ndk-depends.cmd";
  229. #else
  230. fileToCheckFor = "ndk-depends";
  231. #endif
  232. }
  233. else
  234. {
  235. // didn't recognise the key provided!
  236. jassertfalse;
  237. return false;
  238. }
  239. return doesSDKPathContainFile (relativeTo, path, fileToCheckFor);
  240. }