1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11 Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12
13 End User License Agreement: www.juce.com/juce-6-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24 */
25
26 #include <JuceHeader.h>
27 #include "../../../Assets/DemoUtilities.h"
28 #include "JUCEDemos.h"
29
30 //==============================================================================
getCategories()31 std::vector<JUCEDemos::DemoCategory>& JUCEDemos::getCategories()
32 {
33 static std::vector<DemoCategory> categories;
34 return categories;
35 }
36
getCategory(const String & name)37 JUCEDemos::DemoCategory& JUCEDemos::getCategory (const String& name)
38 {
39 auto& categories = getCategories();
40
41 for (auto& c : categories)
42 if (c.name == name)
43 return c;
44
45 std::vector<FileAndCallback> fc;
46 categories.push_back ({ name, fc });
47
48 return categories.back();
49 }
50
registerDemo(std::function<Component * ()> constructorCallback,const String & filePath,const String & category,bool isHeavyweight)51 void JUCEDemos::registerDemo (std::function<Component*()> constructorCallback, const String& filePath, const String& category, bool isHeavyweight)
52 {
53 #if JUCE_MAC
54 auto f = File::getSpecialLocation (File::currentExecutableFile)
55 .getParentDirectory().getParentDirectory().getChildFile ("Resources");
56 #else
57 auto f = findExamplesDirectoryFromExecutable (File::getSpecialLocation (File::currentApplicationFile));
58 #endif
59
60 #if ! (JUCE_ANDROID || JUCE_IOS)
61 if (f == File())
62 {
63 jassertfalse;
64 return;
65 }
66 #endif
67
68 getCategory (category).demos.push_back ({ f.getChildFile (filePath), constructorCallback, isHeavyweight });
69 }
70
findExamplesDirectoryFromExecutable(File exec)71 File JUCEDemos::findExamplesDirectoryFromExecutable (File exec)
72 {
73 int numTries = 15;
74 auto exampleDir = exec.getParentDirectory().getChildFile ("examples");
75
76 if (exampleDir.exists())
77 return exampleDir;
78
79 while (exec.getFileName() != "examples" && numTries-- > 0)
80 exec = exec.getParentDirectory();
81 if (exec.getFileName() == "examples")
82 return exec;
83 return {};
84 }
85
86 //==============================================================================
getCurrentDefaultAudioDeviceName(AudioDeviceManager & deviceManager,bool isInput)87 static String getCurrentDefaultAudioDeviceName (AudioDeviceManager& deviceManager, bool isInput)
88 {
89 auto* deviceType = deviceManager.getCurrentDeviceTypeObject();
90 jassert (deviceType != nullptr);
91
92 if (deviceType != nullptr)
93 {
94 auto deviceNames = deviceType->getDeviceNames();
95 return deviceNames [deviceType->getDefaultDeviceIndex (isInput)];
96 }
97
98 return {};
99 }
100
101 // (returns a shared AudioDeviceManager object that all the demos can use)
getSharedAudioDeviceManager(int numInputChannels,int numOutputChannels)102 AudioDeviceManager& getSharedAudioDeviceManager (int numInputChannels, int numOutputChannels)
103 {
104 if (sharedAudioDeviceManager == nullptr)
105 sharedAudioDeviceManager.reset (new AudioDeviceManager());
106
107 auto* currentDevice = sharedAudioDeviceManager->getCurrentAudioDevice();
108
109 if (numInputChannels < 0)
110 numInputChannels = (currentDevice != nullptr ? currentDevice->getActiveInputChannels().countNumberOfSetBits() : 1);
111
112 if (numOutputChannels < 0)
113 numOutputChannels = (currentDevice != nullptr ? currentDevice->getActiveOutputChannels().countNumberOfSetBits() : 2);
114
115 if (numInputChannels > 0 && ! RuntimePermissions::isGranted (RuntimePermissions::recordAudio))
116 {
117 RuntimePermissions::request (RuntimePermissions::recordAudio,
118 [numInputChannels, numOutputChannels] (bool granted)
119 {
120 if (granted)
121 getSharedAudioDeviceManager (numInputChannels, numOutputChannels);
122 });
123
124 numInputChannels = 0;
125 }
126
127 if (sharedAudioDeviceManager->getCurrentAudioDevice() != nullptr)
128 {
129 auto setup = sharedAudioDeviceManager->getAudioDeviceSetup();
130
131 auto numInputs = jmax (numInputChannels, setup.inputChannels.countNumberOfSetBits());
132 auto numOutputs = jmax (numOutputChannels, setup.outputChannels.countNumberOfSetBits());
133
134 auto oldInputs = setup.inputChannels.countNumberOfSetBits();
135 auto oldOutputs = setup.outputChannels.countNumberOfSetBits();
136
137 if (oldInputs != numInputs || oldOutputs != numOutputs)
138 {
139 if (oldInputs == 0 && oldOutputs == 0)
140 {
141 sharedAudioDeviceManager->initialise (numInputChannels, numOutputChannels, nullptr, true, {}, nullptr);
142 }
143 else
144 {
145 setup.useDefaultInputChannels = setup.useDefaultOutputChannels = false;
146
147 setup.inputChannels.clear();
148 setup.outputChannels.clear();
149
150 setup.inputChannels.setRange (0, numInputs, true);
151 setup.outputChannels.setRange (0, numOutputs, true);
152
153 if (oldInputs == 0 && numInputs > 0 && setup.inputDeviceName.isEmpty())
154 setup.inputDeviceName = getCurrentDefaultAudioDeviceName (*sharedAudioDeviceManager, true);
155
156 if (oldOutputs == 0 && numOutputs > 0 && setup.outputDeviceName.isEmpty())
157 setup.outputDeviceName = getCurrentDefaultAudioDeviceName (*sharedAudioDeviceManager, false);
158
159 sharedAudioDeviceManager->setAudioDeviceSetup (setup, false);
160 }
161 }
162 }
163 else
164 {
165 sharedAudioDeviceManager->initialise (numInputChannels, numOutputChannels, nullptr, true, {}, nullptr);
166 }
167
168 return *sharedAudioDeviceManager;
169 }
170
171 //==============================================================================
registerAllDemos()172 void registerAllDemos() noexcept
173 {
174 registerDemos_One();
175 registerDemos_Two();
176 }
177