JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_LADSPAPluginFormat.cpp
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - 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 7 End-User License
11 Agreement and JUCE Privacy Policy.
12
13 End User License Agreement: www.juce.com/juce-7-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#if JUCE_PLUGINHOST_LADSPA && (JUCE_LINUX || JUCE_BSD)
27
28#include <ladspa.h>
29
30namespace juce
31{
32
33static int shellLADSPAUIDToCreate = 0;
34static int insideLADSPACallback = 0;
35
36#define JUCE_LADSPA_LOGGING 1
37
38#if JUCE_LADSPA_LOGGING
39 #define JUCE_LADSPA_LOG(x) Logger::writeToLog (x);
40#else
41 #define JUCE_LADSPA_LOG(x)
42#endif
43
44//==============================================================================
45class LADSPAModuleHandle final : public ReferenceCountedObject
46{
47public:
48 LADSPAModuleHandle (const File& f)
49 : file (f)
50 {
51 getActiveModules().add (this);
52 }
53
55 {
56 getActiveModules().removeFirstMatchingValue (this);
57 close();
58 }
59
61
63 {
65 return activeModules;
66 }
67
68 static LADSPAModuleHandle* findOrCreateModule (const File& file)
69 {
70 for (auto i = getActiveModules().size(); --i >= 0;)
71 {
72 auto* module = getActiveModules().getUnchecked (i);
73
74 if (module->file == file)
75 return module;
76 }
77
80
81 JUCE_LADSPA_LOG ("Loading LADSPA module: " + file.getFullPathName());
82
84
85 if (! m->open())
86 m = nullptr;
87
89
90 return m.release();
91 }
92
93 File file;
95
96private:
97 DynamicLibrary module;
98
99 bool open()
100 {
101 module.open (file.getFullPathName());
102 moduleMain = (LADSPA_Descriptor_Function) module.getFunction ("ladspa_descriptor");
103
104 return (moduleMain != nullptr);
105 }
106
107 void close()
108 {
109 module.close();
110 }
111
113};
114
115//==============================================================================
116class LADSPAPluginInstance final : public AudioPluginInstance
117{
118public:
119 LADSPAPluginInstance (const LADSPAModuleHandle::Ptr& m)
120 : module (m)
121 {
122 ++insideLADSPACallback;
123
124 name = module->file.getFileNameWithoutExtension();
125
126 JUCE_LADSPA_LOG ("Creating LADSPA instance: " + name);
127
128 if (module->moduleMain != nullptr)
129 {
130 plugin = module->moduleMain ((size_t) shellLADSPAUIDToCreate);
131
132 if (plugin == nullptr)
133 {
134 JUCE_LADSPA_LOG ("Cannot find any valid descriptor in shared library");
135 --insideLADSPACallback;
136 return;
137 }
138 }
139 else
140 {
141 JUCE_LADSPA_LOG ("Cannot find any valid plugin in shared library");
142 --insideLADSPACallback;
143 return;
144 }
145
146 const auto sampleRate = getSampleRate() > 0 ? getSampleRate()
147 : 44100.0;
148
149 handle = plugin->instantiate (plugin, (uint32) sampleRate);
150
151 --insideLADSPACallback;
152 }
153
154 ~LADSPAPluginInstance() override
155 {
156 const ScopedLock sl (lock);
157
158 jassert (insideLADSPACallback == 0);
159
160 if (handle != nullptr && plugin != nullptr)
161 NullCheckedInvocation::invoke (plugin->cleanup, handle);
162
163 initialised = false;
164 module = nullptr;
165 plugin = nullptr;
166 handle = nullptr;
167 }
168
169 void initialise (double initialSampleRate, int initialBlockSize)
170 {
171 setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
172
173 if (initialised || plugin == nullptr || handle == nullptr)
174 return;
175
176 JUCE_LADSPA_LOG ("Initialising LADSPA: " + name);
177
178 initialised = true;
179
180 inputs.clear();
181 outputs.clear();
182 AudioProcessorParameterGroup newTree;
183
184 for (unsigned int i = 0; i < plugin->PortCount; ++i)
185 {
186 const auto portDesc = plugin->PortDescriptors[i];
187
188 if ((portDesc & LADSPA_PORT_CONTROL) != 0)
189 newTree.addChild (std::make_unique<LADSPAParameter> (*this, (int) i,
190 String (plugin->PortNames[i]).trim(),
191 (portDesc & LADSPA_PORT_INPUT) != 0));
192
193 if ((portDesc & LADSPA_PORT_AUDIO) != 0)
194 {
195 if ((portDesc & LADSPA_PORT_INPUT) != 0) inputs.add ((int) i);
196 if ((portDesc & LADSPA_PORT_OUTPUT) != 0) outputs.add ((int) i);
197 }
198 }
199
200 setHostedParameterTree (std::move (newTree));
201
202 for (auto* param : getParameters())
203 if (auto* ladspaParam = dynamic_cast<LADSPAParameter*> (param))
204 plugin->connect_port (handle, (size_t) ladspaParam->paramID, &(ladspaParam->paramValue.scaled));
205
206 setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
207
208 setCurrentProgram (0);
209 setLatencySamples (0);
210
211 // Some plugins crash if this doesn't happen:
212 NullCheckedInvocation::invoke (plugin->activate, handle);
213 NullCheckedInvocation::invoke (plugin->deactivate, handle);
214 }
215
216 //==============================================================================
217 // AudioPluginInstance methods:
218
219 void fillInPluginDescription (PluginDescription& desc) const override
220 {
221 desc.name = getName();
222 desc.fileOrIdentifier = module->file.getFullPathName();
223 desc.uniqueId = desc.deprecatedUid = getUID();
224 desc.lastFileModTime = module->file.getLastModificationTime();
225 desc.lastInfoUpdateTime = Time::getCurrentTime();
226 desc.pluginFormatName = "LADSPA";
227 desc.category = getCategory();
228 desc.manufacturerName = plugin != nullptr ? String (plugin->Maker) : String();
229 desc.version = getVersion();
230 desc.numInputChannels = getTotalNumInputChannels();
231 desc.numOutputChannels = getTotalNumOutputChannels();
232 desc.isInstrument = false;
233 }
234
235 const String getName() const override
236 {
237 if (plugin != nullptr && plugin->Label != nullptr)
238 return plugin->Label;
239
240 return name;
241 }
242
243 int getUID() const
244 {
245 if (plugin != nullptr && plugin->UniqueID != 0)
246 return (int) plugin->UniqueID;
247
248 return module->file.hashCode();
249 }
250
251 String getVersion() const { return LADSPA_VERSION; }
252 String getCategory() const { return "Effect"; }
253
254 bool acceptsMidi() const override { return false; }
255 bool producesMidi() const override { return false; }
256
257 double getTailLengthSeconds() const override { return 0.0; }
258
259 //==============================================================================
260 void prepareToPlay (double newSampleRate, int samplesPerBlockExpected) override
261 {
262 setLatencySamples (0);
263
264 initialise (newSampleRate, samplesPerBlockExpected);
265
266 if (initialised)
267 {
268 tempBuffer.setSize (jmax (1, outputs.size()), samplesPerBlockExpected);
269
270 // dodgy hack to force some plugins to initialise the sample rate..
271 if (auto* firstParam = getParameters()[0])
272 {
273 const auto old = firstParam->getValue();
274 firstParam->setValue ((old < 0.5f) ? 1.0f : 0.0f);
275 firstParam->setValue (old);
276 }
277
278 NullCheckedInvocation::invoke (plugin->activate, handle);
279 }
280 }
281
282 void releaseResources() override
283 {
284 if (handle != nullptr && plugin->deactivate != nullptr)
285 NullCheckedInvocation::invoke (plugin->deactivate, handle);
286
287 tempBuffer.setSize (1, 1);
288 }
289
290 void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override
291 {
292 auto numSamples = buffer.getNumSamples();
293
294 if (initialised && plugin != nullptr && handle != nullptr)
295 {
296 for (int i = 0; i < inputs.size(); ++i)
297 plugin->connect_port (handle, (size_t) inputs[i],
298 i < buffer.getNumChannels() ? buffer.getWritePointer (i) : nullptr);
299
300 if (plugin->run != nullptr)
301 {
302 for (int i = 0; i < outputs.size(); ++i)
303 plugin->connect_port (handle, (size_t) outputs.getUnchecked (i),
304 i < buffer.getNumChannels() ? buffer.getWritePointer (i) : nullptr);
305
306 plugin->run (handle, (size_t) numSamples);
307 return;
308 }
309
310 if (plugin->run_adding != nullptr)
311 {
312 tempBuffer.setSize (outputs.size(), numSamples);
313 tempBuffer.clear();
314
315 for (int i = 0; i < outputs.size(); ++i)
316 plugin->connect_port (handle, (size_t) outputs.getUnchecked (i), tempBuffer.getWritePointer (i));
317
318 plugin->run_adding (handle, (size_t) numSamples);
319
320 for (int i = 0; i < outputs.size(); ++i)
321 if (i < buffer.getNumChannels())
322 buffer.copyFrom (i, 0, tempBuffer, i, 0, numSamples);
323
324 return;
325 }
326
327 jassertfalse; // no callback to use?
328 }
329
330 for (auto i = getTotalNumInputChannels(), e = getTotalNumOutputChannels(); i < e; ++i)
331 buffer.clear (i, 0, numSamples);
332 }
333
334 using AudioPluginInstance::processBlock;
335
336 bool isInputChannelStereoPair (int index) const override { return isPositiveAndBelow (index, getTotalNumInputChannels()); }
337 bool isOutputChannelStereoPair (int index) const override { return isPositiveAndBelow (index, getTotalNumOutputChannels()); }
338
339 const String getInputChannelName (const int index) const override
340 {
341 if (isPositiveAndBelow (index, getTotalNumInputChannels()))
342 return String (plugin->PortNames [inputs [index]]).trim();
343
344 return {};
345 }
346
347 const String getOutputChannelName (const int index) const override
348 {
349 if (isPositiveAndBelow (index, getTotalNumInputChannels()))
350 return String (plugin->PortNames [outputs [index]]).trim();
351
352 return {};
353 }
354
355 //==============================================================================
356 int getNumPrograms() override { return 0; }
357 int getCurrentProgram() override { return 0; }
358
359 void setCurrentProgram (int) override
360 {
361 for (auto* param : getParameters())
362 if (auto* ladspaParam = dynamic_cast<LADSPAParameter*> (param))
363 ladspaParam->reset();
364 }
365
366 const String getProgramName (int) override { return {}; }
367 void changeProgramName (int, const String&) override {}
368
369 //==============================================================================
370 void getStateInformation (MemoryBlock& destData) override
371 {
372 auto numParameters = getParameters().size();
373 destData.setSize ((size_t) numParameters * sizeof (float));
374 destData.fillWith (0);
375
376 auto* p = unalignedPointerCast<float*> (destData.getData());
377
378 for (int i = 0; i < numParameters; ++i)
379 if (auto* param = getParameters()[i])
380 p[i] = param->getValue();
381 }
382
383 void getCurrentProgramStateInformation (MemoryBlock& destData) override { getStateInformation (destData); }
384 void setCurrentProgramStateInformation (const void* data, int sizeInBytes) override { setStateInformation (data, sizeInBytes); }
385
386 void setStateInformation (const void* data, [[maybe_unused]] int sizeInBytes) override
387 {
388 auto* p = static_cast<const float*> (data);
389
390 for (int i = 0; i < getParameters().size(); ++i)
391 if (auto* param = getParameters()[i])
392 param->setValue (p[i]);
393 }
394
395 bool hasEditor() const override { return false; }
396 AudioProcessorEditor* createEditor() override { return nullptr; }
397
398 bool isValid() const { return handle != nullptr; }
399
400 //==============================================================================
401 LADSPAModuleHandle::Ptr module;
402 const LADSPA_Descriptor* plugin = nullptr;
403
404private:
405 //==============================================================================
406 struct LADSPAParameter final : public Parameter
407 {
408 struct ParameterValue
409 {
410 inline ParameterValue() noexcept {}
411 inline ParameterValue (float s, float u) noexcept : scaled (s), unscaled (u) {}
412
413 float scaled = 0, unscaled = 0;
414 };
415
416 LADSPAParameter (LADSPAPluginInstance& parent, int parameterID,
417 const String& parameterName, bool parameterIsAutomatable)
418 : pluginInstance (parent),
419 paramID (parameterID),
420 name (parameterName),
421 automatable (parameterIsAutomatable)
422 {
423 reset();
424 }
425
426 float getValue() const override
427 {
428 if (pluginInstance.plugin != nullptr)
429 {
430 const ScopedLock sl (pluginInstance.lock);
431
432 return paramValue.unscaled;
433 }
434
435 return 0.0f;
436 }
437
438 String getCurrentValueAsText() const override
439 {
440 if (auto* interface = pluginInstance.plugin)
441 {
442 const auto& hint = interface->PortRangeHints[paramID];
443
444 if (LADSPA_IS_HINT_INTEGER (hint.HintDescriptor))
445 return String ((int) paramValue.scaled);
446
447 return String (paramValue.scaled, 4);
448 }
449
450 return {};
451 }
452
453 void setValue (float newValue) override
454 {
455 if (auto* interface = pluginInstance.plugin)
456 {
457 const ScopedLock sl (pluginInstance.lock);
458
459 if (! approximatelyEqual (paramValue.unscaled, newValue))
460 paramValue = ParameterValue (getNewParamScaled (interface->PortRangeHints [paramID], newValue), newValue);
461 }
462 }
463
464 float getDefaultValue() const override
465 {
466 return defaultValue;
467 }
468
469 ParameterValue getDefaultParamValue() const
470 {
471 if (auto* interface = pluginInstance.plugin)
472 {
473 const auto& hint = interface->PortRangeHints[paramID];
474 const auto& desc = hint.HintDescriptor;
475
476 if (LADSPA_IS_HINT_HAS_DEFAULT (desc))
477 {
478 if (LADSPA_IS_HINT_DEFAULT_0 (desc)) return {};
479 if (LADSPA_IS_HINT_DEFAULT_1 (desc)) return { 1.0f, 1.0f };
480 if (LADSPA_IS_HINT_DEFAULT_100 (desc)) return { 100.0f, 0.5f };
481 if (LADSPA_IS_HINT_DEFAULT_440 (desc)) return { 440.0f, 0.5f };
482
483 const auto scale = LADSPA_IS_HINT_SAMPLE_RATE (desc) ? (float) pluginInstance.getSampleRate()
484 : 1.0f;
485 const auto lower = hint.LowerBound * scale;
486 const auto upper = hint.UpperBound * scale;
487
488 if (LADSPA_IS_HINT_BOUNDED_BELOW (desc) && LADSPA_IS_HINT_DEFAULT_MINIMUM (desc)) return { lower, 0.0f };
489 if (LADSPA_IS_HINT_BOUNDED_ABOVE (desc) && LADSPA_IS_HINT_DEFAULT_MAXIMUM (desc)) return { upper, 1.0f };
490
491 if (LADSPA_IS_HINT_BOUNDED_BELOW (desc))
492 {
493 auto useLog = LADSPA_IS_HINT_LOGARITHMIC (desc);
494
495 if (LADSPA_IS_HINT_DEFAULT_LOW (desc)) return { scaledValue (lower, upper, 0.25f, useLog), 0.25f };
496 if (LADSPA_IS_HINT_DEFAULT_MIDDLE (desc)) return { scaledValue (lower, upper, 0.50f, useLog), 0.50f };
497 if (LADSPA_IS_HINT_DEFAULT_HIGH (desc)) return { scaledValue (lower, upper, 0.75f, useLog), 0.75f };
498 }
499 }
500 }
501
502 return {};
503 }
504
505 void reset()
506 {
507 paramValue = getDefaultParamValue();
508 defaultValue = paramValue.unscaled;
509 }
510
511 String getName (int /*maximumStringLength*/) const override { return name; }
512 String getLabel() const override { return {}; }
513
514 bool isAutomatable() const override { return automatable; }
515
516 String getParameterID() const override
517 {
518 return String (paramID);
519 }
520
521 static float scaledValue (float low, float high, float alpha, bool useLog) noexcept
522 {
523 if (useLog && low > 0 && high > 0)
524 return expf (logf (low) * (1.0f - alpha) + logf (high) * alpha);
525
526 return low + (high - low) * alpha;
527 }
528
529 static float toIntIfNecessary (const LADSPA_PortRangeHintDescriptor& desc, float value)
530 {
531 return LADSPA_IS_HINT_INTEGER (desc) ? ((float) (int) value) : value;
532 }
533
534 float getNewParamScaled (const LADSPA_PortRangeHint& hint, float newValue) const
535 {
536 const auto& desc = hint.HintDescriptor;
537
538 if (LADSPA_IS_HINT_TOGGLED (desc))
539 return (newValue < 0.5f) ? 0.0f : 1.0f;
540
541 const auto scale = LADSPA_IS_HINT_SAMPLE_RATE (desc) ? (float) pluginInstance.getSampleRate()
542 : 1.0f;
543 const auto lower = hint.LowerBound * scale;
544 const auto upper = hint.UpperBound * scale;
545
546 if (LADSPA_IS_HINT_BOUNDED_BELOW (desc) && LADSPA_IS_HINT_BOUNDED_ABOVE (desc))
547 return toIntIfNecessary (desc, scaledValue (lower, upper, newValue, LADSPA_IS_HINT_LOGARITHMIC (desc)));
548
549 if (LADSPA_IS_HINT_BOUNDED_BELOW (desc)) return toIntIfNecessary (desc, newValue);
550 if (LADSPA_IS_HINT_BOUNDED_ABOVE (desc)) return toIntIfNecessary (desc, newValue * upper);
551
552 return 0.0f;
553 }
554
555 LADSPAPluginInstance& pluginInstance;
556 const int paramID;
557 const String name;
558 const bool automatable;
559
560 ParameterValue paramValue;
561 float defaultValue = 0.0f;
562 };
563
564 //==============================================================================
565 LADSPA_Handle handle = nullptr;
566 String name;
567 CriticalSection lock;
568 bool initialised = false;
569 AudioBuffer<float> tempBuffer { 1, 1 };
570 Array<int> inputs, outputs;
571
572 //==============================================================================
574};
575
576
577//==============================================================================
578LADSPAPluginFormat::LADSPAPluginFormat() {}
579LADSPAPluginFormat::~LADSPAPluginFormat() {}
580
581void LADSPAPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& results, const String& fileOrIdentifier)
582{
583 if (! fileMightContainThisPluginType (fileOrIdentifier))
584 return;
585
586 PluginDescription desc;
587 desc.fileOrIdentifier = fileOrIdentifier;
588 desc.uniqueId = desc.deprecatedUid = 0;
589
590 auto createdInstance = createInstanceFromDescription (desc, 44100.0, 512);
591 auto instance = dynamic_cast<LADSPAPluginInstance*> (createdInstance.get());
592
593 if (instance == nullptr || ! instance->isValid())
594 return;
595
596 instance->initialise (44100.0, 512);
597 instance->fillInPluginDescription (desc);
598
599 if (instance->module->moduleMain != nullptr)
600 {
601 for (int uid = 0;; ++uid)
602 {
603 if (auto* plugin = instance->module->moduleMain ((size_t) uid))
604 {
605 desc.uniqueId = desc.deprecatedUid = uid;
606 desc.name = plugin->Name != nullptr ? plugin->Name : "Unknown";
607
608 if (! arrayContainsPlugin (results, desc))
609 results.add (new PluginDescription (desc));
610 }
611 else
612 {
613 break;
614 }
615 }
616 }
617}
618
619void LADSPAPluginFormat::createPluginInstance (const PluginDescription& desc,
620 double sampleRate, int blockSize,
621 PluginCreationCallback callback)
622{
624
625 if (fileMightContainThisPluginType (desc.fileOrIdentifier))
626 {
627 auto file = File (desc.fileOrIdentifier);
628
630 file.getParentDirectory().setAsCurrentWorkingDirectory();
631
632 const LADSPAModuleHandle::Ptr module (LADSPAModuleHandle::findOrCreateModule (file));
633
634 if (module != nullptr)
635 {
636 shellLADSPAUIDToCreate = desc.uniqueId != 0 ? desc.uniqueId : desc.deprecatedUid;
637
638 result.reset (new LADSPAPluginInstance (module));
639
640 if (result->plugin != nullptr && result->isValid())
641 result->initialise (sampleRate, blockSize);
642 else
643 result = nullptr;
644 }
645
646 previousWorkingDirectory.setAsCurrentWorkingDirectory();
647 }
648
649 String errorMsg;
650
651 if (result == nullptr)
652 errorMsg = TRANS ("Unable to load XXX plug-in file").replace ("XXX", "LADSPA");
653
654 callback (std::move (result), errorMsg);
655}
656
657bool LADSPAPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const
658{
659 return false;
660}
661
662bool LADSPAPluginFormat::fileMightContainThisPluginType (const String& fileOrIdentifier)
663{
664 auto f = File::createFileWithoutCheckingPath (fileOrIdentifier);
665 return f.existsAsFile() && f.hasFileExtension (".so");
666}
667
668String LADSPAPluginFormat::getNameOfPluginFromIdentifier (const String& fileOrIdentifier)
669{
670 return fileOrIdentifier;
671}
672
673bool LADSPAPluginFormat::pluginNeedsRescanning (const PluginDescription& desc)
674{
675 return File (desc.fileOrIdentifier).getLastModificationTime() != desc.lastFileModTime;
676}
677
678bool LADSPAPluginFormat::doesPluginStillExist (const PluginDescription& desc)
679{
680 return File::createFileWithoutCheckingPath (desc.fileOrIdentifier).exists();
681}
682
683StringArray LADSPAPluginFormat::searchPathsForPlugins (const FileSearchPath& directoriesToSearch, const bool recursive, bool)
684{
685 StringArray results;
686
687 for (int j = 0; j < directoriesToSearch.getNumPaths(); ++j)
688 recursiveFileSearch (results, directoriesToSearch[j], recursive);
689
690 return results;
691}
692
693void LADSPAPluginFormat::recursiveFileSearch (StringArray& results, const File& dir, const bool recursive)
694{
695
696 for (const auto& iter : RangedDirectoryIterator (dir, false, "*", File::findFilesAndDirectories))
697 {
698 auto f = iter.getFile();
699 bool isPlugin = false;
700
701 if (fileMightContainThisPluginType (f.getFullPathName()))
702 {
703 isPlugin = true;
704 results.add (f.getFullPathName());
705 }
706
707 if (recursive && (! isPlugin) && f.isDirectory())
708 recursiveFileSearch (results, f, true);
709 }
710}
711
713{
714 return { SystemStats::getEnvironmentVariable ("LADSPA_PATH", "/usr/lib/ladspa;/usr/local/lib/ladspa;~/.ladspa").replace (":", ";") };
715}
716
717} // namespace juce
718
719#endif
std::unique_ptr< AudioPluginInstance > createInstanceFromDescription(const PluginDescription &, double initialSampleRate, int initialBufferSize)
Tries to recreate a type from a previously generated PluginDescription.
static File getCurrentWorkingDirectory()
Returns the current working directory.
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Creates a file that simply contains this string, without doing the sanity-checking that the normal co...
Definition juce_File.cpp:31
bool exists() const
Checks whether the file actually exists.
void findAllTypesForFile(OwnedArray< PluginDescription > &, const String &fileOrIdentifier) override
This tries to create descriptions for all the plugin types available in a binary module file.
StringArray searchPathsForPlugins(const FileSearchPath &, bool recursive, bool) override
Searches a suggested set of directories for any plugins in this format.
bool fileMightContainThisPluginType(const String &fileOrIdentifier) override
Should do a quick check to see if this file or directory might be a plugin of this format.
FileSearchPath getDefaultLocationsToSearch() override
Returns the typical places to look for this kind of plugin.
bool doesPluginStillExist(const PluginDescription &) override
Checks whether this plugin could possibly be loaded.
bool pluginNeedsRescanning(const PluginDescription &) override
Returns true if this plugin's version or date has changed and it should be re-checked.
String getNameOfPluginFromIdentifier(const String &fileOrIdentifier) override
Returns a readable version of the name of the plugin that this identifier refers to.
void add(String stringToAdd)
Appends a string at the end of the array.
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
Replaces all occurrences of a substring with another string.
static String getEnvironmentVariable(const String &name, const String &defaultValue)
Returns an environment variable.
close
T data(T... args)
expf
#define TRANS(stringLiteral)
Uses the LocalisedStrings class to translate the given string literal.
#define jassert(expression)
Platform-independent assertion macro.
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
This is a shorthand way of writing both a JUCE_DECLARE_NON_COPYABLE and JUCE_LEAK_DETECTOR macro for ...
#define jassertfalse
This will always cause an assertion failure.
T lock(T... args)
typedef float
JUCE Namespace.
CriticalSection::ScopedLockType ScopedLock
Automatically locks and unlocks a CriticalSection object.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Returns true if a value is at least zero, and also below a specified upper limit.
open
T reset(T... args)
T size(T... args)
typedef size_t