26#if JUCE_PLUGINHOST_LADSPA && (JUCE_LINUX || JUCE_BSD)
33static int shellLADSPAUIDToCreate = 0;
34static int insideLADSPACallback = 0;
36#define JUCE_LADSPA_LOGGING 1
38#if JUCE_LADSPA_LOGGING
39 #define JUCE_LADSPA_LOG(x) Logger::writeToLog (x);
41 #define JUCE_LADSPA_LOG(x)
45class LADSPAModuleHandle :
public ReferenceCountedObject
48 LADSPAModuleHandle (
const File&
f)
51 getActiveModules().add (
this);
56 getActiveModules().removeFirstMatchingValue (
this);
60 using Ptr = ReferenceCountedObjectPtr<LADSPAModuleHandle>;
62 static Array<LADSPAModuleHandle*>& getActiveModules()
64 static Array<LADSPAModuleHandle*> activeModules;
68 static LADSPAModuleHandle* findOrCreateModule (
const File&
file)
70 for (
auto i = getActiveModules().
size(); --
i >= 0;)
72 auto*
module = getActiveModules().getUnchecked(i);
74 if (module->file ==
file)
78 ++insideLADSPACallback;
79 shellLADSPAUIDToCreate = 0;
81 JUCE_LADSPA_LOG (
"Loading LADSPA module: " +
file.getFullPathName());
83 std::unique_ptr<LADSPAModuleHandle>
m (
new LADSPAModuleHandle (
file));
88 --insideLADSPACallback;
97 DynamicLibrary module;
101 module.open (file.getFullPathName());
104 return (moduleMain !=
nullptr);
116class LADSPAPluginInstance
final :
public AudioPluginInstance
119 LADSPAPluginInstance (
const LADSPAModuleHandle::Ptr&
m)
122 ++insideLADSPACallback;
124 name =
module->file.getFileNameWithoutExtension();
126 JUCE_LADSPA_LOG (
"Creating LADSPA instance: " +
name);
128 if (module->moduleMain !=
nullptr)
130 plugin =
module->moduleMain ((size_t) shellLADSPAUIDToCreate);
132 if (plugin ==
nullptr)
134 JUCE_LADSPA_LOG (
"Cannot find any valid descriptor in shared library");
135 --insideLADSPACallback;
141 JUCE_LADSPA_LOG (
"Cannot find any valid plugin in shared library");
142 --insideLADSPACallback;
149 handle = plugin->instantiate (plugin, (
uint32) sampleRate);
151 --insideLADSPACallback;
154 ~LADSPAPluginInstance()
override
158 jassert (insideLADSPACallback == 0);
160 if (handle !=
nullptr && plugin !=
nullptr && plugin->cleanup !=
nullptr)
161 plugin->cleanup (handle);
169 void initialise (
double initialSampleRate,
int initialBlockSize)
171 setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
173 if (initialised || plugin ==
nullptr || handle ==
nullptr)
176 JUCE_LADSPA_LOG (
"Initialising LADSPA: " +
name);
182 AudioProcessorParameterGroup newTree;
184 for (
unsigned int i = 0;
i < plugin->PortCount; ++
i)
186 const auto portDesc = plugin->PortDescriptors[
i];
189 newTree.addChild (std::make_unique<LADSPAParameter> (*
this, (
int)
i,
190 String (plugin->PortNames[
i]).trim(),
200 setHostedParameterTree (std::move (newTree));
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));
206 setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
208 setCurrentProgram (0);
209 setLatencySamples (0);
212 if (plugin->activate !=
nullptr) plugin->activate (handle);
213 if (plugin->deactivate !=
nullptr) plugin->deactivate (handle);
219 void fillInPluginDescription (PluginDescription& desc)
const override
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();
230 desc.numInputChannels = getTotalNumInputChannels();
231 desc.numOutputChannels = getTotalNumOutputChannels();
232 desc.isInstrument =
false;
235 const String getName()
const override
237 if (plugin !=
nullptr && plugin->Label !=
nullptr)
238 return plugin->Label;
245 if (plugin !=
nullptr && plugin->UniqueID != 0)
246 return (
int) plugin->UniqueID;
248 return module->file.hashCode();
252 String getCategory()
const {
return "Effect"; }
254 bool acceptsMidi()
const override {
return false; }
255 bool producesMidi()
const override {
return false; }
257 double getTailLengthSeconds()
const override {
return 0.0; }
260 void prepareToPlay (
double newSampleRate,
int samplesPerBlockExpected)
override
262 setLatencySamples (0);
264 initialise (newSampleRate, samplesPerBlockExpected);
268 tempBuffer.setSize (
jmax (1, outputs.size()), samplesPerBlockExpected);
271 if (
auto* firstParam = getParameters()[0])
273 const auto old = firstParam->getValue();
274 firstParam->setValue ((old < 0.5f) ? 1.0f : 0.0f);
275 firstParam->setValue (old);
278 if (plugin->activate !=
nullptr)
279 plugin->activate (handle);
283 void releaseResources()
override
285 if (handle !=
nullptr && plugin->deactivate !=
nullptr)
286 plugin->deactivate (handle);
288 tempBuffer.setSize (1, 1);
291 void processBlock (AudioBuffer<float>& buffer, MidiBuffer&)
override
293 auto numSamples =
buffer.getNumSamples();
295 if (initialised && plugin !=
nullptr && handle !=
nullptr)
297 for (
int i = 0;
i < inputs.size(); ++
i)
298 plugin->connect_port (handle, (
size_t) inputs[
i],
299 i <
buffer.getNumChannels() ?
buffer.getWritePointer (
i) :
nullptr);
301 if (plugin->run !=
nullptr)
303 for (
int i = 0;
i < outputs.size(); ++
i)
304 plugin->connect_port (handle, (
size_t) outputs.getUnchecked(
i),
305 i <
buffer.getNumChannels() ?
buffer.getWritePointer (
i) :
nullptr);
307 plugin->run (handle, (
size_t) numSamples);
311 if (plugin->run_adding !=
nullptr)
313 tempBuffer.setSize (outputs.size(), numSamples);
316 for (
int i = 0;
i < outputs.size(); ++
i)
317 plugin->connect_port (handle, (
size_t) outputs.getUnchecked(
i), tempBuffer.getWritePointer (
i));
319 plugin->run_adding (handle, (
size_t) numSamples);
321 for (
int i = 0;
i < outputs.size(); ++
i)
322 if (
i <
buffer.getNumChannels())
323 buffer.copyFrom (
i, 0, tempBuffer,
i, 0, numSamples);
331 for (
auto i = getTotalNumInputChannels(),
e = getTotalNumOutputChannels();
i <
e; ++
i)
332 buffer.clear (
i, 0, numSamples);
335 using AudioPluginInstance::processBlock;
337 bool isInputChannelStereoPair (
int index)
const override {
return isPositiveAndBelow (index, getTotalNumInputChannels()); }
338 bool isOutputChannelStereoPair (
int index)
const override {
return isPositiveAndBelow (index, getTotalNumOutputChannels()); }
340 const String getInputChannelName (
const int index)
const override
342 if (isPositiveAndBelow (index, getTotalNumInputChannels()))
343 return String (plugin->PortNames [inputs [index]]).trim();
348 const String getOutputChannelName (
const int index)
const override
350 if (isPositiveAndBelow (index, getTotalNumInputChannels()))
351 return String (plugin->PortNames [outputs [index]]).trim();
357 int getNumPrograms()
override {
return 0; }
358 int getCurrentProgram()
override {
return 0; }
360 void setCurrentProgram (
int)
override
362 for (
auto* param : getParameters())
363 if (
auto* ladspaParam =
dynamic_cast<LADSPAParameter*
> (param))
364 ladspaParam->reset();
367 const String getProgramName (
int)
override {
return {}; }
368 void changeProgramName (
int,
const String&)
override {}
371 void getStateInformation (MemoryBlock& destData)
override
373 auto numParameters = getParameters().size();
374 destData.
setSize ((
size_t) numParameters *
sizeof (
float));
377 auto*
p = unalignedPointerCast<float*> (destData.
getData());
379 for (
int i = 0;
i < numParameters; ++
i)
380 if (
auto* param = getParameters()[
i])
381 p[
i] = param->getValue();
384 void getCurrentProgramStateInformation (MemoryBlock& destData)
override { getStateInformation (destData); }
385 void setCurrentProgramStateInformation (
const void*
data,
int sizeInBytes)
override { setStateInformation (
data, sizeInBytes); }
387 void setStateInformation (
const void*
data,
int sizeInBytes)
override
391 auto*
p =
static_cast<const float*
> (
data);
393 for (
int i = 0;
i < getParameters().size(); ++
i)
394 if (
auto* param = getParameters()[
i])
395 param->setValue (
p[
i]);
398 bool hasEditor()
const override {
return false; }
399 AudioProcessorEditor* createEditor()
override {
return nullptr; }
401 bool isValid()
const {
return handle !=
nullptr; }
404 LADSPAModuleHandle::Ptr module;
409 struct LADSPAParameter
final :
public Parameter
411 struct ParameterValue
414 inline ParameterValue (
float s,
float u)
noexcept : scaled (
s), unscaled (
u) {}
416 float scaled = 0, unscaled = 0;
419 LADSPAParameter (LADSPAPluginInstance&
parent,
int parameterID,
420 const String& parameterName,
bool parameterIsAutomatable)
421 : pluginInstance (
parent),
422 paramID (parameterID),
423 name (parameterName),
424 automatable (parameterIsAutomatable)
429 float getValue()
const override
431 if (pluginInstance.plugin !=
nullptr)
435 return paramValue.unscaled;
441 String getCurrentValueAsText()
const override
443 if (
auto* interface = pluginInstance.plugin)
445 const auto&
hint = interface->PortRangeHints[paramID];
448 return String ((
int) paramValue.scaled);
450 return String (paramValue.scaled, 4);
456 void setValue (
float newValue)
override
458 if (
auto* interface = pluginInstance.plugin)
462 if (paramValue.unscaled != newValue)
463 paramValue = ParameterValue (getNewParamScaled (interface->PortRangeHints [paramID], newValue), newValue);
467 float getDefaultValue()
const override
472 ParameterValue getDefaultParamValue()
const
474 if (
auto* interface = pluginInstance.plugin)
476 const auto&
hint = interface->PortRangeHints[paramID];
477 const auto& desc =
hint.HintDescriptor;
488 const auto lower =
hint.LowerBound * scale;
489 const auto upper =
hint.UpperBound * scale;
510 paramValue = getDefaultParamValue();
511 defaultValue = paramValue.unscaled;
514 String getName (
int )
const override {
return name; }
515 String getLabel()
const override {
return {}; }
517 bool isAutomatable()
const override {
return automatable; }
519 String getParameterID()
const override
521 return String (paramID);
524 static float scaledValue (
float low,
float high,
float alpha,
bool useLog)
noexcept
526 if (useLog && low > 0 && high > 0)
527 return expf (logf (low) * (1.0f - alpha) + logf (high) * alpha);
529 return low + (high - low) * alpha;
539 const auto& desc =
hint.HintDescriptor;
542 return (newValue < 0.5f) ? 0.0f : 1.0f;
546 const auto lower =
hint.LowerBound * scale;
547 const auto upper =
hint.UpperBound * scale;
558 LADSPAPluginInstance& pluginInstance;
561 const bool automatable;
563 ParameterValue paramValue;
564 float defaultValue = 0.0f;
570 CriticalSection lock;
571 bool initialised =
false;
572 AudioBuffer<float> tempBuffer { 1, 1 };
573 Array<int> inputs, outputs;
581LADSPAPluginFormat::LADSPAPluginFormat() {}
582LADSPAPluginFormat::~LADSPAPluginFormat() {}
584void LADSPAPluginFormat::findAllTypesForFile (OwnedArray<PluginDescription>& results,
const String& fileOrIdentifier)
586 if (! fileMightContainThisPluginType (fileOrIdentifier))
589 PluginDescription desc;
590 desc.fileOrIdentifier = fileOrIdentifier;
591 desc.uniqueId = desc.deprecatedUid = 0;
593 auto createdInstance = createInstanceFromDescription (desc, 44100.0, 512);
594 auto instance =
dynamic_cast<LADSPAPluginInstance*
> (createdInstance.get());
596 if (instance ==
nullptr || ! instance->isValid())
599 instance->initialise (44100.0, 512);
600 instance->fillInPluginDescription (desc);
602 if (instance->module->moduleMain !=
nullptr)
604 for (
int uid = 0;; ++uid)
606 if (
auto* plugin = instance->module->moduleMain ((
size_t) uid))
608 desc.uniqueId = desc.deprecatedUid = uid;
609 desc.name = plugin->
Name !=
nullptr ? plugin->
Name :
"Unknown";
611 if (! arrayContainsPlugin (results, desc))
612 results.add (
new PluginDescription (desc));
622void LADSPAPluginFormat::createPluginInstance (
const PluginDescription& desc,
623 double sampleRate,
int blockSize,
626 std::unique_ptr<LADSPAPluginInstance>
result;
628 if (fileMightContainThisPluginType (desc.fileOrIdentifier))
630 auto file = File (desc.fileOrIdentifier);
633 file.getParentDirectory().setAsCurrentWorkingDirectory();
635 const LADSPAModuleHandle::Ptr module (LADSPAModuleHandle::findOrCreateModule (
file));
637 if (module !=
nullptr)
639 shellLADSPAUIDToCreate = desc.uniqueId != 0 ? desc.uniqueId : desc.deprecatedUid;
641 result.reset (
new LADSPAPluginInstance (module));
644 result->initialise (sampleRate, blockSize);
649 previousWorkingDirectory.setAsCurrentWorkingDirectory();
655 errorMsg =
TRANS (
"Unable to load XXX plug-in file").
replace (
"XXX",
"LADSPA");
660bool LADSPAPluginFormat::requiresUnblockedMessageThreadDuringCreation (
const PluginDescription&)
const
665bool LADSPAPluginFormat::fileMightContainThisPluginType (
const String& fileOrIdentifier)
668 return f.existsAsFile() &&
f.hasFileExtension (
".so");
671String LADSPAPluginFormat::getNameOfPluginFromIdentifier (
const String& fileOrIdentifier)
673 return fileOrIdentifier;
676bool LADSPAPluginFormat::pluginNeedsRescanning (
const PluginDescription& desc)
678 return File (desc.fileOrIdentifier).getLastModificationTime() != desc.lastFileModTime;
681bool LADSPAPluginFormat::doesPluginStillExist (
const PluginDescription& desc)
686StringArray LADSPAPluginFormat::searchPathsForPlugins (
const FileSearchPath& directoriesToSearch,
const bool recursive,
bool)
690 for (
int j = 0;
j < directoriesToSearch.getNumPaths(); ++
j)
691 recursiveFileSearch (results, directoriesToSearch[
j], recursive);
696void LADSPAPluginFormat::recursiveFileSearch (StringArray& results,
const File& dir,
const bool recursive)
701 auto f = iter.getFile();
704 if (fileMightContainThisPluginType (
f.getFullPathName()))
707 results.
add (
f.getFullPathName());
710 if (recursive && (! isPlugin) &&
f.isDirectory())
711 recursiveFileSearch (results,
f,
true);
715FileSearchPath LADSPAPluginFormat::getDefaultLocationsToSearch()
717 return { SystemStats::getEnvironmentVariable (
"LADSPA_PATH",
"/usr/lib/ladspa;/usr/local/lib/ladspa;~/.ladspa").replace (
":",
";") };
Type jmax(const Type a, const Type b)
Definition MathsFunctions.h:48
#define noexcept
Definition DistrhoDefines.h:72
#define final
Definition DistrhoDefines.h:74
uint32_t uint32
Definition basics.h:90
static File createFileWithoutCheckingPath(const String &absolutePath) noexcept
Definition File.cpp:65
static File getCurrentWorkingDirectory()
Definition File.cpp:1395
@ findFilesAndDirectories
Definition File.h:463
void setSize(const size_t newSize, bool initialiseNewSpaceToZero=false)
Definition MemoryBlock.cpp:109
void fillWith(uint8 valueToUse) noexcept
Definition MemoryBlock.cpp:162
void * getData() const noexcept
Definition MemoryBlock.h:91
bool add(const String &stringToAdd)
Definition StringArray.cpp:108
String replace(StringRef stringToReplace, StringRef stringToInsertInstead, bool ignoreCase=false) const
Definition String.cpp:1159
bool exists() const
Definition juce_posix_SharedCode.h:246
* e
Definition inflate.c:1404
unsigned * m
Definition inflate.c:1559
register unsigned j
Definition inflate.c:1576
struct huft * u[BMAX]
Definition inflate.c:1583
register unsigned i
Definition inflate.c:1575
unsigned s
Definition inflate.c:1555
unsigned f
Definition inflate.c:1572
static PuglViewHint int value
Definition pugl.h:1708
static PuglViewHint hint
Definition pugl.h:1707
static const char * name
Definition pugl.h:1582
static uintptr_t parent
Definition pugl.h:1644
virtual ASIOError getSampleRate(ASIOSampleRate *sampleRate)=0
struct _LADSPA_PortRangeHint LADSPA_PortRangeHint
#define LADSPA_IS_HINT_BOUNDED_BELOW(x)
Definition ladspa.h:310
#define LADSPA_VERSION
Definition ladspa.h:25
#define LADSPA_IS_HINT_DEFAULT_0(x)
Definition ladspa.h:328
#define LADSPA_PORT_INPUT
Definition ladspa.h:155
#define LADSPA_IS_HINT_BOUNDED_ABOVE(x)
Definition ladspa.h:311
#define LADSPA_IS_HINT_DEFAULT_440(x)
Definition ladspa.h:334
#define LADSPA_PORT_OUTPUT
Definition ladspa.h:158
#define LADSPA_IS_HINT_INTEGER(x)
Definition ladspa.h:315
#define LADSPA_IS_HINT_DEFAULT_100(x)
Definition ladspa.h:332
#define LADSPA_IS_HINT_HAS_DEFAULT(x)
Definition ladspa.h:317
#define LADSPA_IS_HINT_LOGARITHMIC(x)
Definition ladspa.h:314
#define LADSPA_IS_HINT_TOGGLED(x)
Definition ladspa.h:312
int LADSPA_PortRangeHintDescriptor
Definition ladspa.h:200
#define LADSPA_IS_HINT_DEFAULT_MIDDLE(x)
Definition ladspa.h:322
#define LADSPA_IS_HINT_DEFAULT_1(x)
Definition ladspa.h:330
#define LADSPA_PORT_CONTROL
Definition ladspa.h:162
#define LADSPA_IS_HINT_DEFAULT_HIGH(x)
Definition ladspa.h:324
#define LADSPA_IS_HINT_DEFAULT_LOW(x)
Definition ladspa.h:320
#define LADSPA_PORT_AUDIO
Definition ladspa.h:166
#define LADSPA_IS_HINT_DEFAULT_MAXIMUM(x)
Definition ladspa.h:326
const LADSPA_Descriptor *(* LADSPA_Descriptor_Function)(unsigned long Index)
Definition ladspa.h:593
void * LADSPA_Handle
Definition ladspa.h:363
#define LADSPA_IS_HINT_DEFAULT_MINIMUM(x)
Definition ladspa.h:318
struct _LADSPA_Descriptor LADSPA_Descriptor
#define LADSPA_IS_HINT_SAMPLE_RATE(x)
Definition ladspa.h:313
JSAMPIMAGE data
Definition jpeglib.h:945
#define TRANS(stringLiteral)
Definition juce_LocalisedStrings.h:208
const char * getVersion()
Definition carla_juce.cpp:57
void initialise()
Definition hardgate.cpp:79
JOCTET * buffer
Definition juce_JPEGLoader.cpp:302
Definition carla_juce.cpp:31
CriticalSection::ScopedLockType ScopedLock
Definition juce_CriticalSection.h:186
void ignoreUnused(Types &&...) noexcept
Definition juce_MathsFunctions.h:333
bool isPositiveAndBelow(Type1 valueToTest, Type2 upperLimit) noexcept
Definition juce_MathsFunctions.h:279
bool isPlugin
Definition Util.cpp:41
const char * Name
Definition ladspa.h:393
RECT const char void(* callback)(const char *droppath))) SWELL_API_DEFINE(BOOL
Definition swell-functions.h:1004
uch * p
Definition crypt.c:594
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
struct zdirent * file
Definition win32.c:1500