Audio plugin host https://kx.studio/carla
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.

juce_PropertiesFile.h 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. namespace juce
  20. {
  21. //==============================================================================
  22. /** Wrapper on a file that stores a list of key/value data pairs.
  23. Useful for storing application settings, etc. See the PropertySet class for
  24. the interfaces that read and write values.
  25. Not designed for very large amounts of data, as it keeps all the values in
  26. memory and writes them out to disk lazily when they are changed.
  27. Because this class derives from ChangeBroadcaster, ChangeListeners can be registered
  28. with it, and these will be signalled when a value changes.
  29. @see PropertySet
  30. */
  31. class JUCE_API PropertiesFile : public PropertySet,
  32. public ChangeBroadcaster,
  33. private Timer
  34. {
  35. public:
  36. //==============================================================================
  37. enum StorageFormat
  38. {
  39. storeAsBinary,
  40. storeAsCompressedBinary,
  41. storeAsXML
  42. };
  43. //==============================================================================
  44. struct JUCE_API Options
  45. {
  46. /** Creates an empty Options structure.
  47. You'll need to fill-in the data members appropriately before using this structure.
  48. */
  49. Options();
  50. /** The name of your application - this is used to help generate the path and filename
  51. at which the properties file will be stored. */
  52. String applicationName;
  53. /** The suffix to use for your properties file.
  54. It doesn't really matter what this is - you may want to use ".settings" or
  55. ".properties" or something. If the suffix includes the prefixing dot (for example
  56. ".settings") then the suffix of applicationName will be replaced with your suffix
  57. ("MyApp.exe" -> "MyApp.settings"). If your filenameSuffix does NOT include the dot,
  58. then the suffix will be appended to the applicationName ("MyApp.exe" ->
  59. "MyApp.exe.settings").
  60. */
  61. String filenameSuffix;
  62. /** The name of a subfolder in which you'd like your properties file to live.
  63. See the getDefaultFile() method for more details about how this is used.
  64. */
  65. String folderName;
  66. /** If you're using properties files on a Mac, you must set this value - failure to
  67. do so will cause a runtime assertion.
  68. The PropertiesFile class always used to put its settings files in "Library/Preferences", but Apple
  69. have changed their advice, and now stipulate that settings should go in "Library/Application Support".
  70. Because older apps would be broken by a silent change in this class's behaviour, you must now
  71. explicitly set the osxLibrarySubFolder value to indicate which path you want to use.
  72. In newer apps, you should always set this to "Application Support" or
  73. "Application Support/YourSubFolderName".
  74. If your app needs to load settings files that were created by older versions of juce and
  75. you want to maintain backwards-compatibility, then you can set this to "Preferences".
  76. But.. for better Apple-compliance, the recommended approach would be to write some code that
  77. finds your old settings files in ~/Library/Preferences, moves them to ~/Library/Application Support,
  78. and then uses the new path.
  79. */
  80. String osxLibrarySubFolder;
  81. /** If true, the file will be created in a location that's shared between users.
  82. The default constructor initialises this value to false.
  83. */
  84. bool commonToAllUsers;
  85. /** If true, this means that property names are matched in a case-insensitive manner.
  86. See the PropertySet constructor for more info.
  87. The default constructor initialises this value to false.
  88. */
  89. bool ignoreCaseOfKeyNames;
  90. /** If set to true, this prevents the file from being written to disk. */
  91. bool doNotSave;
  92. /** If this is zero or greater, then after a value is changed, the object will wait
  93. for this amount of time and then save the file. If this zero, the file will be
  94. written to disk immediately on being changed (which might be slow, as it'll re-write
  95. synchronously each time a value-change method is called). If it is less than zero,
  96. the file won't be saved until save() or saveIfNeeded() are explicitly called.
  97. The default constructor sets this to a reasonable value of a few seconds, so you
  98. only need to change it if you need a special case.
  99. */
  100. int millisecondsBeforeSaving;
  101. /** Specifies whether the file should be written as XML, binary, etc.
  102. The default constructor sets this to storeAsXML, so you only need to set it explicitly
  103. if you want to use a different format.
  104. */
  105. StorageFormat storageFormat;
  106. /** An optional InterprocessLock object that will be used to prevent multiple threads or
  107. processes from writing to the file at the same time. The PropertiesFile will keep a
  108. pointer to this object but will not take ownership of it - the caller is responsible for
  109. making sure that the lock doesn't get deleted before the PropertiesFile has been deleted.
  110. The default constructor initialises this value to nullptr, so you don't need to touch it
  111. unless you want to use a lock.
  112. */
  113. InterProcessLock* processLock;
  114. /** This can be called to suggest a file that should be used, based on the values
  115. in this structure.
  116. So on a Mac, this will return a file called:
  117. ~/Library/[osxLibrarySubFolder]/[folderName]/[applicationName].[filenameSuffix]
  118. On Windows it'll return something like:
  119. C:\\Documents and Settings\\username\\Application Data\\[folderName]\\[applicationName].[filenameSuffix]
  120. On Linux it'll return
  121. ~/[folderName]/[applicationName].[filenameSuffix]
  122. If the folderName variable is empty, it'll use the app name for this (or omit the
  123. folder name on the Mac).
  124. The paths will also vary depending on whether commonToAllUsers is true.
  125. */
  126. File getDefaultFile() const;
  127. };
  128. //==============================================================================
  129. /** Creates a PropertiesFile object.
  130. The file used will be chosen by calling PropertiesFile::Options::getDefaultFile()
  131. for the options provided. To set the file explicitly, use the other constructor.
  132. */
  133. explicit PropertiesFile (const Options& options);
  134. /** Creates a PropertiesFile object.
  135. Unlike the other constructor, this one allows you to explicitly set the file that you
  136. want to be used, rather than using the default one.
  137. */
  138. PropertiesFile (const File& file,
  139. const Options& options);
  140. /** Destructor.
  141. When deleted, the file will first call saveIfNeeded() to flush any changes to disk.
  142. */
  143. ~PropertiesFile();
  144. //==============================================================================
  145. /** Returns true if this file was created from a valid (or non-existent) file.
  146. If the file failed to load correctly because it was corrupt or had insufficient
  147. access, this will be false.
  148. */
  149. bool isValidFile() const noexcept { return loadedOk; }
  150. //==============================================================================
  151. /** This will flush all the values to disk if they've changed since the last
  152. time they were saved.
  153. Returns false if it fails to write to the file for some reason (maybe because
  154. it's read-only or the directory doesn't exist or something).
  155. @see save
  156. */
  157. bool saveIfNeeded();
  158. /** This will force a write-to-disk of the current values, regardless of whether
  159. anything has changed since the last save.
  160. Returns false if it fails to write to the file for some reason (maybe because
  161. it's read-only or the directory doesn't exist or something).
  162. @see saveIfNeeded
  163. */
  164. bool save();
  165. /** Returns true if the properties have been altered since the last time they were saved.
  166. The file is flagged as needing to be saved when you change a value, but you can
  167. explicitly set this flag with setNeedsToBeSaved().
  168. */
  169. bool needsToBeSaved() const;
  170. /** Explicitly sets the flag to indicate whether the file needs saving or not.
  171. @see needsToBeSaved
  172. */
  173. void setNeedsToBeSaved (bool needsToBeSaved);
  174. /** Attempts to reload the settings from the file. */
  175. bool reload();
  176. //==============================================================================
  177. /** Returns the file that's being used. */
  178. const File& getFile() const noexcept { return file; }
  179. protected:
  180. /** @internal */
  181. void propertyChanged() override;
  182. private:
  183. //==============================================================================
  184. File file;
  185. Options options;
  186. bool loadedOk, needsWriting;
  187. typedef const ScopedPointer<InterProcessLock::ScopedLockType> ProcessScopedLock;
  188. InterProcessLock::ScopedLockType* createProcessLock() const;
  189. void timerCallback() override;
  190. bool saveAsXml();
  191. bool saveAsBinary();
  192. bool loadAsXml();
  193. bool loadAsBinary();
  194. bool loadAsBinary (InputStream&);
  195. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertiesFile)
  196. };
  197. } // namespace juce