2 * Carla CachedPlugins Test
3 * Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaUtils.h"
19 #include "CarlaLv2Utils.hpp"
20 #include "CarlaString.hpp"
22 namespace CB
= CarlaBackend
;
24 static const char* const gNullCharPtr
= "";
26 // -------------------------------------------------------------------------------------------------------------------
28 _CarlaCachedPluginInfo::_CarlaCachedPluginInfo() noexcept
29 : category(CB::PLUGIN_CATEGORY_NONE
),
40 copyright(gNullCharPtr
) {}
42 // -------------------------------------------------------------------------------------------------------------------
46 Lv2WorldClass
& lv2World(Lv2WorldClass::getInstance());
47 lv2World
.initIfNeeded("~/.lv2/");
49 const uint pcount
= lv2World
.getPluginCount();
50 CARLA_SAFE_ASSERT_RETURN(pcount
> 0, 1);
52 CarlaCachedPluginInfo info
;
54 for (uint index
=0; index
<pcount
; ++index
)
56 const LilvPlugin
* const cPlugin(lv2World
.getPluginFromIndex(index
));
57 CARLA_SAFE_ASSERT_BREAK(cPlugin
!= nullptr);
59 Lilv::Plugin
lilvPlugin(cPlugin
);
60 CARLA_SAFE_ASSERT_BREAK(lilvPlugin
.get_uri().is_uri());
62 carla_stdout("Filling info for LV2 with URI '%s'", lilvPlugin
.get_uri().as_uri());
67 if (lilvPlugin
.get_uis().size() > 0 || lilvPlugin
.get_modgui_resources_directory().as_uri() != nullptr)
68 info
.hints
|= CB::PLUGIN_HAS_CUSTOM_UI
;
71 Lilv::Nodes
lilvFeatureNodes(lilvPlugin
.get_supported_features());
73 LILV_FOREACH(nodes
, it
, lilvFeatureNodes
)
75 Lilv::Node
lilvFeatureNode(lilvFeatureNodes
.get(it
));
76 const char* const featureURI(lilvFeatureNode
.as_uri());
77 CARLA_SAFE_ASSERT_CONTINUE(featureURI
!= nullptr);
79 if (std::strcmp(featureURI
, LV2_CORE__hardRTCapable
) == 0)
80 info
.hints
|= CB::PLUGIN_IS_RTSAFE
;
83 lilv_nodes_free(const_cast<LilvNodes
*>(lilvFeatureNodes
.me
));
87 info
.category
= CB::PLUGIN_CATEGORY_NONE
;
90 Lilv::Nodes
typeNodes(lilvPlugin
.get_value(lv2World
.rdf_type
));
92 if (typeNodes
.size() > 0)
94 if (typeNodes
.contains(lv2World
.class_allpass
))
95 info
.category
= CB::PLUGIN_CATEGORY_FILTER
;
96 if (typeNodes
.contains(lv2World
.class_amplifier
))
97 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
98 if (typeNodes
.contains(lv2World
.class_analyzer
))
99 info
.category
= CB::PLUGIN_CATEGORY_UTILITY
;
100 if (typeNodes
.contains(lv2World
.class_bandpass
))
101 info
.category
= CB::PLUGIN_CATEGORY_FILTER
;
102 if (typeNodes
.contains(lv2World
.class_chorus
))
103 info
.category
= CB::PLUGIN_CATEGORY_MODULATOR
;
104 if (typeNodes
.contains(lv2World
.class_comb
))
105 info
.category
= CB::PLUGIN_CATEGORY_FILTER
;
106 if (typeNodes
.contains(lv2World
.class_compressor
))
107 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
108 if (typeNodes
.contains(lv2World
.class_constant
))
109 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
110 if (typeNodes
.contains(lv2World
.class_converter
))
111 info
.category
= CB::PLUGIN_CATEGORY_UTILITY
;
112 if (typeNodes
.contains(lv2World
.class_delay
))
113 info
.category
= CB::PLUGIN_CATEGORY_DELAY
;
114 if (typeNodes
.contains(lv2World
.class_distortion
))
115 info
.category
= CB::PLUGIN_CATEGORY_DISTORTION
;
116 if (typeNodes
.contains(lv2World
.class_dynamics
))
117 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
118 if (typeNodes
.contains(lv2World
.class_eq
))
119 info
.category
= CB::PLUGIN_CATEGORY_EQ
;
120 if (typeNodes
.contains(lv2World
.class_envelope
))
121 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
122 if (typeNodes
.contains(lv2World
.class_expander
))
123 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
124 if (typeNodes
.contains(lv2World
.class_filter
))
125 info
.category
= CB::PLUGIN_CATEGORY_FILTER
;
126 if (typeNodes
.contains(lv2World
.class_flanger
))
127 info
.category
= CB::PLUGIN_CATEGORY_MODULATOR
;
128 if (typeNodes
.contains(lv2World
.class_function
))
129 info
.category
= CB::PLUGIN_CATEGORY_UTILITY
;
130 if (typeNodes
.contains(lv2World
.class_gate
))
131 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
132 if (typeNodes
.contains(lv2World
.class_generator
))
133 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
134 if (typeNodes
.contains(lv2World
.class_highpass
))
135 info
.category
= CB::PLUGIN_CATEGORY_FILTER
;
136 if (typeNodes
.contains(lv2World
.class_limiter
))
137 info
.category
= CB::PLUGIN_CATEGORY_DYNAMICS
;
138 if (typeNodes
.contains(lv2World
.class_lowpass
))
139 info
.category
= CB::PLUGIN_CATEGORY_FILTER
;
140 if (typeNodes
.contains(lv2World
.class_mixer
))
141 info
.category
= CB::PLUGIN_CATEGORY_UTILITY
;
142 if (typeNodes
.contains(lv2World
.class_modulator
))
143 info
.category
= CB::PLUGIN_CATEGORY_MODULATOR
;
144 if (typeNodes
.contains(lv2World
.class_multiEQ
))
145 info
.category
= CB::PLUGIN_CATEGORY_EQ
;
146 if (typeNodes
.contains(lv2World
.class_oscillator
))
147 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
148 if (typeNodes
.contains(lv2World
.class_paraEQ
))
149 info
.category
= CB::PLUGIN_CATEGORY_EQ
;
150 if (typeNodes
.contains(lv2World
.class_phaser
))
151 info
.category
= CB::PLUGIN_CATEGORY_MODULATOR
;
152 if (typeNodes
.contains(lv2World
.class_pitch
))
153 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
154 if (typeNodes
.contains(lv2World
.class_reverb
))
155 info
.category
= CB::PLUGIN_CATEGORY_DELAY
;
156 if (typeNodes
.contains(lv2World
.class_simulator
))
157 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
158 if (typeNodes
.contains(lv2World
.class_spatial
))
159 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
160 if (typeNodes
.contains(lv2World
.class_spectral
))
161 info
.category
= CB::PLUGIN_CATEGORY_OTHER
;
162 if (typeNodes
.contains(lv2World
.class_utility
))
163 info
.category
= CB::PLUGIN_CATEGORY_UTILITY
;
164 if (typeNodes
.contains(lv2World
.class_waveshaper
))
165 info
.category
= CB::PLUGIN_CATEGORY_DISTORTION
;
166 if (typeNodes
.contains(lv2World
.class_instrument
))
168 info
.category
= CB::PLUGIN_CATEGORY_SYNTH
;
169 info
.hints
|= CB::PLUGIN_IS_SYNTH
;
173 lilv_nodes_free(const_cast<LilvNodes
*>(typeNodes
.me
));
181 info
.parameterIns
= 0;
182 info
.parameterOuts
= 0;
184 for (uint i
=0, count
=lilvPlugin
.get_num_ports(); i
<count
; ++i
)
186 Lilv::Port
lilvPort(lilvPlugin
.get_port_by_index(i
));
190 /**/ if (lilvPort
.is_a(lv2World
.port_input
))
192 else if (lilvPort
.is_a(lv2World
.port_output
))
197 /**/ if (lilvPort
.is_a(lv2World
.port_control
))
199 // skip some control ports
200 if (lilvPort
.has_property(lv2World
.reportsLatency
))
203 if (LilvNode
* const designationNode
= lilv_port_get(lilvPort
.parent
, lilvPort
.me
, lv2World
.designation
.me
))
207 if (const char* const designation
= lilv_node_as_string(designationNode
))
209 /**/ if (std::strcmp(designation
, LV2_CORE__control
) == 0)
211 else if (std::strcmp(designation
, LV2_CORE__freeWheeling
) == 0)
213 else if (std::strcmp(designation
, LV2_CORE__latency
) == 0)
215 else if (std::strcmp(designation
, LV2_PARAMETERS__sampleRate
) == 0)
217 else if (std::strcmp(designation
, LV2_TIME__bar
) == 0)
219 else if (std::strcmp(designation
, LV2_TIME__barBeat
) == 0)
221 else if (std::strcmp(designation
, LV2_TIME__beat
) == 0)
223 else if (std::strcmp(designation
, LV2_TIME__beatUnit
) == 0)
225 else if (std::strcmp(designation
, LV2_TIME__beatsPerBar
) == 0)
227 else if (std::strcmp(designation
, LV2_TIME__beatsPerMinute
) == 0)
229 else if (std::strcmp(designation
, LV2_TIME__frame
) == 0)
231 else if (std::strcmp(designation
, LV2_TIME__framesPerSecond
) == 0)
233 else if (std::strcmp(designation
, LV2_TIME__speed
) == 0)
235 else if (std::strcmp(designation
, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat
) == 0)
239 lilv_node_free(designationNode
);
246 ++(info
.parameterIns
);
248 ++(info
.parameterOuts
);
250 else if (lilvPort
.is_a(lv2World
.port_audio
))
257 else if (lilvPort
.is_a(lv2World
.port_cv
))
260 else if (lilvPort
.is_a(lv2World
.port_atom
))
262 Lilv::Nodes
supportNodes(lilvPort
.get_value(lv2World
.atom_supports
));
264 for (LilvIter
*it
= lilv_nodes_begin(supportNodes
.me
); ! lilv_nodes_is_end(supportNodes
.me
, it
); it
= lilv_nodes_next(supportNodes
.me
, it
))
266 const Lilv::Node
node(lilv_nodes_get(supportNodes
.me
, it
));
267 CARLA_SAFE_ASSERT_CONTINUE(node
.is_uri());
269 if (node
.equals(lv2World
.midi_event
))
278 lilv_nodes_free(const_cast<LilvNodes
*>(supportNodes
.me
));
280 else if (lilvPort
.is_a(lv2World
.port_event
))
282 if (lilvPort
.supports_event(lv2World
.midi_event
))
290 else if (lilvPort
.is_a(lv2World
.port_midi
))
300 static CarlaString suri
, sname
, smaker
, slicense
;
301 suri
.clear(); sname
.clear(); smaker
.clear(); slicense
.clear();
303 suri
= lilvPlugin
.get_uri().as_uri();
305 if (LilvNode
* const nameNode
= lilv_plugin_get_name(lilvPlugin
.me
))
307 if (const char* const name
= lilv_node_as_string(nameNode
))
309 lilv_node_free(nameNode
);
312 if (const char* const author
= lilvPlugin
.get_author_name().as_string())
315 Lilv::Nodes
licenseNodes(lilvPlugin
.get_value(lv2World
.doap_license
));
317 if (licenseNodes
.size() > 0)
319 if (const char* const license
= licenseNodes
.get_first().as_string())
323 lilv_nodes_free(const_cast<LilvNodes
*>(licenseNodes
.me
));
328 info
.copyright
= slicense
;
334 // #include "CarlaUtils.cpp"