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.

269 lines
11KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE examples.
  4. Copyright (c) 2022 - Raw Material Software Limited
  5. The code included in this file is provided under the terms of the ISC license
  6. http://www.isc.org/downloads/software-support-policy/isc-license. Permission
  7. To use, copy, modify, and/or distribute this software for any purpose with or
  8. without fee is hereby granted provided that the above copyright notice and
  9. this permission notice appear in all copies.
  10. THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
  11. WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
  12. PURPOSE, ARE DISCLAIMED.
  13. ==============================================================================
  14. */
  15. #ifndef PIP_DEMO_UTILITIES_INCLUDED
  16. #define PIP_DEMO_UTILITIES_INCLUDED 1
  17. #include <JuceHeader.h>
  18. //==============================================================================
  19. /*
  20. This file contains a bunch of miscellaneous utilities that are
  21. used by the various demos.
  22. */
  23. //==============================================================================
  24. inline Colour getRandomColour (float brightness) noexcept
  25. {
  26. return Colour::fromHSV (Random::getSystemRandom().nextFloat(), 0.5f, brightness, 1.0f);
  27. }
  28. inline Colour getRandomBrightColour() noexcept { return getRandomColour (0.8f); }
  29. inline Colour getRandomDarkColour() noexcept { return getRandomColour (0.3f); }
  30. inline Colour getUIColourIfAvailable (LookAndFeel_V4::ColourScheme::UIColour uiColour, Colour fallback = Colour (0xff4d4d4d)) noexcept
  31. {
  32. if (auto* v4 = dynamic_cast<LookAndFeel_V4*> (&LookAndFeel::getDefaultLookAndFeel()))
  33. return v4->getCurrentColourScheme().getUIColour (uiColour);
  34. return fallback;
  35. }
  36. inline File getExamplesDirectory() noexcept
  37. {
  38. #ifdef PIP_JUCE_EXAMPLES_DIRECTORY
  39. MemoryOutputStream mo;
  40. auto success = Base64::convertFromBase64 (mo, JUCE_STRINGIFY (PIP_JUCE_EXAMPLES_DIRECTORY));
  41. ignoreUnused (success);
  42. jassert (success);
  43. return mo.toString();
  44. #elif defined PIP_JUCE_EXAMPLES_DIRECTORY_STRING
  45. return File { CharPointer_UTF8 { PIP_JUCE_EXAMPLES_DIRECTORY_STRING } };
  46. #else
  47. auto currentFile = File::getSpecialLocation (File::SpecialLocationType::currentApplicationFile);
  48. auto exampleDir = currentFile.getParentDirectory().getChildFile ("examples");
  49. if (exampleDir.exists())
  50. return exampleDir;
  51. // keep track of the number of parent directories so we don't go on endlessly
  52. for (int numTries = 0; numTries < 15; ++numTries)
  53. {
  54. if (currentFile.getFileName() == "examples")
  55. return currentFile;
  56. const auto sibling = currentFile.getSiblingFile ("examples");
  57. if (sibling.exists())
  58. return sibling;
  59. currentFile = currentFile.getParentDirectory();
  60. }
  61. return currentFile;
  62. #endif
  63. }
  64. inline std::unique_ptr<InputStream> createAssetInputStream (const char* resourcePath)
  65. {
  66. #if JUCE_ANDROID
  67. ZipFile apkZip (File::getSpecialLocation (File::invokedExecutableFile));
  68. return std::unique_ptr<InputStream> (apkZip.createStreamForEntry (apkZip.getIndexOfFileName ("assets/" + String (resourcePath))));
  69. #else
  70. #if JUCE_IOS
  71. auto assetsDir = File::getSpecialLocation (File::currentExecutableFile)
  72. .getParentDirectory().getChildFile ("Assets");
  73. #elif JUCE_MAC
  74. auto assetsDir = File::getSpecialLocation (File::currentExecutableFile)
  75. .getParentDirectory().getParentDirectory().getChildFile ("Resources").getChildFile ("Assets");
  76. if (! assetsDir.exists())
  77. assetsDir = getExamplesDirectory().getChildFile ("Assets");
  78. #else
  79. auto assetsDir = getExamplesDirectory().getChildFile ("Assets");
  80. #endif
  81. auto resourceFile = assetsDir.getChildFile (resourcePath);
  82. jassert (resourceFile.existsAsFile());
  83. return resourceFile.createInputStream();
  84. #endif
  85. }
  86. inline Image getImageFromAssets (const char* assetName)
  87. {
  88. auto hashCode = (String (assetName) + "@juce_demo_assets").hashCode64();
  89. auto img = ImageCache::getFromHashCode (hashCode);
  90. if (img.isNull())
  91. {
  92. std::unique_ptr<InputStream> juceIconStream (createAssetInputStream (assetName));
  93. if (juceIconStream == nullptr)
  94. return {};
  95. img = ImageFileFormat::loadFrom (*juceIconStream);
  96. ImageCache::addImageToCache (img, hashCode);
  97. }
  98. return img;
  99. }
  100. inline String loadEntireAssetIntoString (const char* assetName)
  101. {
  102. std::unique_ptr<InputStream> input (createAssetInputStream (assetName));
  103. if (input == nullptr)
  104. return {};
  105. return input->readString();
  106. }
  107. //==============================================================================
  108. inline Path getJUCELogoPath()
  109. {
  110. return Drawable::parseSVGPath (
  111. "M72.87 84.28A42.36 42.36 0 0130.4 42.14a42.48 42.48 0 0184.95 0 42.36 42.36 0 01-42.48 42.14zm0-78.67A36.74 36.74 0 0036 42.14a36.88 36.88 0 0073.75 0A36.75 36.75 0 0072.87 5.61z"
  112. "M77.62 49.59a177.77 177.77 0 008.74 18.93A4.38 4.38 0 0092.69 70a34.5 34.5 0 008.84-9 4.3 4.3 0 00-2.38-6.49A176.73 176.73 0 0180 47.32a1.78 1.78 0 00-2.38 2.27zM81.05 44.27a169.68 169.68 0 0020.13 7.41 4.39 4.39 0 005.52-3.41 34.42 34.42 0 00.55-6.13 33.81 33.81 0 00-.67-6.72 4.37 4.37 0 00-6.31-3A192.32 192.32 0 0181.1 41a1.76 1.76 0 00-.05 3.27zM74.47 50.44a1.78 1.78 0 00-3.29 0 165.54 165.54 0 00-7.46 19.89 4.33 4.33 0 003.47 5.48 35.49 35.49 0 005.68.46 34.44 34.44 0 007.13-.79 4.32 4.32 0 003-6.25 187.83 187.83 0 01-8.53-18.79zM71.59 34.12a1.78 1.78 0 003.29.05 163.9 163.9 0 007.52-20.11A4.34 4.34 0 0079 8.59a35.15 35.15 0 00-13.06.17 4.32 4.32 0 00-3 6.26 188.41 188.41 0 018.65 19.1zM46.32 30.3a176.2 176.2 0 0120 7.48 1.78 1.78 0 002.37-2.28 180.72 180.72 0 00-9.13-19.84 4.38 4.38 0 00-6.33-1.47 34.27 34.27 0 00-9.32 9.65 4.31 4.31 0 002.41 6.46zM68.17 49.18a1.77 1.77 0 00-2.29-2.34 181.71 181.71 0 00-19.51 8.82A4.3 4.3 0 0044.91 62a34.36 34.36 0 009.42 8.88 4.36 4.36 0 006.5-2.38 175.11 175.11 0 017.34-19.32zM77.79 35.59a1.78 1.78 0 002.3 2.35 182.51 182.51 0 0019.6-8.88 4.3 4.3 0 001.5-6.25 34.4 34.4 0 00-9.41-9.14A4.36 4.36 0 0085.24 16a174.51 174.51 0 01-7.45 19.59zM64.69 40.6a167.72 167.72 0 00-20.22-7.44A4.36 4.36 0 0039 36.6a33.68 33.68 0 00-.45 5.54 34 34 0 00.81 7.4 4.36 4.36 0 006.28 2.84 189.19 189.19 0 0119-8.52 1.76 1.76 0 00.05-3.26zM20 129.315c0 5-2.72 8.16-7.11 8.16-2.37 0-4.17-1-6.2-3.56l-.69-.78-6 5 .57.76c3.25 4.36 7.16 6.39 12.31 6.39 9 0 15.34-6.57 15.34-16v-28.1H20zM61.69 126.505c0 6.66-3.76 11-9.57 11-5.81 0-9.56-4.31-9.56-11v-25.32h-8.23v25.69c0 10.66 7.4 18.4 17.6 18.4 10 0 17.61-7.72 18-18.4v-25.69h-8.24zM106.83 134.095c-3.58 2.43-6.18 3.38-9.25 3.38a14.53 14.53 0 010-29c3.24 0 5.66.88 9.25 3.38l.76.53 4.78-6-.75-.62a22.18 22.18 0 00-14.22-5.1 22.33 22.33 0 100 44.65 21.53 21.53 0 0014.39-5.08l.81-.64-5-6zM145.75 137.285h-19.06v-10.72h18.3v-7.61h-18.3v-10.16h19.06v-7.61h-27.28v43.53h27.28z"
  113. "M68.015 83.917c-7.723-.902-15.472-4.123-21.566-8.966-8.475-6.736-14.172-16.823-15.574-27.575C29.303 35.31 33.538 22.7 42.21 13.631 49.154 6.368 58.07 1.902 68.042.695c2.15-.26 7.524-.26 9.675 0 12.488 1.512 23.464 8.25 30.437 18.686 8.332 12.471 9.318 28.123 2.605 41.368-2.28 4.5-4.337 7.359-7.85 10.909A42.273 42.273 0 0177.613 83.92c-2.027.227-7.644.225-9.598-.003zm7.823-5.596c8.435-.415 17.446-4.678 23.683-11.205 5.976-6.254 9.35-13.723 10.181-22.537.632-6.705-1.346-14.948-5.065-21.108C98.88 13.935 89.397 7.602 78.34 5.906c-2.541-.39-8.398-.386-10.96.006C53.54 8.034 42.185 17.542 37.81 30.67c-2.807 8.426-2.421 17.267 1.11 25.444 4.877 11.297 14.959 19.41 26.977 21.709 2.136.408 6.1.755 7.377.645.325-.028 1.48-.094 2.564-.147z"
  114. );
  115. }
  116. //==============================================================================
  117. #if JUCE_MODULE_AVAILABLE_juce_gui_extra
  118. inline CodeEditorComponent::ColourScheme getDarkCodeEditorColourScheme()
  119. {
  120. struct Type
  121. {
  122. const char* name;
  123. juce::uint32 colour;
  124. };
  125. const Type types[] =
  126. {
  127. { "Error", 0xffe60000 },
  128. { "Comment", 0xff72d20c },
  129. { "Keyword", 0xffee6f6f },
  130. { "Operator", 0xffc4eb19 },
  131. { "Identifier", 0xffcfcfcf },
  132. { "Integer", 0xff42c8c4 },
  133. { "Float", 0xff885500 },
  134. { "String", 0xffbc45dd },
  135. { "Bracket", 0xff058202 },
  136. { "Punctuation", 0xffcfbeff },
  137. { "Preprocessor Text", 0xfff8f631 }
  138. };
  139. CodeEditorComponent::ColourScheme cs;
  140. for (auto& t : types)
  141. cs.set (t.name, Colour (t.colour));
  142. return cs;
  143. }
  144. inline CodeEditorComponent::ColourScheme getLightCodeEditorColourScheme()
  145. {
  146. struct Type
  147. {
  148. const char* name;
  149. juce::uint32 colour;
  150. };
  151. const Type types[] =
  152. {
  153. { "Error", 0xffcc0000 },
  154. { "Comment", 0xff00aa00 },
  155. { "Keyword", 0xff0000cc },
  156. { "Operator", 0xff225500 },
  157. { "Identifier", 0xff000000 },
  158. { "Integer", 0xff880000 },
  159. { "Float", 0xff885500 },
  160. { "String", 0xff990099 },
  161. { "Bracket", 0xff000055 },
  162. { "Punctuation", 0xff004400 },
  163. { "Preprocessor Text", 0xff660000 }
  164. };
  165. CodeEditorComponent::ColourScheme cs;
  166. for (auto& t : types)
  167. cs.set (t.name, Colour (t.colour));
  168. return cs;
  169. }
  170. #endif
  171. //==============================================================================
  172. // This is basically a sawtooth wave generator - maps a value that bounces between
  173. // 0.0 and 1.0 at a random speed
  174. struct BouncingNumber
  175. {
  176. virtual ~BouncingNumber() = default;
  177. float getValue() const
  178. {
  179. double v = fmod (phase + speed * Time::getMillisecondCounterHiRes(), 2.0);
  180. return (float) (v >= 1.0 ? (2.0 - v) : v);
  181. }
  182. protected:
  183. double speed = 0.0004 + 0.0007 * Random::getSystemRandom().nextDouble(),
  184. phase = Random::getSystemRandom().nextDouble();
  185. };
  186. struct SlowerBouncingNumber final : public BouncingNumber
  187. {
  188. SlowerBouncingNumber()
  189. {
  190. speed *= 0.3;
  191. }
  192. };
  193. inline std::unique_ptr<InputSource> makeInputSource (const URL& url)
  194. {
  195. if (const auto doc = AndroidDocument::fromDocument (url))
  196. return std::make_unique<AndroidDocumentInputSource> (doc);
  197. #if ! JUCE_IOS
  198. if (url.isLocalFile())
  199. return std::make_unique<FileInputSource> (url.getLocalFile());
  200. #endif
  201. return std::make_unique<URLInputSource> (url);
  202. }
  203. inline std::unique_ptr<OutputStream> makeOutputStream (const URL& url)
  204. {
  205. if (const auto doc = AndroidDocument::fromDocument (url))
  206. return doc.createOutputStream();
  207. #if ! JUCE_IOS
  208. if (url.isLocalFile())
  209. return url.getLocalFile().createOutputStream();
  210. #endif
  211. return url.createOutputStream();
  212. }
  213. #endif // PIP_DEMO_UTILITIES_INCLUDED