Browse Source

Simplify discovery lv2 code

tags/v1.9.11
falkTX 7 years ago
parent
commit
ff6aecfe54
4 changed files with 409 additions and 438 deletions
  1. +1
    -0
      source/backend/Makefile
  2. +371
    -290
      source/backend/utils/CachedPlugins.cpp
  3. +7
    -0
      source/backend/utils/PipeClient.cpp
  4. +30
    -148
      source/discovery/carla-discovery.cpp

+ 1
- 0
source/backend/Makefile View File

@@ -60,6 +60,7 @@ STANDALONE_LINK_FLAGS += $(X11_LIBS)
# ---------------------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------------------


all: $(TARGETS) all: $(TARGETS)
$(MAKE) -C utils


# ---------------------------------------------------------------------------------------------------------------------------- # ----------------------------------------------------------------------------------------------------------------------------




+ 371
- 290
source/backend/utils/CachedPlugins.cpp View File

@@ -31,6 +31,7 @@ static bool isCachedPluginType(const CB::PluginType ptype)
{ {
case CB::PLUGIN_INTERNAL: case CB::PLUGIN_INTERNAL:
case CB::PLUGIN_LV2: case CB::PLUGIN_LV2:
case CB::PLUGIN_SFZ:
return false; return false;
default: default:
return true; return true;
@@ -56,304 +57,333 @@ _CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept


// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------


uint carla_get_cached_plugin_count(CB::PluginType ptype, const char* pluginPath)
const CarlaCachedPluginInfo* get_cached_plugin_internal(const NativePluginDescriptor& desc)
{ {
CARLA_SAFE_ASSERT_RETURN(isCachedPluginType(ptype), 0);
carla_debug("carla_get_cached_plugin_count(%i:%s)", ptype, CB::PluginType2Str(ptype));
static CarlaCachedPluginInfo info;


switch (ptype)
{
case CB::PLUGIN_INTERNAL: {
uint32_t count = 0;
carla_get_native_plugins_data(&count);
return count;
}
info.category = static_cast<CB::PluginCategory>(desc.category);
info.hints = 0x0;

if (desc.hints & NATIVE_PLUGIN_IS_RTSAFE)
info.hints |= CB::PLUGIN_IS_RTSAFE;
if (desc.hints & NATIVE_PLUGIN_IS_SYNTH)
info.hints |= CB::PLUGIN_IS_SYNTH;
if (desc.hints & NATIVE_PLUGIN_HAS_UI)
info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
if (desc.hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
if (desc.hints & NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD)
info.hints |= CB::PLUGIN_NEEDS_UI_MAIN_THREAD;
if (desc.hints & NATIVE_PLUGIN_USES_MULTI_PROGS)
info.hints |= CB::PLUGIN_USES_MULTI_PROGS;


case CB::PLUGIN_LV2: {
Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
lv2World.initIfNeeded(pluginPath);
return lv2World.getPluginCount();
}

default:
return 0;
}
info.valid = true;
info.audioIns = desc.audioIns;
info.audioOuts = desc.audioOuts;
info.midiIns = desc.midiIns;
info.midiOuts = desc.midiOuts;
info.parameterIns = desc.paramIns;
info.parameterOuts = desc.paramOuts;
info.name = desc.name;
info.label = desc.label;
info.maker = desc.maker;
info.copyright = desc.copyright;
return &info;
} }


const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype, uint index)
const CarlaCachedPluginInfo* get_cached_plugin_lv2(Lv2WorldClass& lv2World, Lilv::Plugin& lilvPlugin)
{ {
carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);

static CarlaCachedPluginInfo info; static CarlaCachedPluginInfo info;


switch (ptype)
info.valid = false;
bool supported = true;

// ----------------------------------------------------------------------------------------------------------------
// text data

{ {
case CB::PLUGIN_INTERNAL: {
uint32_t count = 0;
const NativePluginDescriptor* const descs(carla_get_native_plugins_data(&count));
CARLA_SAFE_ASSERT_BREAK(index < count);
CARLA_SAFE_ASSERT_BREAK(descs != nullptr);
static CarlaString suri, sname, smaker, slicense;
suri.clear(); sname.clear(); smaker.clear(); slicense.clear();


const NativePluginDescriptor& desc(descs[index]);
suri = lilvPlugin.get_uri().as_uri();


info.category = static_cast<CB::PluginCategory>(desc.category);
info.hints = 0x0;

if (desc.hints & NATIVE_PLUGIN_IS_RTSAFE)
info.hints |= CB::PLUGIN_IS_RTSAFE;
if (desc.hints & NATIVE_PLUGIN_IS_SYNTH)
info.hints |= CB::PLUGIN_IS_SYNTH;
if (desc.hints & NATIVE_PLUGIN_HAS_UI)
info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
if (desc.hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
info.hints |= CB::PLUGIN_NEEDS_FIXED_BUFFERS;
if (desc.hints & NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD)
info.hints |= CB::PLUGIN_NEEDS_UI_MAIN_THREAD;
if (desc.hints & NATIVE_PLUGIN_USES_MULTI_PROGS)
info.hints |= CB::PLUGIN_USES_MULTI_PROGS;

info.valid = true;
info.audioIns = desc.audioIns;
info.audioOuts = desc.audioOuts;
info.midiIns = desc.midiIns;
info.midiOuts = desc.midiOuts;
info.parameterIns = desc.paramIns;
info.parameterOuts = desc.paramOuts;
info.name = desc.name;
info.label = desc.label;
info.maker = desc.maker;
info.copyright = desc.copyright;
return &info;
}
if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me))
{
if (const char* const name = lilv_node_as_string(nameNode))
sname = name;
lilv_node_free(nameNode);
}


case CB::PLUGIN_LV2: {
Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
if (const char* const author = lilvPlugin.get_author_name().as_string())
smaker = author;


const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);
Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));


Lilv::Plugin lilvPlugin(cPlugin);
CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());
if (licenseNodes.size() > 0)
{
if (const char* const license = licenseNodes.get_first().as_string())
slicense = license;
}


// features
info.hints = 0x0;
lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));


if (lilvPlugin.get_uis().size() > 0)
info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;
info.name = sname.buffer();
info.label = suri.buffer();
info.maker = smaker.buffer();
info.copyright = slicense.buffer();
}


// ----------------------------------------------------------------------------------------------------------------
// features

info.hints = 0x0;

if (lilvPlugin.get_uis().size() > 0)
info.hints |= CB::PLUGIN_HAS_CUSTOM_UI;

{
Lilv::Nodes lilvRequiredFeatureNodes(lilvPlugin.get_required_features());

LILV_FOREACH(nodes, it, lilvRequiredFeatureNodes)
{ {
Lilv::Nodes lilvFeatureNodes(lilvPlugin.get_supported_features());
Lilv::Node lilvFeatureNode(lilvRequiredFeatureNodes.get(it));
const char* const featureURI(lilvFeatureNode.as_uri());
CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);


LILV_FOREACH(nodes, it, lilvFeatureNodes)
if (! is_lv2_feature_supported(featureURI))
{ {
Lilv::Node lilvFeatureNode(lilvFeatureNodes.get(it));
const char* const featureURI(lilvFeatureNode.as_uri());
CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);
if (std::strcmp(featureURI, LV2_DATA_ACCESS_URI) == 0
|| std::strcmp(featureURI, LV2_INSTANCE_ACCESS_URI) == 0)
{
// we give a warning about this below
continue;
}


if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
info.hints |= CB::PLUGIN_IS_RTSAFE;
supported = false;
carla_stderr("LV2 plugin '%s' requires unsupported feature '%s'", info.label, featureURI);
} }

lilv_nodes_free(const_cast<LilvNodes*>(lilvFeatureNodes.me));
} }


// category
info.category = CB::PLUGIN_CATEGORY_NONE;
lilv_nodes_free(const_cast<LilvNodes*>(lilvRequiredFeatureNodes.me));
}


{
Lilv::Nodes lilvSupportedFeatureNodes(lilvPlugin.get_supported_features());

LILV_FOREACH(nodes, it, lilvSupportedFeatureNodes)
{ {
Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));
Lilv::Node lilvFeatureNode(lilvSupportedFeatureNodes.get(it));
const char* const featureURI(lilvFeatureNode.as_uri());
CARLA_SAFE_ASSERT_CONTINUE(featureURI != nullptr);


if (typeNodes.size() > 0)
if (std::strcmp(featureURI, LV2_CORE__hardRTCapable) == 0)
{ {
if (typeNodes.contains(lv2World.class_allpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_amplifier))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_analyzer))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_bandpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_chorus))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_comb))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_compressor))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_constant))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_converter))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_delay))
info.category = CB::PLUGIN_CATEGORY_DELAY;
if (typeNodes.contains(lv2World.class_distortion))
info.category = CB::PLUGIN_CATEGORY_DISTORTION;
if (typeNodes.contains(lv2World.class_dynamics))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_eq))
info.category = CB::PLUGIN_CATEGORY_EQ;
if (typeNodes.contains(lv2World.class_envelope))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_expander))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_filter))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_flanger))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_function))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_gate))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_generator))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_highpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_limiter))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_lowpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_mixer))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_modulator))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_multiEQ))
info.category = CB::PLUGIN_CATEGORY_EQ;
if (typeNodes.contains(lv2World.class_oscillator))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_paraEQ))
info.category = CB::PLUGIN_CATEGORY_EQ;
if (typeNodes.contains(lv2World.class_phaser))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_pitch))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_reverb))
info.category = CB::PLUGIN_CATEGORY_DELAY;
if (typeNodes.contains(lv2World.class_simulator))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_spatial))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_spectral))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_utility))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_waveshaper))
info.category = CB::PLUGIN_CATEGORY_DISTORTION;
if (typeNodes.contains(lv2World.class_instrument))
{
info.category = CB::PLUGIN_CATEGORY_SYNTH;
info.hints |= CB::PLUGIN_IS_SYNTH;
}
info.hints |= CB::PLUGIN_IS_RTSAFE;
}
else if (std::strcmp(featureURI, LV2_DATA_ACCESS_URI) == 0
|| std::strcmp(featureURI, LV2_INSTANCE_ACCESS_URI) == 0)
{
carla_stderr("LV2 plugin '%s' DSP wants UI feature '%s', ignoring this", info.label, featureURI);
} }
}

lilv_nodes_free(const_cast<LilvNodes*>(lilvSupportedFeatureNodes.me));
}


lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
// ----------------------------------------------------------------------------------------------------------------
// category

info.category = CB::PLUGIN_CATEGORY_NONE;

{
Lilv::Nodes typeNodes(lilvPlugin.get_value(lv2World.rdf_type));

if (typeNodes.size() > 0)
{
if (typeNodes.contains(lv2World.class_allpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_amplifier))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_analyzer))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_bandpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_chorus))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_comb))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_compressor))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_constant))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_converter))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_delay))
info.category = CB::PLUGIN_CATEGORY_DELAY;
if (typeNodes.contains(lv2World.class_distortion))
info.category = CB::PLUGIN_CATEGORY_DISTORTION;
if (typeNodes.contains(lv2World.class_dynamics))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_eq))
info.category = CB::PLUGIN_CATEGORY_EQ;
if (typeNodes.contains(lv2World.class_envelope))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_expander))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_filter))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_flanger))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_function))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_gate))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_generator))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_highpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_limiter))
info.category = CB::PLUGIN_CATEGORY_DYNAMICS;
if (typeNodes.contains(lv2World.class_lowpass))
info.category = CB::PLUGIN_CATEGORY_FILTER;
if (typeNodes.contains(lv2World.class_mixer))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_modulator))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_multiEQ))
info.category = CB::PLUGIN_CATEGORY_EQ;
if (typeNodes.contains(lv2World.class_oscillator))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_paraEQ))
info.category = CB::PLUGIN_CATEGORY_EQ;
if (typeNodes.contains(lv2World.class_phaser))
info.category = CB::PLUGIN_CATEGORY_MODULATOR;
if (typeNodes.contains(lv2World.class_pitch))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_reverb))
info.category = CB::PLUGIN_CATEGORY_DELAY;
if (typeNodes.contains(lv2World.class_simulator))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_spatial))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_spectral))
info.category = CB::PLUGIN_CATEGORY_OTHER;
if (typeNodes.contains(lv2World.class_utility))
info.category = CB::PLUGIN_CATEGORY_UTILITY;
if (typeNodes.contains(lv2World.class_waveshaper))
info.category = CB::PLUGIN_CATEGORY_DISTORTION;
if (typeNodes.contains(lv2World.class_instrument))
{
info.category = CB::PLUGIN_CATEGORY_SYNTH;
info.hints |= CB::PLUGIN_IS_SYNTH;
}
} }


// number data
info.audioIns = 0;
info.audioOuts = 0;
info.midiIns = 0;
info.midiOuts = 0;
info.parameterIns = 0;
info.parameterOuts = 0;
lilv_nodes_free(const_cast<LilvNodes*>(typeNodes.me));
}

// ----------------------------------------------------------------------------------------------------------------
// number data

for (uint i=0, count=lilvPlugin.get_num_ports(); i<count; ++i)
{
Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));

bool isInput;


for (uint i=0, count=lilvPlugin.get_num_ports(); i<count; ++i)
/**/ if (lilvPort.is_a(lv2World.port_input))
{
isInput = true;
}
else if (lilvPort.is_a(lv2World.port_output))
{
isInput = false;
}
else
{ {
Lilv::Port lilvPort(lilvPlugin.get_port_by_index(i));
const LilvNode* const symbolNode = lilvPort.get_symbol();
CARLA_SAFE_ASSERT_CONTINUE(symbolNode != nullptr && lilv_node_is_string(symbolNode));


bool isInput;
const char* const symbol = lilv_node_as_string(symbolNode);
CARLA_SAFE_ASSERT_CONTINUE(symbol != nullptr);


/**/ if (lilvPort.is_a(lv2World.port_input))
isInput = true;
else if (lilvPort.is_a(lv2World.port_output))
isInput = false;
else
carla_stderr("LV2 plugin '%s' port '%s' is neither input or output", info.label, symbol);
continue;
}

/**/ if (lilvPort.is_a(lv2World.port_control))
{
// skip some control ports
if (lilvPort.has_property(lv2World.reportsLatency))
continue; continue;


/**/ if (lilvPort.is_a(lv2World.port_control))
if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
{ {
// skip some control ports
if (lilvPort.has_property(lv2World.reportsLatency))
continue;
bool skip = false;


if (LilvNode* const designationNode = lilv_port_get(lilvPort.parent, lilvPort.me, lv2World.designation.me))
if (const char* const designation = lilv_node_as_string(designationNode))
{ {
bool skip = false;

if (const char* const designation = lilv_node_as_string(designationNode))
{
/**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
skip = true;
else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
skip = true;
else if (std::strcmp(designation, LV2_CORE__latency) == 0)
skip = true;
else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__bar) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beat) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__frame) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__speed) == 0)
skip = true;
else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
skip = true;
}

lilv_node_free(designationNode);

if (skip)
continue;
/**/ if (std::strcmp(designation, LV2_CORE__control) == 0)
skip = true;
else if (std::strcmp(designation, LV2_CORE__freeWheeling) == 0)
skip = true;
else if (std::strcmp(designation, LV2_CORE__latency) == 0)
skip = true;
else if (std::strcmp(designation, LV2_PARAMETERS__sampleRate) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__bar) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__barBeat) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beat) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beatUnit) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beatsPerBar) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__beatsPerMinute) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__frame) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__framesPerSecond) == 0)
skip = true;
else if (std::strcmp(designation, LV2_TIME__speed) == 0)
skip = true;
else if (std::strcmp(designation, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat) == 0)
skip = true;
} }


if (isInput)
++(info.parameterIns);
else
++(info.parameterOuts);
}
else if (lilvPort.is_a(lv2World.port_audio))
{
if (isInput)
++(info.audioIns);
else
++(info.audioOuts);
}
else if (lilvPort.is_a(lv2World.port_cv))
{
lilv_node_free(designationNode);

if (skip)
continue;
} }
else if (lilvPort.is_a(lv2World.port_atom))
{
Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));


for (LilvIter *it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
{
const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());

if (node.equals(lv2World.midi_event))
{
if (isInput)
++(info.midiIns);
else
++(info.midiOuts);
}
}
if (isInput)
++(info.parameterIns);
else
++(info.parameterOuts);
}
else if (lilvPort.is_a(lv2World.port_audio))
{
if (isInput)
++(info.audioIns);
else
++(info.audioOuts);
}
else if (lilvPort.is_a(lv2World.port_cv))
{
}
else if (lilvPort.is_a(lv2World.port_atom))
{
Lilv::Nodes supportNodes(lilvPort.get_value(lv2World.atom_supports));


lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
}
else if (lilvPort.is_a(lv2World.port_event))
for (LilvIter *it = lilv_nodes_begin(supportNodes.me); ! lilv_nodes_is_end(supportNodes.me, it); it = lilv_nodes_next(supportNodes.me, it))
{ {
if (lilvPort.supports_event(lv2World.midi_event))
const Lilv::Node node(lilv_nodes_get(supportNodes.me, it));
CARLA_SAFE_ASSERT_CONTINUE(node.is_uri());

if (node.equals(lv2World.midi_event))
{ {
if (isInput) if (isInput)
++(info.midiIns); ++(info.midiIns);
@@ -361,7 +391,12 @@ const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype,
++(info.midiOuts); ++(info.midiOuts);
} }
} }
else if (lilvPort.is_a(lv2World.port_midi))

lilv_nodes_free(const_cast<LilvNodes*>(supportNodes.me));
}
else if (lilvPort.is_a(lv2World.port_event))
{
if (lilvPort.supports_event(lv2World.midi_event))
{ {
if (isInput) if (isInput)
++(info.midiIns); ++(info.midiIns);
@@ -369,59 +404,105 @@ const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype,
++(info.midiOuts); ++(info.midiOuts);
} }
} }
else if (lilvPort.is_a(lv2World.port_midi))
{
if (isInput)
++(info.midiIns);
else
++(info.midiOuts);
}
else
{
const LilvNode* const symbolNode = lilvPort.get_symbol();
CARLA_SAFE_ASSERT_CONTINUE(symbolNode != nullptr && lilv_node_is_string(symbolNode));


// text data
static CarlaString suri, sname, smaker, slicense;
suri.clear(); sname.clear(); smaker.clear(); slicense.clear();

suri = lilvPlugin.get_uri().as_uri();
const char* const symbol = lilv_node_as_string(symbolNode);
CARLA_SAFE_ASSERT_CONTINUE(symbol != nullptr);


if (LilvNode* const nameNode = lilv_plugin_get_name(lilvPlugin.me))
{
if (const char* const name = lilv_node_as_string(nameNode))
sname = name;
lilv_node_free(nameNode);
supported = false;
carla_stderr("LV2 plugin '%s' port '%s' is required but has unsupported type", info.label, symbol);
} }
}


if (const char* const author = lilvPlugin.get_author_name().as_string())
smaker = author;
if (supported)
info.valid = true;


Lilv::Nodes licenseNodes(lilvPlugin.get_value(lv2World.doap_license));
return &info;
}


if (licenseNodes.size() > 0)
{
if (const char* const license = licenseNodes.get_first().as_string())
slicense = license;
}
const CarlaCachedPluginInfo* get_cached_plugin_sfz()
{
static CarlaCachedPluginInfo info;
return &info;
}


lilv_nodes_free(const_cast<LilvNodes*>(licenseNodes.me));
// -------------------------------------------------------------------------------------------------------------------


info.valid = true;
info.name = sname;
info.label = suri;
info.maker = smaker;
info.copyright = slicense;
uint carla_get_cached_plugin_count(CB::PluginType ptype, const char* pluginPath)
{
CARLA_SAFE_ASSERT_RETURN(isCachedPluginType(ptype), 0);
carla_debug("carla_get_cached_plugin_count(%i:%s)", ptype, CB::PluginType2Str(ptype));

switch (ptype)
{
case CB::PLUGIN_INTERNAL: {
uint32_t count = 0;
carla_get_native_plugins_data(&count);
return count;
}

case CB::PLUGIN_LV2: {
Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());
lv2World.initIfNeeded(pluginPath);
return lv2World.getPluginCount();
}

case CB::PLUGIN_SFZ: {
return 0;
}

default:
return 0;
}
}

const CarlaCachedPluginInfo* carla_get_cached_plugin_info(CB::PluginType ptype, uint index)
{
carla_debug("carla_get_cached_plugin_info(%i:%s, %i)", ptype, CB::PluginType2Str(ptype), index);

switch (ptype)
{
case CB::PLUGIN_INTERNAL: {
uint32_t count = 0;
const NativePluginDescriptor* const descs(carla_get_native_plugins_data(&count));
CARLA_SAFE_ASSERT_BREAK(index < count);
CARLA_SAFE_ASSERT_BREAK(descs != nullptr);

const NativePluginDescriptor& desc(descs[index]);
return get_cached_plugin_internal(desc);
}


return &info;
case CB::PLUGIN_LV2: {
Lv2WorldClass& lv2World(Lv2WorldClass::getInstance());

const LilvPlugin* const cPlugin(lv2World.getPluginFromIndex(index));
CARLA_SAFE_ASSERT_BREAK(cPlugin != nullptr);

Lilv::Plugin lilvPlugin(cPlugin);
CARLA_SAFE_ASSERT_BREAK(lilvPlugin.get_uri().is_uri());

return get_cached_plugin_lv2(lv2World, lilvPlugin);
}

case CB::PLUGIN_SFZ: {
return get_cached_plugin_sfz();
} }


default: default:
break; break;
} }


info.valid = true;
info.category = CB::PLUGIN_CATEGORY_NONE;
info.hints = 0x0;
info.audioIns = 0;
info.audioOuts = 0;
info.midiIns = 0;
info.midiOuts = 0;
info.parameterIns = 0;
info.parameterOuts = 0;
info.name = gNullCharPtr;
info.label = gNullCharPtr;
info.maker = gNullCharPtr;
info.copyright = gNullCharPtr;
static CarlaCachedPluginInfo info;
return &info; return &info;
} }




+ 7
- 0
source/backend/utils/PipeClient.cpp View File

@@ -107,6 +107,13 @@ void carla_pipe_client_lock(CarlaPipeClientHandle handle)
return ((ExposedCarlaPipeClient*)handle)->lockPipe(); return ((ExposedCarlaPipeClient*)handle)->lockPipe();
} }


void carla_pipe_client_unlock(CarlaPipeClientHandle handle)
{
CARLA_SAFE_ASSERT_RETURN(handle != nullptr,);

return ((ExposedCarlaPipeClient*)handle)->unlockPipe();
}

const char* carla_pipe_client_readlineblock(CarlaPipeClientHandle handle, uint timeout) const char* carla_pipe_client_readlineblock(CarlaPipeClientHandle handle, uint timeout)
{ {
CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr); CARLA_SAFE_ASSERT_RETURN(handle != nullptr, nullptr);


+ 30
- 148
source/discovery/carla-discovery.cpp View File

@@ -269,6 +269,26 @@ static intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t
// ------------------------------ Plugin Checks ----------------------------- // ------------------------------ Plugin Checks -----------------------------


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
static void print_cached_plugin(const CarlaCachedPluginInfo* const pinfo)
{
if (! pinfo->valid)
return;

DISCOVERY_OUT("init", "-----------");
DISCOVERY_OUT("build", BINARY_NATIVE);
DISCOVERY_OUT("hints", pinfo->hints);
DISCOVERY_OUT("name", pinfo->name);
DISCOVERY_OUT("maker", pinfo->maker);
DISCOVERY_OUT("label", pinfo->label);
DISCOVERY_OUT("audio.ins", pinfo->audioIns);
DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
DISCOVERY_OUT("midi.ins", pinfo->midiIns);
DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
DISCOVERY_OUT("end", "------------");
}

static void do_cached_check(const PluginType type) static void do_cached_check(const PluginType type)
{ {
const char* const plugPath = (type == PLUGIN_LV2) ? std::getenv("LV2_PATH") : nullptr; const char* const plugPath = (type == PLUGIN_LV2) ? std::getenv("LV2_PATH") : nullptr;
@@ -279,22 +299,7 @@ static void do_cached_check(const PluginType type)
const CarlaCachedPluginInfo* pinfo(carla_get_cached_plugin_info(type, i)); const CarlaCachedPluginInfo* pinfo(carla_get_cached_plugin_info(type, i));
CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr); CARLA_SAFE_ASSERT_CONTINUE(pinfo != nullptr);


if (! pinfo->valid)
continue;

DISCOVERY_OUT("init", "-----------");
DISCOVERY_OUT("build", BINARY_NATIVE);
DISCOVERY_OUT("hints", pinfo->hints);
DISCOVERY_OUT("name", pinfo->name);
DISCOVERY_OUT("maker", pinfo->maker);
DISCOVERY_OUT("label", pinfo->label);
DISCOVERY_OUT("audio.ins", pinfo->audioIns);
DISCOVERY_OUT("audio.outs", pinfo->audioOuts);
DISCOVERY_OUT("midi.ins", pinfo->midiIns);
DISCOVERY_OUT("midi.outs", pinfo->midiOuts);
DISCOVERY_OUT("parameters.ins", pinfo->parameterIns);
DISCOVERY_OUT("parameters.outs", pinfo->parameterOuts);
DISCOVERY_OUT("end", "------------");
print_cached_plugin(pinfo);
} }
} }
#endif #endif
@@ -868,17 +873,18 @@ static void do_lv2_check(const char* const bundle, const bool doInit)
// Get & check every plugin-instance // Get & check every plugin-instance
for (int i=0, count=URIs.size(); i < count; ++i) for (int i=0, count=URIs.size(); i < count; ++i)
{ {
const LV2_RDF_Descriptor* const rdfDescriptor(lv2_rdf_new(URIs[i].toRawUTF8(), false));
const char* const URI = URIs[i].toRawUTF8();
ScopedPointer<const LV2_RDF_Descriptor> rdfDescriptor(lv2_rdf_new(URI, false));


if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr) if (rdfDescriptor == nullptr || rdfDescriptor->URI == nullptr)
{ {
DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URIs[i].toRawUTF8() << "'");
DISCOVERY_OUT("error", "Failed to find LV2 plugin '" << URI << "'");
continue; continue;
} }


if (doInit) if (doInit)
{ {
// test if DLL is loadable, twice
// test if lib is loadable, twice
const lib_t libHandle1 = lib_open(rdfDescriptor->Binary); const lib_t libHandle1 = lib_open(rdfDescriptor->Binary);


if (libHandle1 == nullptr) if (libHandle1 == nullptr)
@@ -902,137 +908,13 @@ static void do_lv2_check(const char* const bundle, const bool doInit)
lib_close(libHandle2); lib_close(libHandle2);
} }


// test if we support all required ports and features
{
bool supported = true;

for (uint32_t j=0; j < rdfDescriptor->PortCount && supported; ++j)
{
const LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[j]);

if (is_lv2_port_supported(rdfPort->Types))
{
pass();
}
else if (! LV2_IS_PORT_OPTIONAL(rdfPort->Properties))
{
DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported port type (portName: '" << rdfPort->Name << "')");
supported = false;
break;
}
}

for (uint32_t j=0; j < rdfDescriptor->FeatureCount && supported; ++j)
{
const LV2_RDF_Feature& feature(rdfDescriptor->Features[j]);

if (std::strcmp(feature.URI, LV2_DATA_ACCESS_URI) == 0 || std::strcmp(feature.URI, LV2_INSTANCE_ACCESS_URI) == 0)
{
DISCOVERY_OUT("warning", "Plugin '" << rdfDescriptor->URI << "' DSP wants UI feature '" << feature.URI << "', ignoring this");
}
else if (feature.Required && ! is_lv2_feature_supported(feature.URI))
{
DISCOVERY_OUT("error", "Plugin '" << rdfDescriptor->URI << "' requires a non-supported feature '" << feature.URI << "'");
supported = false;
break;
}
}

if (! supported)
{
delete rdfDescriptor;
continue;
}
}

uint hints = 0x0;
int audioIns = 0;
int audioOuts = 0;
int midiIns = 0;
int midiOuts = 0;
int parametersIns = 0;
int parametersOuts = 0;

for (uint32_t j=0; j < rdfDescriptor->FeatureCount; ++j)
{
const LV2_RDF_Feature* const rdfFeature(&rdfDescriptor->Features[j]);

if (std::strcmp(rdfFeature->URI, LV2_CORE__hardRTCapable) == 0)
hints |= PLUGIN_IS_RTSAFE;
}

for (uint32_t j=0; j < rdfDescriptor->PortCount; ++j)
{
const LV2_RDF_Port* const rdfPort(&rdfDescriptor->Ports[j]);
const LilvPlugin* const cPlugin(lv2World.getPluginFromURI(URI));
CARLA_SAFE_ASSERT_CONTINUE(cPlugin != nullptr);


if (LV2_IS_PORT_AUDIO(rdfPort->Types))
{
if (LV2_IS_PORT_INPUT(rdfPort->Types))
audioIns += 1;
else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
audioOuts += 1;
}
else if (LV2_IS_PORT_CONTROL(rdfPort->Types))
{
if (LV2_IS_PORT_DESIGNATION_LATENCY(rdfPort->Designation))
{
pass();
}
else if (LV2_IS_PORT_DESIGNATION_SAMPLE_RATE(rdfPort->Designation))
{
pass();
}
else if (LV2_IS_PORT_DESIGNATION_FREEWHEELING(rdfPort->Designation))
{
pass();
}
else if (LV2_IS_PORT_DESIGNATION_TIME(rdfPort->Designation))
{
pass();
}
else
{
if (LV2_IS_PORT_INPUT(rdfPort->Types))
parametersIns += 1;
else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
parametersOuts += 1;
}
}
else if (LV2_PORT_SUPPORTS_MIDI_EVENT(rdfPort->Types))
{
if (LV2_IS_PORT_INPUT(rdfPort->Types))
midiIns += 1;
else if (LV2_IS_PORT_OUTPUT(rdfPort->Types))
midiOuts += 1;
}
}

if (LV2_IS_INSTRUMENT(rdfDescriptor->Type[0], rdfDescriptor->Type[1]))
hints |= PLUGIN_IS_SYNTH;

if (rdfDescriptor->UICount > 0)
hints |= PLUGIN_HAS_CUSTOM_UI;

DISCOVERY_OUT("init", "-----------");
DISCOVERY_OUT("build", BINARY_NATIVE);
DISCOVERY_OUT("hints", hints);

if (rdfDescriptor->Name != nullptr)
DISCOVERY_OUT("name", rdfDescriptor->Name);
if (rdfDescriptor->Author != nullptr)
DISCOVERY_OUT("maker", rdfDescriptor->Author);

DISCOVERY_OUT("uri", rdfDescriptor->URI);
DISCOVERY_OUT("uniqueId", rdfDescriptor->UniqueID);
DISCOVERY_OUT("audio.ins", audioIns);
DISCOVERY_OUT("audio.outs", audioOuts);
DISCOVERY_OUT("midi.ins", midiIns);
DISCOVERY_OUT("midi.outs", midiOuts);
DISCOVERY_OUT("parameters.ins", parametersIns);
DISCOVERY_OUT("parameters.outs", parametersOuts);
DISCOVERY_OUT("end", "------------");
Lilv::Plugin lilvPlugin(cPlugin);
CARLA_SAFE_ASSERT_CONTINUE(lilvPlugin.get_uri().is_uri());


delete rdfDescriptor;
print_cached_plugin(get_cached_plugin_lv2(lv2World, lilvPlugin));
} }
} }




Loading…
Cancel
Save