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.

315 lines
9.0KB

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