Add auto-scanning plugin API, with initial implementation
Signed-off-by: falkTX <falktx@falktx.com>
This commit is contained in:
parent
b32f6dbad8
commit
7321be60c6
|
@ -21,6 +21,7 @@
|
|||
#include "CarlaBackend.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
using CARLA_BACKEND_NAMESPACE::BinaryType;
|
||||
using CARLA_BACKEND_NAMESPACE::PluginCategory;
|
||||
using CARLA_BACKEND_NAMESPACE::PluginType;
|
||||
#endif
|
||||
|
@ -34,16 +35,6 @@ using CARLA_BACKEND_NAMESPACE::PluginType;
|
|||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef void* CarlaPipeClientHandle;
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef void (*CarlaPipeCallbackFunc)(void* ptr, const char* msg);
|
||||
|
||||
/*!
|
||||
* Information about a cached plugin.
|
||||
* @see carla_get_cached_plugin_info()
|
||||
|
@ -138,6 +129,170 @@ typedef struct _CarlaCachedPluginInfo {
|
|||
|
||||
} CarlaCachedPluginInfo;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------------------------------
|
||||
* plugin discovery */
|
||||
|
||||
typedef void* CarlaPluginDiscoveryHandle;
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef struct _CarlaPluginDiscoveryMetadata {
|
||||
/*!
|
||||
* Plugin name.
|
||||
*/
|
||||
const char* name;
|
||||
|
||||
/*!
|
||||
* Plugin author/maker.
|
||||
*/
|
||||
const char* maker;
|
||||
|
||||
/*!
|
||||
* Plugin category.
|
||||
*/
|
||||
PluginCategory category;
|
||||
|
||||
/*!
|
||||
* Plugin hints.
|
||||
* @see PluginHints
|
||||
*/
|
||||
uint hints;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/*!
|
||||
* C++ constructor.
|
||||
*/
|
||||
CARLA_API _CarlaPluginDiscoveryMetadata() noexcept;
|
||||
CARLA_DECLARE_NON_COPYABLE(_CarlaPluginDiscoveryMetadata)
|
||||
#endif
|
||||
|
||||
} CarlaPluginDiscoveryMetadata;
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef struct _CarlaPluginDiscoveryIO {
|
||||
/*!
|
||||
* Number of audio inputs.
|
||||
*/
|
||||
uint32_t audioIns;
|
||||
|
||||
/*!
|
||||
* Number of audio outputs.
|
||||
*/
|
||||
uint32_t audioOuts;
|
||||
|
||||
/*!
|
||||
* Number of CV inputs.
|
||||
*/
|
||||
uint32_t cvIns;
|
||||
|
||||
/*!
|
||||
* Number of CV outputs.
|
||||
*/
|
||||
uint32_t cvOuts;
|
||||
|
||||
/*!
|
||||
* Number of MIDI inputs.
|
||||
*/
|
||||
uint32_t midiIns;
|
||||
|
||||
/*!
|
||||
* Number of MIDI outputs.
|
||||
*/
|
||||
uint32_t midiOuts;
|
||||
|
||||
/*!
|
||||
* Number of input parameters.
|
||||
*/
|
||||
uint32_t parameterIns;
|
||||
|
||||
/*!
|
||||
* Number of output parameters.
|
||||
*/
|
||||
uint32_t parameterOuts;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/*!
|
||||
* C++ constructor.
|
||||
*/
|
||||
CARLA_API _CarlaPluginDiscoveryIO() noexcept;
|
||||
CARLA_DECLARE_NON_COPYABLE(_CarlaPluginDiscoveryIO)
|
||||
#endif
|
||||
|
||||
} CarlaPluginDiscoveryIO;
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef struct _CarlaPluginDiscoveryInfo {
|
||||
/*!
|
||||
* Binary type.
|
||||
*/
|
||||
BinaryType btype;
|
||||
|
||||
/*!
|
||||
* Plugin type.
|
||||
*/
|
||||
PluginType ptype;
|
||||
|
||||
/*!
|
||||
* Plugin filename.
|
||||
*/
|
||||
const char* filename;
|
||||
|
||||
/*!
|
||||
* Plugin label/URI/Id.
|
||||
*/
|
||||
const char* label;
|
||||
|
||||
/*!
|
||||
* Plugin unique Id.
|
||||
*/
|
||||
uint64_t uniqueId;
|
||||
|
||||
/*!
|
||||
* Extra information, not required for load plugins.
|
||||
*/
|
||||
CarlaPluginDiscoveryMetadata metadata;
|
||||
|
||||
/*!
|
||||
* Extra information, not required for load plugins.
|
||||
*/
|
||||
CarlaPluginDiscoveryIO io;
|
||||
|
||||
#ifdef __cplusplus
|
||||
/*!
|
||||
* C++ constructor.
|
||||
*/
|
||||
CARLA_API _CarlaPluginDiscoveryInfo() noexcept;
|
||||
CARLA_DECLARE_NON_COPYABLE(_CarlaPluginDiscoveryInfo)
|
||||
#endif
|
||||
|
||||
} CarlaPluginDiscoveryInfo;
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef void (*CarlaPluginDiscoveryCallback)(void* ptr, const CarlaPluginDiscoveryInfo* info);
|
||||
|
||||
/*!
|
||||
*/
|
||||
CARLA_PLUGIN_EXPORT CarlaPluginDiscoveryHandle carla_plugin_discovery_start(const char* discoveryTool,
|
||||
PluginType ptype,
|
||||
const char* pluginPath,
|
||||
CarlaPluginDiscoveryCallback callback,
|
||||
void* callbackPtr);
|
||||
|
||||
/*!
|
||||
*/
|
||||
CARLA_PLUGIN_EXPORT bool carla_plugin_discovery_idle(CarlaPluginDiscoveryHandle handle);
|
||||
|
||||
/*!
|
||||
*/
|
||||
CARLA_PLUGIN_EXPORT void carla_plugin_discovery_stop(CarlaPluginDiscoveryHandle handle);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------------------------------
|
||||
* cached plugins */
|
||||
|
||||
|
@ -222,6 +377,16 @@ CARLA_PLUGIN_EXPORT void carla_juce_cleanup(void);
|
|||
/* --------------------------------------------------------------------------------------------------------------------
|
||||
* pipes */
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef void* CarlaPipeClientHandle;
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
typedef void (*CarlaPipeCallbackFunc)(void* ptr, const char* msg);
|
||||
|
||||
/*!
|
||||
* TODO.
|
||||
*/
|
||||
|
|
|
@ -19,6 +19,7 @@ OBJS = \
|
|||
$(OBJDIR)/Information.cpp.o \
|
||||
$(OBJDIR)/JUCE.cpp.o \
|
||||
$(OBJDIR)/PipeClient.cpp.o \
|
||||
$(OBJDIR)/PluginDiscovery.cpp.o \
|
||||
$(OBJDIR)/System.cpp.o \
|
||||
$(OBJDIR)/Windows.cpp.o
|
||||
|
||||
|
|
|
@ -0,0 +1,458 @@
|
|||
/*
|
||||
* Carla Plugin Host
|
||||
* Copyright (C) 2011-2023 Filipe Coelho <falktx@falktx.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
|
||||
*/
|
||||
|
||||
#include "CarlaUtils.h"
|
||||
|
||||
#include "CarlaBackendUtils.hpp"
|
||||
#include "CarlaJuceUtils.hpp"
|
||||
#include "CarlaPipeUtils.hpp"
|
||||
|
||||
#include "water/files/File.h"
|
||||
#include "water/threads/ChildProcess.h"
|
||||
#include "water/text/StringArray.h"
|
||||
|
||||
namespace CB = CARLA_BACKEND_NAMESPACE;
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
static const char* const gPluginsDiscoveryNullCharPtr = "";
|
||||
|
||||
_CarlaPluginDiscoveryMetadata::_CarlaPluginDiscoveryMetadata() noexcept
|
||||
: name(gPluginsDiscoveryNullCharPtr),
|
||||
maker(gPluginsDiscoveryNullCharPtr),
|
||||
category(CB::PLUGIN_CATEGORY_NONE),
|
||||
hints(0x0) {}
|
||||
|
||||
_CarlaPluginDiscoveryIO::_CarlaPluginDiscoveryIO() noexcept
|
||||
: audioIns(0),
|
||||
audioOuts(0),
|
||||
cvIns(0),
|
||||
cvOuts(0),
|
||||
midiIns(0),
|
||||
midiOuts(0),
|
||||
parameterIns(0),
|
||||
parameterOuts(0) {}
|
||||
|
||||
_CarlaPluginDiscoveryInfo::_CarlaPluginDiscoveryInfo() noexcept
|
||||
: btype(CB::BINARY_NONE),
|
||||
ptype(CB::PLUGIN_NONE),
|
||||
filename(gPluginsDiscoveryNullCharPtr),
|
||||
label(gPluginsDiscoveryNullCharPtr),
|
||||
uniqueId(0),
|
||||
metadata() {}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
class CarlaPluginDiscovery : private CarlaPipeServer
|
||||
{
|
||||
public:
|
||||
CarlaPluginDiscovery(const char* const discoveryTool,
|
||||
const PluginType ptype,
|
||||
const std::vector<water::File>&& binaries,
|
||||
const CarlaPluginDiscoveryCallback callback,
|
||||
void* const callbackPtr)
|
||||
: fPluginType(ptype),
|
||||
fCallback(callback),
|
||||
fCallbackPtr(callbackPtr),
|
||||
fBinaryIndex(0),
|
||||
fBinaryCount(binaries.size()),
|
||||
fBinaries(binaries),
|
||||
fDiscoveryTool(discoveryTool),
|
||||
nextLabel(nullptr),
|
||||
nextMaker(nullptr),
|
||||
nextName(nullptr)
|
||||
{
|
||||
startPipeServer(discoveryTool, getPluginTypeAsString(fPluginType), fBinaries[0].getFullPathName().toRawUTF8());
|
||||
}
|
||||
|
||||
CarlaPluginDiscovery(const char* const discoveryTool,
|
||||
const PluginType ptype,
|
||||
const CarlaPluginDiscoveryCallback callback,
|
||||
void* const callbackPtr)
|
||||
: fPluginType(ptype),
|
||||
fCallback(callback),
|
||||
fCallbackPtr(callbackPtr),
|
||||
fBinaryIndex(0),
|
||||
fBinaryCount(1),
|
||||
nextLabel(nullptr),
|
||||
nextMaker(nullptr),
|
||||
nextName(nullptr)
|
||||
{
|
||||
startPipeServer(discoveryTool, getPluginTypeAsString(fPluginType), ":all");
|
||||
}
|
||||
|
||||
~CarlaPluginDiscovery()
|
||||
{
|
||||
std::free(nextLabel);
|
||||
std::free(nextMaker);
|
||||
std::free(nextName);
|
||||
}
|
||||
|
||||
// closePipeServer()
|
||||
|
||||
bool idle()
|
||||
{
|
||||
if (isPipeRunning())
|
||||
{
|
||||
idlePipe();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (++fBinaryIndex == fBinaryCount)
|
||||
return false;
|
||||
|
||||
startPipeServer(fDiscoveryTool,
|
||||
getPluginTypeAsString(fPluginType),
|
||||
fBinaries[fBinaryIndex].getFullPathName().toRawUTF8());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool msgReceived(const char* const msg) noexcept
|
||||
{
|
||||
if (std::strcmp(msg, "warning") == 0 || std::strcmp(msg, "error") == 0)
|
||||
{
|
||||
const char* text = nullptr;
|
||||
readNextLineAsString(text, false);
|
||||
carla_stdout("discovery: %s", text);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "init") == 0)
|
||||
{
|
||||
const char* _;
|
||||
readNextLineAsString(_, false);
|
||||
new (&nextInfo) _CarlaPluginDiscoveryInfo();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "end") == 0)
|
||||
{
|
||||
const char* _;
|
||||
readNextLineAsString(_, false);
|
||||
|
||||
if (nextInfo.label == nullptr)
|
||||
nextInfo.label = gPluginsDiscoveryNullCharPtr;
|
||||
|
||||
if (nextInfo.metadata.maker == nullptr)
|
||||
nextInfo.metadata.maker = gPluginsDiscoveryNullCharPtr;
|
||||
|
||||
if (nextInfo.metadata.name == nullptr)
|
||||
nextInfo.metadata.name = gPluginsDiscoveryNullCharPtr;
|
||||
|
||||
if (fDiscoveryTool.isEmpty())
|
||||
{
|
||||
char* filename = nullptr;
|
||||
|
||||
if (fPluginType == CB::PLUGIN_LV2)
|
||||
{
|
||||
do {
|
||||
const char* const slash = std::strchr(nextLabel, CARLA_OS_SEP);
|
||||
CARLA_SAFE_ASSERT_BREAK(slash != nullptr);
|
||||
filename = strdup(nextLabel);
|
||||
filename[slash - nextLabel] = '\0';
|
||||
nextInfo.filename = filename;
|
||||
nextInfo.label = slash + 1;
|
||||
} while (false);
|
||||
}
|
||||
|
||||
fCallback(fCallbackPtr, &nextInfo);
|
||||
|
||||
std::free(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
const water::String filename(fBinaries[fBinaryIndex].getFullPathName());
|
||||
nextInfo.filename = filename.toRawUTF8();
|
||||
fCallback(fCallbackPtr, &nextInfo);
|
||||
}
|
||||
|
||||
std::free(nextLabel);
|
||||
nextLabel = nullptr;
|
||||
|
||||
std::free(nextMaker);
|
||||
nextMaker = nullptr;
|
||||
|
||||
std::free(nextName);
|
||||
nextName = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "build") == 0)
|
||||
{
|
||||
uint8_t btype = 0;
|
||||
readNextLineAsByte(btype);
|
||||
nextInfo.btype = static_cast<BinaryType>(btype);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "hints") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.metadata.hints);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "category") == 0)
|
||||
{
|
||||
const char* category = nullptr;
|
||||
readNextLineAsString(category, false);
|
||||
nextInfo.metadata.category = getPluginCategoryFromString(category);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "name") == 0)
|
||||
{
|
||||
nextInfo.metadata.name = nextName = readNextLineAsString();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "label") == 0)
|
||||
{
|
||||
nextInfo.label = nextLabel = readNextLineAsString();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "maker") == 0)
|
||||
{
|
||||
nextInfo.metadata.maker = nextMaker = readNextLineAsString();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "uniqueId") == 0)
|
||||
{
|
||||
readNextLineAsULong(nextInfo.uniqueId);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "audio.ins") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.audioIns);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "audio.outs") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.audioOuts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "cv.ins") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.cvIns);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "cv.outs") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.cvOuts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "midi.ins") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.midiIns);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "midi.outs") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.midiOuts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "parameters.ins") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.parameterIns);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "parameters.outs") == 0)
|
||||
{
|
||||
readNextLineAsUInt(nextInfo.io.parameterOuts);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (std::strcmp(msg, "exiting") == 0)
|
||||
{
|
||||
stopPipeServer(1000);
|
||||
return true;
|
||||
}
|
||||
|
||||
carla_stdout("discovery: unknown message '%s' received", msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
const PluginType fPluginType;
|
||||
const CarlaPluginDiscoveryCallback fCallback;
|
||||
void* const fCallbackPtr;
|
||||
|
||||
uint fBinaryIndex;
|
||||
const uint fBinaryCount;
|
||||
const std::vector<water::File> fBinaries;
|
||||
const CarlaString fDiscoveryTool;
|
||||
|
||||
CarlaPluginDiscoveryInfo nextInfo;
|
||||
char* nextLabel;
|
||||
char* nextMaker;
|
||||
char* nextName;
|
||||
|
||||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginDiscovery)
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
static std::vector<water::File> findBinaries(const char* const pluginPath, const char* const wildcard)
|
||||
{
|
||||
CARLA_SAFE_ASSERT_RETURN(pluginPath != nullptr, {});
|
||||
|
||||
if (pluginPath[0] == '\0')
|
||||
return {};
|
||||
|
||||
using water::File;
|
||||
using water::String;
|
||||
using water::StringArray;
|
||||
|
||||
const StringArray splitPaths(StringArray::fromTokens(pluginPath, CARLA_OS_SPLIT_STR, ""));
|
||||
|
||||
if (splitPaths.size() == 0)
|
||||
return {};
|
||||
|
||||
std::vector<water::File> ret;
|
||||
|
||||
for (String *it = splitPaths.begin(), *end = splitPaths.end(); it != end; ++it)
|
||||
{
|
||||
const File dir(*it);
|
||||
std::vector<File> results;
|
||||
|
||||
if (dir.findChildFiles(results, File::findFiles|File::ignoreHiddenFiles, true, wildcard) > 0)
|
||||
{
|
||||
ret.reserve(ret.size() + results.size());
|
||||
ret.insert(ret.end(), results.begin(), results.end());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::vector<water::File> findVST3s(const char* const pluginPath)
|
||||
{
|
||||
CARLA_SAFE_ASSERT_RETURN(pluginPath != nullptr, {});
|
||||
|
||||
if (pluginPath[0] == '\0')
|
||||
return {};
|
||||
|
||||
using water::File;
|
||||
using water::String;
|
||||
using water::StringArray;
|
||||
|
||||
const StringArray splitPaths(StringArray::fromTokens(pluginPath, CARLA_OS_SPLIT_STR, ""));
|
||||
|
||||
if (splitPaths.size() == 0)
|
||||
return {};
|
||||
|
||||
std::vector<water::File> ret;
|
||||
|
||||
for (String *it = splitPaths.begin(), *end = splitPaths.end(); it != end; ++it)
|
||||
{
|
||||
const File dir(*it);
|
||||
std::vector<File> results;
|
||||
|
||||
if (dir.findChildFiles(results, File::findDirectories|File::findFiles|File::ignoreHiddenFiles, true, "*.vst3") > 0)
|
||||
{
|
||||
ret.reserve(ret.size() + results.size());
|
||||
ret.insert(ret.end(), results.begin(), results.end());
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
CarlaPluginDiscoveryHandle carla_plugin_discovery_start(const char* const discoveryTool,
|
||||
const PluginType ptype,
|
||||
const char* const pluginPath,
|
||||
const CarlaPluginDiscoveryCallback callback,
|
||||
void* const callbackPtr)
|
||||
{
|
||||
CARLA_SAFE_ASSERT_RETURN(discoveryTool != nullptr && discoveryTool[0] != '\0', nullptr);
|
||||
CARLA_SAFE_ASSERT_RETURN(callback != nullptr, nullptr);
|
||||
|
||||
const char* wildcard = nullptr;
|
||||
|
||||
switch (ptype)
|
||||
{
|
||||
case CB::PLUGIN_NONE:
|
||||
case CB::PLUGIN_JACK:
|
||||
case CB::PLUGIN_TYPE_COUNT:
|
||||
return nullptr;
|
||||
|
||||
case CB::PLUGIN_SFZ:
|
||||
case CB::PLUGIN_JSFX:
|
||||
{
|
||||
const CarlaScopedEnvVar csev("CARLA_DISCOVERY_PATH", pluginPath);
|
||||
return new CarlaPluginDiscovery(discoveryTool, ptype, callback, callbackPtr);
|
||||
}
|
||||
|
||||
case CB::PLUGIN_INTERNAL:
|
||||
case CB::PLUGIN_LV2:
|
||||
case CB::PLUGIN_AU:
|
||||
return new CarlaPluginDiscovery(discoveryTool, ptype, callback, callbackPtr);
|
||||
|
||||
case CB::PLUGIN_LADSPA:
|
||||
case CB::PLUGIN_DSSI:
|
||||
case CB::PLUGIN_VST2:
|
||||
wildcard = "*.so";
|
||||
break;
|
||||
case CB::PLUGIN_VST3:
|
||||
// handled separately
|
||||
break;
|
||||
case CB::PLUGIN_CLAP:
|
||||
wildcard = "*.clap";
|
||||
break;
|
||||
case CB::PLUGIN_DLS:
|
||||
wildcard = "*.dls";
|
||||
break;
|
||||
case CB::PLUGIN_GIG:
|
||||
wildcard = "*.gig";
|
||||
break;
|
||||
case CB::PLUGIN_SF2:
|
||||
wildcard = "*.sf2";
|
||||
break;
|
||||
}
|
||||
|
||||
const std::vector<water::File> binaries(ptype == CB::PLUGIN_VST3 ? findVST3s(pluginPath)
|
||||
: findBinaries(pluginPath, wildcard));
|
||||
|
||||
if (binaries.size() == 0)
|
||||
return nullptr;
|
||||
|
||||
return new CarlaPluginDiscovery(discoveryTool, ptype, std::move(binaries), callback, callbackPtr);
|
||||
}
|
||||
|
||||
bool carla_plugin_discovery_idle(CarlaPluginDiscoveryHandle handle)
|
||||
{
|
||||
return static_cast<CarlaPluginDiscovery*>(handle)->idle();
|
||||
}
|
||||
|
||||
void carla_plugin_discovery_stop(CarlaPluginDiscoveryHandle handle)
|
||||
{
|
||||
delete static_cast<CarlaPluginDiscovery*>(handle);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
|
@ -28,6 +28,7 @@
|
|||
#include "utils/Information.cpp"
|
||||
#include "utils/JUCE.cpp"
|
||||
#include "utils/PipeClient.cpp"
|
||||
#include "utils/PluginDiscovery.cpp"
|
||||
#include "utils/System.cpp"
|
||||
#include "utils/Windows.cpp"
|
||||
|
||||
|
|
Loading…
Reference in New Issue