1 /*
2 * Copyright (C) 2012 Andreas Degert, Hermann Meyer
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18
19 #include <lrdf.h>
20 #include <ladspa.h>
21 #include <dlfcn.h>
22
23 #include "engine.h"
24
25 using Glib::ustring;
26 using gx_system::JsonParser;
27 using gx_system::JsonWriter;
28 using gx_system::JsonException;
29 using gx_engine::LV2Features;
30
31 namespace ladspa {
32
33 //#define HARD_RT_ONLY
34
35 static const unsigned long blacklist[] = {
36 1912, // jamincont (crashes on unload?)
37 //1044, 1045, 1046, 1047, // sine
38 };
39
lib_is_blacklisted(const std::string & name)40 static bool lib_is_blacklisted(const std::string& name) {
41 static const char *blacklist[] = {
42 "dssi-vst.so",
43 "ladspa_guitarix.so",
44 };
45 for (unsigned int i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); i++) {
46 if (name == blacklist[i]) {
47 return true;
48 }
49 }
50 return false;
51 }
52
53 static const unsigned long quirklist_no_cleanup[] = { 1912, 0 };
54 static const unsigned long quirklist_activate[] = { 1890, 1891, 1893, 1894, 1892, 1903, 1904, 0 };
55 static const struct {
56 int flag;
57 const unsigned long *ids;
58 } quirk_list[] = {
59 {1, quirklist_no_cleanup},
60 {2, quirklist_activate},
61 {0, 0}
62 };
63
64 #define unknown_category "External"
65
66 static const char *cat_subst[][2] = {
67 {"Reverbs", "Reverb"},
68 {"Filters", "Tone Control"},
69 {"EQs", "Tone Control"},
70 {"Compressors", "Guitar Effects"},
71 {"Utilities", "Misc"},
72 {"Delays", "Echo / Delay"},
73 {"Phasers", "Modulation"},
74 {"Chorus", "Modulation"},
75 {"Flangers", "Modulation"},
76 {"Modulators", "Modulation"},
77 {"Distortions", "Distortion"},
78 {"Waveshapers", "Distortion"},
79 {"Amplifiers", "Distortion"},
80 // added for LV2
81 {"Filter", "Tone Control"},
82 {"Distortion", "Distortion"},
83 {"Delay", "Echo / Delay"},
84 {"Modulator", "Modulation"},
85 {"Utility", "Misc"},
86 {"Compressor", "Guitar Effects"},
87 {0, 0}
88 };
89
90 /****************************************************************
91 ** PluginDesc, PortDesc
92 */
93
float_eq(float v1,float v2)94 static inline bool float_eq(float v1, float v2) {
95 return std::abs(v1 - v2) <= 1e-5 * std::abs(v1);
96 }
97
operator !=(const ChangeableValues & v1,const ChangeableValues & v2)98 bool operator!=(const ChangeableValues& v1, const ChangeableValues& v2) {
99 if (v1.set_flags != v2.set_flags) {
100 return true;
101 }
102 if (v1.is_set(ChangeableValues::name_set) && v1.name != v2.name) {
103 return true;
104 }
105 if (v1.is_set(ChangeableValues::dflt_set) && !float_eq(v1.dflt, v2.dflt)) {
106 return true;
107 }
108 if (v1.is_set(ChangeableValues::low_set) && !float_eq(v1.low, v2.low)) {
109 return true;
110 }
111 if (v1.is_set(ChangeableValues::up_set) && !float_eq(v1.up, v2.up)) {
112 return true;
113 }
114 if (v1.is_set(ChangeableValues::tp_set) && v1.tp != v2.tp) {
115 return true;
116 }
117 if (v1.is_set(ChangeableValues::newrow_set) && v1.newrow != v2.newrow) {
118 return true;
119 }
120 if (v1.enumdict.size() != v2.enumdict.size()) {
121 return true;
122 }
123 for (std::map<int, ustring>::const_iterator i = v1.enumdict.begin(); i != v1.enumdict.end(); ++i) {
124 std::map<int, ustring>::const_iterator j = v2.enumdict.find(i->first);
125 if (j == v2.enumdict.end() || j->second != i->second) {
126 return true;
127 }
128 }
129 return false;
130 }
131
132
ChangeableValues(gx_system::JsonParser & jp)133 ChangeableValues::ChangeableValues(gx_system::JsonParser& jp)
134 : name(), dflt(), low(), up(), tp(tp_scale), enumdict(), newrow(), set_flags(0) {
135 jp.next(gx_system::JsonParser::begin_object);
136 while (jp.peek() != gx_system::JsonParser::end_object) {
137 jp.next(gx_system::JsonParser::value_key);
138 if (jp.read_kv("name", name) ||
139 jp.read_kv("dflt", dflt) ||
140 jp.read_kv("low", low) ||
141 jp.read_kv("up", up) ||
142 jp.read_kv("tp", tp) ||
143 jp.read_kv("newrow", newrow) ||
144 jp.read_kv("set_flags", set_flags)) {
145 } else if (jp.current_value() == "enumdict") {
146 jp.next(gx_system::JsonParser::begin_object);
147 while (jp.peek() != gx_system::JsonParser::end_object) {
148 jp.next(gx_system::JsonParser::value_key);
149 int k = jp.current_value_int();
150 jp.next(gx_system::JsonParser::value_string);
151 enumdict[k] = jp.current_value();
152 }
153 jp.next(gx_system::JsonParser::end_object);
154 } else {
155 gx_print_warning(
156 "ladspa::ChangeableValues", Glib::ustring::compose("unknown key: %1", jp.current_value()));
157 jp.skip_object();
158 }
159 }
160 jp.next(gx_system::JsonParser::end_object);
161 }
162
serializeJSON(gx_system::JsonWriter & jw)163 void ChangeableValues::serializeJSON(gx_system::JsonWriter& jw) {
164 jw.begin_object();
165 jw.write_kv("name", name);
166 jw.write_kv("dflt", dflt);
167 jw.write_kv("low", low);
168 jw.write_kv("up", up);
169 jw.write_kv("tp", tp);
170 jw.write_kv("newrow", newrow);
171 jw.write_kv("set_flags", set_flags);
172 jw.write_key("enumdict");
173 jw.begin_object();
174 for (std::map<int, Glib::ustring>::iterator i = enumdict.begin(); i != enumdict.end(); ++i) {
175 jw.write_kv(gx_system::to_string(i->first).c_str(), i->second);
176 }
177 jw.end_object();
178 jw.end_object();
179 }
180
get_excl_flags(DisplayType t) const181 int ChangeableValues::get_excl_flags(DisplayType t) const {
182 switch (t) {
183 case tp_enabled:
184 return low_set|up_set;
185 case tp_toggle:
186 return low_set|up_set;
187 case tp_display:
188 return dflt_set;
189 case tp_display_toggle:
190 return dflt_set|low_set|up_set;
191 case tp_none:
192 return dflt_set|low_set|up_set;
193 default:
194 return 0;
195 }
196 }
197
has_settings(DisplayType t) const198 bool ChangeableValues::has_settings(DisplayType t) const {
199 if ((set_flags & ~get_excl_flags(t)) || enumdict.size()) {
200 return true;
201 }
202 return false;
203 }
204
PortDesc(int idx_,int pos_,bool is_output_,ustring name,const LADSPA_PortRangeHint & hint)205 PortDesc::PortDesc(int idx_, int pos_, bool is_output_, ustring name, const LADSPA_PortRangeHint& hint)
206 : idx(idx_), pos(pos_), is_output(is_output_), hint_desc(hint.HintDescriptor),
207 fake_low(false), fake_up(false), fake_dflt(false),
208 step(stp_normal), use_sr(false), has_sr(LADSPA_IS_HINT_SAMPLE_RATE(hint_desc)),
209 has_caption(true), factory(), user() {
210 factory.set_name(name);
211 set_range_default(hint, factory);
212 set_default_value(hint, factory);
213 set_tp_default(hint, factory);
214 }
215
PortDesc(gx_system::JsonParser & jp)216 PortDesc::PortDesc(gx_system::JsonParser& jp)
217 : idx(), pos(), is_output(), hint_desc(),
218 fake_low(false), fake_up(false), fake_dflt(false),
219 step(stp_normal), use_sr(false), has_sr(false),
220 has_caption(true), factory(), user() {
221 jp.next(gx_system::JsonParser::begin_object);
222 while (jp.peek() != gx_system::JsonParser::end_object) {
223 jp.next(gx_system::JsonParser::value_key);
224 if (jp.read_kv("idx", idx) ||
225 jp.read_kv("pos", pos) ||
226 jp.read_kv("is_output", is_output) ||
227 jp.read_kv("hint_desc", hint_desc) ||
228 jp.read_kv("fake_low", fake_low) ||
229 jp.read_kv("fake_up", fake_up) ||
230 jp.read_kv("fake_dflt", fake_dflt) ||
231 jp.read_kv("step", step) ||
232 jp.read_kv("use_sr", use_sr) ||
233 jp.read_kv("has_sr", has_sr) ||
234 jp.read_kv("has_caption", has_caption)) {
235 } else if (jp.current_value() == "factory") {
236 factory = ChangeableValues(jp);
237 } else if (jp.current_value() == "user") {
238 user = ChangeableValues(jp);
239 } else {
240 gx_print_warning(
241 "ladspa::PortDesc", Glib::ustring::compose("unknown key: %1", jp.current_value()));
242 jp.skip_object();
243 }
244 }
245 jp.next(gx_system::JsonParser::end_object);
246 }
247
serializeJSON(gx_system::JsonWriter & jw)248 void PortDesc::serializeJSON(gx_system::JsonWriter& jw) {
249 jw.begin_object();
250 jw.write_kv("idx", idx);
251 jw.write_kv("pos", pos);
252 jw.write_kv("is_output", is_output);
253 jw.write_kv("hint_desc", hint_desc);
254 jw.write_kv("fake_low", fake_low);
255 jw.write_kv("fake_up", fake_up);
256 jw.write_kv("fake_dflt", fake_dflt);
257 jw.write_kv("step", step);
258 jw.write_kv("use_sr", use_sr);
259 jw.write_kv("has_sr", has_sr);
260 jw.write_kv("has_caption", has_caption);
261 jw.write_key("factory");
262 factory.serializeJSON(jw);
263 jw.write_key("user");
264 user.serializeJSON(jw);
265 jw.end_object();
266 }
267
set_default_value(const LADSPA_PortRangeHint & h,ChangeableValues & store)268 void PortDesc::set_default_value(const LADSPA_PortRangeHint& h, ChangeableValues& store) {
269 if (!LADSPA_IS_HINT_HAS_DEFAULT(h.HintDescriptor)) {
270 store.unset(ChangeableValues::dflt_set);
271 } else if (LADSPA_IS_HINT_DEFAULT_0(h.HintDescriptor)) {
272 store.set_dflt(0);
273 } else if (LADSPA_IS_HINT_DEFAULT_1(h.HintDescriptor)) {
274 store.set_dflt(1);
275 } else if (LADSPA_IS_HINT_DEFAULT_100(h.HintDescriptor)) {
276 store.set_dflt(100);
277 } else if (LADSPA_IS_HINT_DEFAULT_440(h.HintDescriptor)) {
278 store.set_dflt(440);
279 } else if (LADSPA_IS_HINT_DEFAULT_MINIMUM(h.HintDescriptor)) {
280 store.set_dflt(get_low());
281 } else if (LADSPA_IS_HINT_DEFAULT_MAXIMUM(h.HintDescriptor)) {
282 store.set_dflt(get_up());
283 } else {
284 float low = get_low();
285 float up = get_up();
286 if (!factory.is_set(ChangeableValues::low_set) || !factory.is_set(ChangeableValues::up_set)) {
287 store.unset(ChangeableValues::dflt_set);
288 } else if (LADSPA_IS_HINT_LOGARITHMIC(hint_desc)) {
289 if (low > 0) {
290 if (LADSPA_IS_HINT_DEFAULT_LOW(h.HintDescriptor)) {
291 store.set_dflt(exp(log(low)*0.75 + log(up)*0.25));
292 } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(h.HintDescriptor)) {
293 store.set_dflt(exp(log(low)*0.5 + log(up)*0.5));
294 } else if (LADSPA_IS_HINT_DEFAULT_HIGH(h.HintDescriptor)) {
295 store.set_dflt(exp(log(low)*0.25 + log(up)*0.75));
296 }
297 } else {
298 store.unset(ChangeableValues::dflt_set);
299 }
300 } else {
301 if (LADSPA_IS_HINT_DEFAULT_LOW(h.HintDescriptor)) {
302 store.set_dflt(low * 0.75 + up * 0.25);
303 } else if (LADSPA_IS_HINT_DEFAULT_MIDDLE(h.HintDescriptor)) {
304 store.set_dflt(low * 0.5 + up * 0.5);
305 } else if (LADSPA_IS_HINT_DEFAULT_HIGH(h.HintDescriptor)) {
306 store.set_dflt(low * 0.25 + up * 0.75);
307 }
308 }
309 }
310 }
311
set_range_default(const LADSPA_PortRangeHint & h,ChangeableValues & store)312 void PortDesc::set_range_default(const LADSPA_PortRangeHint& h, ChangeableValues& store) {
313 if (LADSPA_IS_HINT_TOGGLED(h.HintDescriptor)) {
314 store.set_low(0);
315 store.set_up(1);
316 } else {
317 if (LADSPA_IS_HINT_BOUNDED_BELOW(h.HintDescriptor)) {
318 store.set_low(h.LowerBound);
319 } else {
320 store.unset(ChangeableValues::low_set);
321 }
322 if (LADSPA_IS_HINT_BOUNDED_ABOVE(h.HintDescriptor)) {
323 store.set_up(h.UpperBound);
324 } else {
325 store.unset(ChangeableValues::up_set);
326 }
327 }
328 }
329
reset()330 void PortDesc::reset() {
331 step = stp_normal;
332 use_sr = false;
333 has_sr = LADSPA_IS_HINT_SAMPLE_RATE(hint_desc);
334 has_caption = true;
335 user = ChangeableValues();
336 }
337
set_low(float v)338 void PortDesc::set_low(float v) {
339 if (!fake_low && float_eq(v, factory.get_low())) {
340 user.unset(ChangeableValues::low_set);
341 } else {
342 user.set_low(v);
343 }
344 }
345
set_up(float v)346 void PortDesc::set_up(float v) {
347 if (!fake_up && float_eq(v, factory.get_up())) {
348 user.unset(ChangeableValues::up_set);
349 } else {
350 user.set_up(v);
351 }
352 }
353
set_dflt(float v)354 void PortDesc::set_dflt(float v) {
355 if (!fake_dflt && float_eq(v, factory.get_dflt())) {
356 user.unset(ChangeableValues::dflt_set);
357 } else {
358 user.set_dflt(v);
359 }
360 }
361
set_tp(DisplayType v)362 void PortDesc::set_tp(DisplayType v) {
363 if (v == factory.get_tp()) {
364 user.unset(ChangeableValues::tp_set);
365 } else {
366 user.set_tp(v);
367 }
368 }
369
set_newrow(bool v)370 void PortDesc::set_newrow(bool v) {
371 if (v == factory.get_newrow()) {
372 user.unset(ChangeableValues::newrow_set);
373 } else {
374 user.set_newrow(v);
375 }
376 }
377
get_enum(int idx)378 ustring PortDesc::get_enum(int idx) {
379 std::map<int, ustring>::iterator i;
380 i = user.find_enum(idx);
381 if (i != user.enum_end()) {
382 return i->second;
383 }
384 i = factory.find_enum(idx);
385 if (i != factory.enum_end()) {
386 return i->second;
387 }
388 return "";
389 }
390
check_changed(const PortDesc & vp) const391 bool PortDesc::check_changed(const PortDesc& vp) const {
392 if (pos != vp.pos) {
393 return true;
394 }
395 if (fake_low != vp.fake_low) {
396 return true;
397 }
398 if (fake_up != vp.fake_up) {
399 return true;
400 }
401 if (fake_dflt != vp.fake_dflt) {
402 return true;
403 }
404 if (step != vp.step) {
405 return true;
406 }
407 if (use_sr != vp.use_sr) {
408 return true;
409 }
410 if (has_sr != vp.has_sr) {
411 return true;
412 }
413 if (has_caption != vp.has_caption) {
414 return true;
415 }
416 if (factory != vp.factory) {
417 return true;
418 }
419 if (user != vp.user) {
420 return true;
421 }
422 return false;
423 }
424
has_settings()425 bool PortDesc::has_settings() {
426 return !has_caption || step != stp_normal || use_sr || user.has_settings(get_tp());
427 }
428
fixup(bool newrow)429 void PortDesc::fixup(bool newrow) {
430 ChangeableValues& f = factory;
431 f.set_newrow(newrow);
432 if (LADSPA_IS_HINT_LOGARITHMIC(hint_desc)) {
433 if (!f.is_set(ChangeableValues::low_set) && !f.is_set(ChangeableValues::up_set)) {
434 if (!f.is_set(ChangeableValues::dflt_set)) {
435 f.set_up(1.0);
436 f.set_low(1.0/1000.0);
437 f.set_dflt(sqrt(f.get_low()*f.get_up()));
438 fake_dflt = true;
439 } else if (f.get_dflt() <= 0) {
440 f.set_dflt(1.0);
441 fake_dflt = true;
442 f.set_low(f.get_dflt()/100.0);
443 f.set_up(f.get_dflt()*100.0);
444 } else {
445 f.set_low(f.get_dflt()/100.0);
446 f.set_up(f.get_dflt()*100.0);
447 }
448 fake_low = fake_up = true;
449 } else if (!f.is_set(ChangeableValues::low_set)) {
450 if (!f.is_set(ChangeableValues::dflt_set)) {
451 f.set_low(f.get_up()/1000.0);
452 f.set_dflt(f.get_low());
453 fake_dflt = true;
454 } else {
455 if (f.get_dflt() >= f.get_up()) {
456 f.set_dflt(f.get_up());
457 f.set_low(f.get_up() / 1000.0);
458 } else {
459 f.set_low(f.get_dflt());
460 }
461 }
462 fake_low = true;
463 } else if (!f.is_set(ChangeableValues::up_set)) {
464 if (f.get_low() == 0) {
465 f.set_low(1e-1);
466 fake_low = true;
467 }
468 if (!f.is_set(ChangeableValues::dflt_set)) {
469 f.set_up(f.get_low() * 1000.0);
470 f.set_dflt(f.get_low());
471 fake_dflt = true;
472 } else {
473 if (f.get_dflt() <= f.get_low()) {
474 f.set_dflt(f.get_low());
475 f.set_up(f.get_low() * 1000.0);
476 } else {
477 f.set_up(f.get_dflt());
478 }
479 }
480 fake_up = true;
481 } else if (f.get_low() <= 0) {
482 f.set_low(1e-7);
483 fake_low = true;
484 }
485 } else {
486 if (!f.is_set(ChangeableValues::low_set) && !f.is_set(ChangeableValues::up_set)) {
487 if (!f.is_set(ChangeableValues::dflt_set)) {
488 f.set_low(-1000);
489 f.set_up(1000);
490 f.set_dflt(0);
491 fake_dflt = true;
492 } else {
493 f.set_low(f.get_dflt() - 100);
494 f.set_up(f.get_dflt() + 100);
495 }
496 fake_low = fake_up = true;
497 } else if (!f.is_set(ChangeableValues::low_set)) {
498 if (!f.is_set(ChangeableValues::dflt_set)) {
499 f.set_low(f.get_up() - 1000);
500 f.set_dflt(f.get_low());
501 fake_dflt = true;
502 } else {
503 if (f.get_dflt() >= f.get_up()) {
504 f.set_dflt(f.get_up());
505 f.set_low(f.get_up() - 1000);
506 } else {
507 f.set_low(f.get_dflt());
508 }
509 }
510 fake_low = true;
511 } else if (!f.is_set(ChangeableValues::up_set)) {
512 if (!f.is_set(ChangeableValues::dflt_set)) {
513 f.set_up(f.get_low() + 1000);
514 f.set_dflt(f.get_low());
515 fake_dflt = true;
516 } else {
517 if (f.get_dflt() <= f.get_low()) {
518 f.set_dflt(f.get_low());
519 f.set_up(f.get_low() + 1000);
520 } else {
521 f.set_up(f.get_dflt());
522 }
523 }
524 fake_up = true;
525 }
526 }
527 if (!f.is_set(ChangeableValues::dflt_set)) {
528 fake_dflt = true;
529 f.set_dflt(f.get_low());
530 }
531 if (f.get_tp() == tp_enum) {
532 for (int k = int(f.get_low()); k < int(f.get_up()+1); k++) {
533 if (!f.has_enumkey(k)) {
534 f.set_enumvalue(k, gx_system::to_string(k));
535 }
536 }
537 }
538 }
539
calc_step()540 float PortDesc::calc_step() {
541 if (get_tp() == tp_enabled || get_tp() == tp_toggle || get_tp() == tp_enum || get_tp() == tp_int) {
542 return 1.0;
543 }
544 float up = get_up();
545 float low = get_low();
546 if (get_tp() == tp_scale_log) {
547 if (step == stp_coarse) {
548 return pow(up/low, 1.0/50);
549 }
550 if (step == stp_normal) {
551 return pow(up/low, 1.0/100);
552 }
553 if (step == stp_fine) {
554 return pow(up/low, 1.0/500);
555 }
556 assert(false);
557 return 1.0;
558 } else {
559 float s = 1.0;
560 if (step == stp_coarse) {
561 s = (up - low) / 30.0;
562 }
563 if (step == stp_normal) {
564 s = (up - low) / 300.0;
565 }
566 if (step == stp_fine) {
567 s = (up - low) / 3000.0;
568 }
569 if (has_sr && !use_sr) {
570 s *= SR;
571 }
572 return pow(10.0, round(log10(s)));
573 }
574 }
575
set_tp_default(const LADSPA_PortRangeHint & h,ChangeableValues & store)576 void PortDesc::set_tp_default(const LADSPA_PortRangeHint& h, ChangeableValues& store) {
577 if (is_output) {
578 if (LADSPA_IS_HINT_TOGGLED(h.HintDescriptor)) {
579 store.set_tp(tp_display_toggle);
580 } else if (get_name() == "latency") {
581 store.set_tp(tp_none);
582 } else {
583 store.set_tp(tp_display);
584 }
585 } else if (LADSPA_IS_HINT_TOGGLED(h.HintDescriptor)) {
586 store.set_tp(tp_toggle);
587 } else if (LADSPA_IS_HINT_LOGARITHMIC(hint_desc)) {
588 store.set_tp(tp_scale_log);
589 } else if (LADSPA_IS_HINT_INTEGER(h.HintDescriptor)) {
590 store.set_tp(tp_int);
591 } else {
592 store.set_tp(tp_scale);
593 }
594 }
595
set_default(float value,ustring label)596 void PortDesc::set_default(float value, ustring label) {
597 if (!factory.is_set(ChangeableValues::dflt_set)) {
598 factory.set_dflt(value);
599 }
600 }
601
output(JsonWriter & jw)602 void PortDesc::output(JsonWriter& jw) {
603 float dflt = get_dflt();
604 float low = get_low();
605 float up = get_up();
606 if (has_sr && !use_sr) {
607 if (factory.is_set(ChangeableValues::dflt_set)) {
608 dflt *= SR;
609 }
610 if (factory.is_set(ChangeableValues::low_set)) {
611 low *= SR;
612 }
613 if (factory.is_set(ChangeableValues::up_set)) {
614 up *= SR;
615 }
616 }
617 jw.begin_array();
618 jw.write(idx);
619 jw.begin_array();
620 jw.write(step);
621 jw.end_array();
622 if (user.is_set(ChangeableValues::name_set)) {
623 jw.write(user.get_name());
624 } else {
625 jw.write("");
626 }
627 jw.write(use_sr);
628 jw.write(dflt);
629 jw.write(low);
630 jw.write(up);
631 jw.write(calc_step());
632 jw.write(get_tp());
633 jw.write(get_newrow());
634 jw.write(has_caption);
635 jw.begin_array();
636 if (get_tp() == tp_enum) {
637 int iup = int(round(up));
638 for (int i = int(round(low)); i < iup+1; ++i) {
639 jw.write(get_enum(i));
640 }
641 }
642 jw.end_array();
643 jw.end_array(true);
644 }
645
set_state(JsonParser & jp,int version)646 void PortDesc::set_state(JsonParser& jp, int version) {
647 jp.next(JsonParser::begin_array);
648 jp.next(JsonParser::value_number);
649 step = static_cast<step_mode>(jp.current_value_int());
650 jp.next(JsonParser::end_array);
651 jp.next(JsonParser::value_string);
652 if (!jp.current_value().empty()) {
653 user.set_name(jp.current_value());
654 }
655 jp.next(JsonParser::value_number);
656 use_sr = jp.current_value_int();
657 jp.next(JsonParser::value_number);
658 float dflt = jp.current_value_float();
659 jp.next(JsonParser::value_number);
660 float low = jp.current_value_float();
661 jp.next(JsonParser::value_number);
662 float up = jp.current_value_float();
663 jp.next(JsonParser::value_number);
664 jp.current_value_float(); // step value, ignored
665 jp.next(JsonParser::value_number);
666 DisplayType tp = DisplayType(jp.current_value_int());
667 if (tp != factory.get_tp()) {
668 user.set_tp(tp);
669 }
670 if (has_sr && !use_sr) {
671 dflt /= SR;
672 low /= SR;
673 up /= SR;
674 }
675 if (!float_eq(dflt, factory.get_dflt())) {
676 user.set_dflt(dflt);
677 }
678 if (!float_eq(low, factory.get_low())) {
679 user.set_low(low);
680 }
681 if (!float_eq(up, factory.get_up())) {
682 user.set_up(up);
683 }
684 jp.next(JsonParser::value_number);
685 bool b = bool(jp.current_value_int());
686 if (b != factory.get_newrow()) {
687 user.set_newrow(b);
688 }
689 jp.next(JsonParser::value_number);
690 b = bool(jp.current_value_int());
691 has_caption = b;
692 jp.next(JsonParser::begin_array);
693 int s = int(low);
694 while (jp.peek() != JsonParser::end_array) {
695 jp.next(JsonParser::value_string);
696 std::map<int, ustring>::iterator it = factory.find_enum(s);
697 if (it != factory.enum_end() && jp.current_value() != it->second) {
698 user.set_enumvalue(s, jp.current_value());
699 }
700 s += 1;
701 }
702 jp.next(JsonParser::end_array);
703 }
704
PluginDesc(const LADSPA_Descriptor & desc,int tp_,std::vector<PortDesc * > & ctrl_ports_,const std::string path_,int index_)705 PluginDesc::PluginDesc(const LADSPA_Descriptor& desc, int tp_, std::vector<PortDesc*>& ctrl_ports_, const std::string path_, int index_)
706 : UniqueID(desc.UniqueID), Label(desc.Label), Name(desc.Name), shortname(desc.Name), Maker(desc.Maker),
707 MasterIdx(-1), MasterLabel(), tp(tp_), ctrl_ports(ctrl_ports_), path(path_), index(index_),
708 category(unknown_category), deduced_category(unknown_category), quirks(), quirks_default(), is_lv2(false),
709 ladspa_category(), active(false), active_set(false), has_settings(false), add_wet_dry(0), stereo_to_mono(0), old(0) {
710 quirks = quirks_default = quirks_get();
711 }
712
PluginDesc(LilvWorld * world,const LilvPlugin * plugin,int tp_,std::vector<PortDesc * > & ctrl_ports_)713 PluginDesc::PluginDesc(LilvWorld *world, const LilvPlugin* plugin, int tp_, std::vector<PortDesc*>& ctrl_ports_)
714 : UniqueID(0), Label(), Name(), shortname(), Maker(),
715 MasterIdx(-1), MasterLabel(), tp(tp_), ctrl_ports(ctrl_ports_),
716 path(lilv_node_as_string(lilv_plugin_get_uri(plugin))), index(0),
717 category(unknown_category), deduced_category(unknown_category), quirks(), quirks_default(), is_lv2(true),
718 ladspa_category(), active(false), active_set(false), has_settings(false), add_wet_dry(0), stereo_to_mono(0), old(0) {
719 LilvNode* nd = lilv_plugin_get_name(plugin);
720 Glib::ustring s = lilv_node_as_string(nd);
721 lilv_node_free(nd);
722 Label = s;
723 Name = s;
724 shortname = s;
725 nd = lilv_plugin_get_author_name(plugin);
726 if (!nd) {
727 nd = lilv_plugin_get_project(plugin);
728 }
729 if (nd) {
730 Maker = lilv_node_as_string(nd);
731 } else {
732 Maker = "";
733 }
734 lilv_node_free(nd);
735 path = lilv_node_as_string(lilv_plugin_get_uri(plugin));
736 const LilvPluginClass* cls = lilv_plugin_get_class(plugin);
737 if (cls) {
738 std::vector<Glib::ustring> cats;
739 const LilvPluginClasses* pclasses = lilv_world_get_plugin_classes(world);
740 while (true) {
741 const LilvNode *pn = lilv_plugin_class_get_parent_uri(cls);
742 if (!pn) {
743 break;
744 }
745 const LilvPluginClass* pcls = lilv_plugin_classes_get_by_uri(pclasses, pn);
746 if (!pcls) {
747 break;
748 }
749 cats.insert(cats.begin(), lilv_node_as_string(lilv_plugin_class_get_label(cls)));
750 cls = pcls;
751 }
752 set_category(cats);
753 }
754 }
755
~PluginDesc()756 PluginDesc::~PluginDesc() {
757 delete old;
758 for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
759 delete *i;
760 }
761 }
762
PluginDesc(gx_system::JsonParser & jp)763 PluginDesc::PluginDesc(gx_system::JsonParser& jp):
764 UniqueID(),
765 Label(),
766 Name(),
767 shortname(),
768 Maker(),
769 MasterIdx(),
770 MasterLabel(),
771 tp(),
772 ctrl_ports(),
773 path(),
774 index(),
775 category(),
776 deduced_category(),
777 quirks(),
778 quirks_default(),
779 is_lv2(),
780 ladspa_category(),
781 active(),
782 active_set(),
783 has_settings(),
784 add_wet_dry(),
785 stereo_to_mono(),
786 old(0) {
787 jp.next(gx_system::JsonParser::begin_object);
788 while (jp.peek() != gx_system::JsonParser::end_object) {
789 jp.next(gx_system::JsonParser::value_key);
790 if (jp.read_kv("UniqueID", UniqueID) ||
791 jp.read_kv("Label", Label) ||
792 jp.read_kv("Name", Name) ||
793 jp.read_kv("shortname", shortname) ||
794 jp.read_kv("Maker", Maker) ||
795 jp.read_kv("MasterIdx", MasterIdx) ||
796 jp.read_kv("MasterLabel", MasterLabel) ||
797 jp.read_kv("tp", tp) ||
798 jp.read_kv("path", path) ||
799 jp.read_kv("index", index) ||
800 jp.read_kv("category", category) ||
801 jp.read_kv("deduced_category", deduced_category) ||
802 jp.read_kv("quirks", quirks) ||
803 jp.read_kv("quirks_default", quirks_default) ||
804 jp.read_kv("is_lv2", is_lv2) ||
805 jp.read_kv("ladspa_category", ladspa_category) ||
806 jp.read_kv("active", active) ||
807 jp.read_kv("active_set", active_set) ||
808 jp.read_kv("has_settings", has_settings) ||
809 jp.read_kv("add_wet_dry", add_wet_dry) ||
810 jp.read_kv("stereo_to_mono", stereo_to_mono)) {
811 } else if (jp.current_value() == "old") {
812 old = new PluginDesc(jp);
813 } else if (jp.current_value() == "ctrl_ports") {
814 jp.next(gx_system::JsonParser::begin_array);
815 while (jp.peek() != gx_system::JsonParser::end_array) {
816 ctrl_ports.push_back(new PortDesc(jp));
817 }
818 jp.next(gx_system::JsonParser::end_array);
819 } else {
820 gx_print_warning(
821 "ladspa::PluginDesc", Glib::ustring::compose("unknown key: %1", jp.current_value()));
822 jp.skip_object();
823 }
824 }
825 jp.next(gx_system::JsonParser::end_object);
826 }
827
serializeJSON(gx_system::JsonWriter & jw)828 void PluginDesc::serializeJSON(gx_system::JsonWriter& jw) {
829 jw.begin_object();
830 jw.write_kv("UniqueID", static_cast<unsigned int>(UniqueID));
831 jw.write_kv("Label", Label);
832 jw.write_kv("Name", Name);
833 jw.write_kv("shortname", shortname);
834 jw.write_kv("Maker", Maker);
835 jw.write_kv("MasterIdx", MasterIdx);
836 jw.write_kv("MasterLabel", MasterLabel);
837 jw.write_kv("tp", tp);
838 jw.write_kv("path", path);
839 jw.write_kv("index", index);
840 jw.write_kv("category", category);
841 jw.write_kv("deduced_category", deduced_category);
842 jw.write_kv("quirks", quirks);
843 jw.write_kv("quirks_default", quirks_default);
844 jw.write_kv("is_lv2", is_lv2);
845 jw.write_kv("ladspa_category", ladspa_category);
846 jw.write_kv("active", active);
847 jw.write_kv("active_set", active_set);
848 jw.write_kv("has_settings", has_settings);
849 jw.write_kv("add_wet_dry", add_wet_dry);
850 jw.write_kv("stereo_to_mono", stereo_to_mono);
851 if (old) {
852 jw.write_key("old");
853 old->serializeJSON(jw);
854 }
855 jw.write_key("ctrl_ports");
856 jw.begin_array();
857 for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
858 (*i)->serializeJSON(jw);
859 }
860 jw.end_array();
861 jw.end_object();
862 }
863
quirks_get()864 int PluginDesc::quirks_get() {
865 int flag = 0;
866 for (int i = 0; quirk_list[i].flag; i++) {
867 for (int j = 0; quirk_list[i].ids[j]; j++) {
868 if (UniqueID == quirk_list[i].ids[j]) {
869 flag |= quirk_list[i].flag;
870 }
871 }
872 }
873 return flag;
874 }
875
cmp_ctrl_ports(const PortDesc * a,const PortDesc * b)876 bool cmp_ctrl_ports(const PortDesc *a, const PortDesc *b) {
877 return a->pos < b->pos;
878 }
879
reset()880 void PluginDesc::reset() {
881 shortname = Name;
882 MasterIdx = -1;
883 MasterLabel = "";
884 add_wet_dry = 0;
885 category = deduced_category;
886 quirks = quirks_default;
887 has_settings = false;
888 std::sort(ctrl_ports.begin(), ctrl_ports.end(), cmp_ctrl_ports);
889 for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
890 (*p)->reset();
891 }
892 }
893
copy_ports(PluginDesc * p)894 void PluginDesc::copy_ports(PluginDesc *p) {
895 assert(ctrl_ports.size() == 0);
896 for (std::vector<PortDesc*>::iterator i = p->ctrl_ports.begin(); i != p->ctrl_ports.end(); ++i) {
897 ctrl_ports.push_back(new PortDesc(**i));
898 }
899 }
900
901 //static
add_plugin(const LADSPA_Descriptor & desc,pluginmap & d,const std::string & path,int index)902 void LadspaPluginList::add_plugin(const LADSPA_Descriptor& desc, pluginmap& d, const std::string& path, int index) {
903 for (unsigned int j = 0; j < sizeof(blacklist)/sizeof(blacklist[0]); j++) {
904 if (desc.UniqueID == blacklist[j]) {
905 return;
906 }
907 }
908 #ifdef HARD_RT_ONLY
909 if (!LADSPA_IS_HARD_RT_CAPABLE(desc.Properties)) {
910 return;
911 }
912 #endif
913 int n_in = 0;
914 int n_out = 0;
915 std::vector<PortDesc*> ctrl_ports;
916 int pos = 0;
917 for (unsigned int n = 0; n < desc.PortCount; n++) {
918 LADSPA_PortDescriptor pd = desc.PortDescriptors[n];
919 if (LADSPA_IS_PORT_AUDIO(pd)) {
920 if (LADSPA_IS_PORT_INPUT(pd)) {
921 n_in += 1;
922 } else {
923 n_out += 1;
924 }
925 } else {
926 ctrl_ports.push_back(new PortDesc(n, pos, LADSPA_IS_PORT_OUTPUT(pd), desc.PortNames[n], desc.PortRangeHints[n]));
927 pos += 1;
928 }
929 }
930 int tp;
931 if (n_in == 1 && n_out == 1) {
932 tp = 0;
933 } else if (n_in == 2 && n_out == 2) {
934 tp = 1;
935 } else {
936 for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
937 delete *i;
938 }
939 return;
940 }
941 d[make_key(desc.UniqueID)] = new PluginDesc(desc, tp, ctrl_ports, path, index);
942 }
943
944 //static
load_defs(const std::string & path,pluginmap & d)945 void LadspaPluginList::load_defs(const std::string& path, pluginmap& d) {
946 void *handle;
947 handle = dlopen(path.c_str(), RTLD_LOCAL|RTLD_NOW);
948 if (!handle) {
949 gx_print_warning(
950 "ladspalist",
951 ustring::compose(_("Cannot open plugin: %1\n"), dlerror()));
952 return;
953 }
954 LADSPA_Descriptor_Function ladspa_descriptor = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
955 const char *dlsym_error = dlerror();
956 if (dlsym_error) {
957 gx_print_warning("ladspalist", dlsym_error);
958 dlclose(handle);
959 handle = 0;
960 return;
961 }
962 int i = 0;
963 while (true) {
964 const LADSPA_Descriptor *desc = ladspa_descriptor(i);
965 if (!desc) {
966 break;
967 }
968 add_plugin(*desc, d, path, i);
969 i += 1;
970 }
971 dlclose(handle);
972 }
973
check_changed()974 bool PluginDesc::check_changed() {
975 if (!old) {
976 return false;
977 }
978 if (UniqueID != old->UniqueID) {
979 return true;
980 }
981 if (Label != old->Label) {
982 return true;
983 }
984 if (Name != old->Name) {
985 return true;
986 }
987 if (shortname != old->shortname) {
988 return true;
989 }
990 if (Maker != old->Maker) {
991 return true;
992 }
993 if (MasterIdx != old->MasterIdx) {
994 return true;
995 }
996 if (MasterIdx > -1 && MasterLabel != old->MasterLabel) {
997 return true;
998 }
999 if (add_wet_dry != old->add_wet_dry) {
1000 return true;
1001 }
1002 if (stereo_to_mono != old->stereo_to_mono) {
1003 return true;
1004 }
1005 if (tp != old->tp) {
1006 return true;
1007 }
1008 if (path != old->path) {
1009 return true;
1010 }
1011 if (index != old->index) {
1012 return true;
1013 }
1014 if (category != old->category) {
1015 return true;
1016 }
1017 if (deduced_category != old->deduced_category) {
1018 return true;
1019 }
1020 if (quirks != old->quirks) {
1021 return true;
1022 }
1023 if (quirks_default != old->quirks_default) {
1024 return true;
1025 }
1026 if (ladspa_category != old->ladspa_category) {
1027 return true;
1028 }
1029 for (unsigned int i = 0; i < ctrl_ports.size(); ++i) {
1030 if (ctrl_ports[i]->check_changed(*old->ctrl_ports[i])) {
1031 return true;
1032 }
1033 }
1034 return false;
1035 }
1036
_i_check_has_settings()1037 bool PluginDesc::_i_check_has_settings() {
1038 if (shortname != Name) {
1039 return true;
1040 }
1041 if (category != deduced_category) {
1042 return true;
1043 }
1044 if (quirks != quirks_default) {
1045 return true;
1046 }
1047 if (MasterIdx != -1) {
1048 return true;
1049 }
1050 for (int i = 0; i < static_cast<int>(ctrl_ports.size()); ++i) {
1051 if (i != ctrl_ports[i]->get_pos()) {
1052 return true;
1053 }
1054 if (ctrl_ports[i]->has_settings()) {
1055 return true;
1056 }
1057 }
1058 return false;
1059 }
1060
check_has_settings()1061 void PluginDesc::check_has_settings() {
1062 has_settings = _i_check_has_settings();
1063 }
1064
set_active(bool v)1065 int PluginDesc::set_active(bool v) {
1066 if (v == active) {
1067 return 0;
1068 }
1069 active = v;
1070 if (v == active_set) {
1071 return -1;
1072 }
1073 return 1;
1074 }
1075
set_add_wet_dry_controller(bool v)1076 void PluginDesc::set_add_wet_dry_controller(bool v) {
1077 if (v) {
1078 add_wet_dry = 1;
1079 } else {
1080 add_wet_dry = 0;
1081 }
1082 }
1083
set_stereo_to_mono(bool v)1084 void PluginDesc::set_stereo_to_mono(bool v) {
1085 if (v) {
1086 stereo_to_mono = 1;
1087 } else {
1088 stereo_to_mono = 0;
1089 }
1090 }
1091
fixup()1092 void PluginDesc::fixup() {
1093 int i = 0;
1094 for (unsigned int n = 0; n < ctrl_ports.size(); ++n) {
1095 bool newrow = false;
1096 if (ctrl_ports[n]->get_tp() != tp_none) {
1097 newrow = (i % 6 == 0 && i != 0);
1098 i += 1;
1099 }
1100 ctrl_ports[n]->fixup(newrow);
1101 }
1102 }
1103
set_category(const std::vector<ustring> & s)1104 void PluginDesc::set_category(const std::vector<ustring>& s) {
1105 bool found = false;
1106 ustring t = "";
1107 for (std::vector<ustring>::const_iterator i = s.begin(); i != s.end(); ++i) {
1108 if (!t.empty()) {
1109 t += "/";
1110 }
1111 t += *i;
1112 if (!found) {
1113 for (const char *(*p)[2] = cat_subst; (*p)[0]; ++p) {
1114 if (*i == (*p)[0]) {
1115 category = deduced_category = (*p)[1];
1116 found = true;
1117 break;
1118 }
1119 }
1120 }
1121 }
1122 ladspa_category = t;
1123 }
1124
set_default(int idx,float value,const ustring & label)1125 void PluginDesc::set_default(int idx, float value, const ustring& label) {
1126 for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1127 if ((*p)->idx == idx) {
1128 (*p)->set_default(value, label);
1129 return;
1130 }
1131 }
1132 }
1133
output(JsonWriter & jw)1134 void PluginDesc::output(JsonWriter& jw) {
1135 ustring s = shortname;
1136 if (s == Name) {
1137 s = "";
1138 }
1139 int idx = -1;
1140 ustring sm = "";
1141 if (MasterIdx >= 0) {
1142 for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1143 ++idx;
1144 if ((*p)->pos == MasterIdx) {
1145 sm = MasterLabel;
1146 break;
1147 }
1148 }
1149 }
1150 jw.begin_array();
1151 jw.write(3); // version
1152 jw.write(s);
1153 jw.write(category);
1154 jw.write(idx);
1155 jw.write(sm);
1156 jw.write(quirks | (is_lv2 ? gx_engine::is_lv2 : 0));
1157 jw.write(add_wet_dry);
1158 jw.write(stereo_to_mono);
1159 jw.begin_array(true);
1160 for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1161 (*p)->output(jw);
1162 }
1163 jw.end_array(true);
1164 jw.end_array(true);
1165 }
1166
output_entry(JsonWriter & jw)1167 void PluginDesc::output_entry(JsonWriter& jw) {
1168 jw.begin_array();
1169 jw.write(path);
1170 if (is_lv2) {
1171 jw.write(-1);
1172 } else {
1173 jw.write(index);
1174 }
1175 jw.write(uint(UniqueID));
1176 jw.write(Label);
1177 jw.end_array(true);
1178 }
1179
set_state(const ustring & fname)1180 void PluginDesc::set_state(const ustring& fname) {
1181 ifstream is(fname.c_str());
1182 if (is.fail()) {
1183 gx_print_error("ladspalist", ustring::compose(_("can't open %1"), fname));
1184 return;
1185 }
1186 try {
1187 JsonParser jp(&is);
1188 jp.next(JsonParser::begin_array);
1189 jp.next(JsonParser::value_number);
1190 int version = jp.current_value_int();
1191 jp.next(JsonParser::value_string);
1192 shortname = jp.current_value();
1193 if (shortname.empty()) {
1194 shortname = Name;
1195 }
1196 jp.next(JsonParser::value_string);
1197 category = jp.current_value();
1198 jp.next(JsonParser::value_number);
1199 MasterIdx = jp.current_value_int();
1200 jp.next(JsonParser::value_string);
1201 MasterLabel = jp.current_value();
1202 jp.next(JsonParser::value_number);
1203 quirks = jp.current_value_int();
1204 if (quirks & gx_engine::is_lv2) {
1205 quirks &= ~gx_engine::is_lv2;
1206 is_lv2 = true;
1207 }
1208 jp.next(JsonParser::value_number);
1209 add_wet_dry = jp.current_value_int();
1210 if (jp.peek() == JsonParser::value_number) {
1211 jp.next(JsonParser::value_number);
1212 stereo_to_mono = jp.current_value_int();
1213 }
1214 std::vector<PortDesc*> ports;
1215 jp.next(JsonParser::begin_array);
1216 int n = 0;
1217 int m_idx = MasterIdx;
1218 while (jp.peek() != JsonParser::end_array) {
1219 jp.next(JsonParser::begin_array);
1220 jp.next(JsonParser::value_number);
1221 int idx = jp.current_value_int();
1222 for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1223 if ((*p)->idx == idx) {
1224 if (m_idx == n) {
1225 MasterIdx = (*p)->pos;
1226 }
1227 (*p)->set_state(jp, version);
1228 ports.push_back((*p));
1229 break;
1230 }
1231 }
1232 n++;
1233 jp.next(JsonParser::end_array);
1234 }
1235 jp.next(JsonParser::end_array);
1236 if (ctrl_ports.size() == ports.size()) ctrl_ports = ports;
1237 //assert(ctrl_ports.size() == ports.size());
1238 //ctrl_ports = ports;
1239 jp.next(JsonParser::end_array);
1240 jp.next(JsonParser::end_token);
1241 jp.close();
1242 } catch(JsonException& e) {
1243 gx_print_error(
1244 "ladspalist",
1245 ustring::compose(_("error parsing LADSPA plugin config file %1: %2"), fname, e.what()));
1246 return;
1247 }
1248 is.close();
1249 check_has_settings();
1250 }
1251
set_old()1252 void PluginDesc::set_old() {
1253 old = new PluginDesc(*this);
1254 old->ctrl_ports.clear();
1255 old->copy_ports(this);
1256 }
1257
1258
1259 /****************************************************************
1260 ** class LadspaPluginList
1261 */
1262
1263 static struct {
1264 unsigned long from, to;
1265 } ranges_1_based[] = {
1266 // swh
1267 {1181, 1440},
1268 {1605, 1605},
1269 {1881, 1922},
1270 // blop
1271 {1641, 1680},
1272 {2021, 2038},
1273 };
1274
LadspaPluginList()1275 LadspaPluginList::LadspaPluginList()
1276 : std::vector<PluginDesc*>(),
1277 world(lilv_world_new()),
1278 lv2_plugins(),
1279 lv2_AudioPort(lilv_new_uri(world, LV2_CORE__AudioPort)),
1280 lv2_ControlPort(lilv_new_uri(world, LV2_CORE__ControlPort)),
1281 lv2_InputPort(lilv_new_uri(world, LV2_CORE__InputPort)),
1282 lv2_OutputPort(lilv_new_uri(world, LV2_CORE__OutputPort)),
1283 lv2_connectionOptional(lilv_new_uri(world, LV2_CORE__connectionOptional)),
1284 lv2_AtomPort(lilv_new_uri(world, LV2_ATOM__AtomPort)) {
1285 LilvNode* false_val = lilv_new_bool(world, false);
1286 lilv_world_set_option(world,LILV_OPTION_DYN_MANIFEST, false_val);
1287 lilv_world_load_all(world);
1288 lv2_plugins = lilv_world_get_all_plugins(world);
1289 lilv_node_free(false_val);
1290 }
1291
in_1_based_range(unsigned long uid)1292 static bool in_1_based_range(unsigned long uid) {
1293 for (unsigned int i = 0; i < sizeof(ranges_1_based)/sizeof(ranges_1_based[0]); ++i) {
1294 if (uid >= ranges_1_based[i].from && uid <= ranges_1_based[i].to) {
1295 return true;
1296 }
1297 }
1298 return false;
1299 }
1300
1301 //static
set_instances(const char * uri,pluginmap & d,std::vector<ustring> & label,std::vector<unsigned long> & not_found,std::set<unsigned long> & seen)1302 void LadspaPluginList::set_instances(const char *uri, pluginmap& d, std::vector<ustring>& label,
1303 std::vector<unsigned long>& not_found, std::set<unsigned long>& seen) {
1304 lrdf_uris *uris = lrdf_get_instances(uri);
1305 if (uris) {
1306 for (unsigned int i = 0; i < uris->count; ++i) {
1307 const char *u = uris->items[i];
1308 unsigned long uid = lrdf_get_uid(u);
1309 std::string uid_key = make_key(uid);
1310 if (d.find(uid_key) == d.end()) {
1311 not_found.push_back(uid);
1312 seen.insert(uid);
1313 continue;
1314 }
1315 if (seen.find(uid) == seen.end()) {
1316 PluginDesc *pd = d[uid_key];
1317 pd->set_category(label);
1318 for (unsigned int n = 0; n < pd->ctrl_ports.size(); n++) {
1319 PortDesc *p = pd->ctrl_ports[n];
1320 lrdf_defaults *sval = lrdf_get_scale_values(uid, p->idx);
1321 if (sval) {
1322 for (unsigned int nn = 0; nn < sval[0].count; nn++) {
1323 lrdf_portvalue& t = sval[0].items[nn];
1324 p->factory.set_enumvalue(t.value, t.label);
1325 }
1326 lrdf_free_setting_values(sval);
1327 if (LADSPA_IS_HINT_INTEGER(p->hint_desc)) {
1328 p->factory.set_tp(tp_enum);
1329 }
1330 }
1331 }
1332 uri = lrdf_get_default_uri(uid);
1333 if (uri) {
1334 lrdf_defaults *sval = lrdf_get_setting_values(uri);
1335 if (sval) {
1336 for (unsigned int nn = 0; nn < sval[0].count; nn++) {
1337 lrdf_portvalue& t = sval[0].items[nn];
1338 int idx = t.pid;
1339 if (in_1_based_range(uid)) {
1340 idx -= 1;
1341 }
1342 pd->set_default(idx, t.value, t.label);
1343 }
1344 lrdf_free_setting_values(sval);
1345 }
1346 }
1347 }
1348 seen.insert(uid);
1349 }
1350 lrdf_free_uris(uris);
1351 }
1352 }
1353
1354 //static
descend(const char * uri,pluginmap & d,std::vector<unsigned long> & not_found,std::set<unsigned long> & seen,std::vector<ustring> & base)1355 void LadspaPluginList::descend(const char *uri, pluginmap& d,
1356 std::vector<unsigned long>& not_found,
1357 std::set<unsigned long>& seen,
1358 std::vector<ustring>& base) {
1359 lrdf_uris *uris = lrdf_get_subclasses(uri);
1360 if (uris) {
1361 for (unsigned int i = 0; i < uris->count; ++i) {
1362 const char *u = uris->items[i];
1363 base.push_back(lrdf_get_label(u));
1364 set_instances(u, d, base, not_found, seen);
1365 descend(u, d, not_found, seen, base);
1366 base.pop_back();
1367 }
1368 lrdf_free_uris(uris);
1369 }
1370 }
1371
get_preset_values(const char * port_symbol,void * user_data,const void * value,uint32_t size,uint32_t type)1372 void LadspaPluginList::get_preset_values(const char* port_symbol,
1373 void* user_data,
1374 const void* value,
1375 uint32_t size,
1376 uint32_t type) {
1377 LV2Preset* pdata = (LV2Preset*)user_data;
1378 for (unsigned int i=0; i< pdata->num_ports; i++) {
1379 const LilvPort* port = lilv_plugin_get_port_by_index(pdata->plugin, i);
1380 const char* sym = lilv_node_as_string(lilv_port_get_symbol(pdata->plugin,port));
1381 if (strcmp(sym, port_symbol) ==0) {
1382 float fvalue = *(const float*)value;
1383 Glib::ustring port_id = pdata->sname ;
1384 pdata->cline += " \"lv2_";
1385 pdata->cline += port_id ;
1386 pdata->cline += "." ;
1387 pdata->cline += gx_system::to_string(i) ;
1388 pdata->cline += "\": " ;
1389 pdata->cline += gx_system::to_string(fvalue);
1390 pdata->cline += "\n";
1391
1392 }
1393 }
1394 }
1395
set_preset_values(Glib::ustring port_symbol,LV2Preset * pdata,Glib::ustring value)1396 void LadspaPluginList::set_preset_values(Glib::ustring port_symbol,
1397 LV2Preset* pdata,
1398 Glib::ustring value) {
1399 for (unsigned int i=0; i< pdata->num_ports; i++) {
1400 const LilvPort* port = lilv_plugin_get_port_by_index(pdata->plugin, i);
1401 Glib::ustring sym = lilv_node_as_string(lilv_port_get_symbol(pdata->plugin,port));
1402 if (sym.compare(port_symbol) ==0) {
1403 Glib::ustring port_id = pdata->sname ;
1404 pdata->cline += " \"lv2_";
1405 pdata->cline += port_id ;
1406 pdata->cline += "." ;
1407 pdata->cline += gx_system::to_string(i) ;
1408 pdata->cline += "\": " ;
1409 pdata->cline += value;
1410 pdata->cline += "\n";
1411 break;
1412 }
1413 }
1414 }
1415
get_presets(LV2Preset * pdata)1416 void LadspaPluginList::get_presets(LV2Preset *pdata) {
1417 pdata->cline ="[\"gx_plugin_version\", 1,\n";
1418 LilvNodes* presets = lilv_plugin_get_related(pdata->plugin,
1419 lilv_new_uri(world,LV2_PRESETS__Preset));
1420 LILV_FOREACH(nodes, i, presets) {
1421 const LilvNode* preset = lilv_nodes_get(presets, i);
1422 lilv_world_load_resource(world, preset);
1423 LilvNodes* labels = lilv_world_find_nodes(
1424 world, preset, lilv_new_uri(world, LILV_NS_RDFS "label"), NULL);
1425 if (labels) {
1426 const LilvNode* label = lilv_nodes_get_first(labels);
1427 if (label) {
1428 Glib::ustring set = lilv_node_as_string(label);
1429 pdata->has_preset = true;
1430 LilvState* state = lilv_state_new_from_world(world, &gx_engine::LV2Features::getInstance().gx_urid_map, preset);
1431 pdata->cline +=" \"" + set + "\"" + " {\n";
1432
1433 Glib::ustring stt = lilv_state_to_string(world,&gx_engine::LV2Features::getInstance().gx_urid_map,&gx_engine::LV2Features::getInstance().gx_urid_unmap,state,"<>",NULL);
1434 std::istringstream stream(stt);
1435 std::string st;
1436 Glib::ustring symbol = "";
1437 Glib::ustring value = "";
1438 while (std::getline(stream, st)) {
1439 std::size_t found = st.find("lv2:symbol");
1440 if(found !=Glib::ustring::npos) {
1441 std::size_t found1 = st.find("\"",found)+1;
1442 std::size_t found2 = st.find("\"",found1);
1443 if(found2 !=Glib::ustring::npos) {
1444 symbol = st.substr(found1, (found2-found1));
1445 } else {
1446 continue;
1447 }
1448 }
1449 found = st.find("pset:value");
1450 if(found !=Glib::ustring::npos) {
1451 std::size_t found1 = st.find(" ",found)+1;
1452 if(found1 !=Glib::ustring::npos) {
1453 value = st.substr(found1);
1454 set_preset_values(symbol,pdata,value);
1455 } else {
1456 continue;
1457 }
1458 }
1459 }
1460 //lilv_state_emit_port_values(state, get_preset_values, pdata);
1461 lilv_state_free(state);
1462 pdata->cline += " },\n";
1463 }
1464 }
1465 lilv_nodes_free(labels);
1466 }
1467 lilv_nodes_free(presets);
1468 }
1469
feature_is_supported(const char * uri)1470 bool LadspaPluginList::feature_is_supported(const char* uri)
1471 {
1472 if (!strcmp(uri, "http://lv2plug.in/ns/lv2core#isLive")) {
1473 return true;
1474 }
1475 for (const LV2_Feature*const* f = gx_engine::LV2Features::getInstance().gx_features; *f; ++f) {
1476 if (!strcmp(uri, (*f)->URI)) {
1477 //fprintf(stderr, "Feature %s is supported\n", uri);
1478 return true;
1479 }
1480 }
1481 return false;
1482 }
add_plugin(const LilvPlugin * plugin,pluginmap & d,gx_system::CmdlineOptions & options)1483 void LadspaPluginList::add_plugin(const LilvPlugin* plugin, pluginmap& d, gx_system::CmdlineOptions& options) {
1484
1485 // check for requested features
1486 LilvNodes* requests = lilv_plugin_get_required_features(plugin);
1487 LILV_FOREACH(nodes, f, requests) {
1488 const char* uri = lilv_node_as_uri(lilv_nodes_get(requests, f));
1489 if (!feature_is_supported(uri)) {
1490 //fprintf(stderr, "Plugin %s \n", lilv_node_as_string(lilv_plugin_get_uri(plugin)));
1491 //fprintf(stderr, "Feature %s is not supported\n", uri);
1492 lilv_nodes_free(requests);
1493 return;
1494 }
1495 }
1496 lilv_nodes_free(requests);
1497
1498 int n_in = 0;
1499 int n_out = 0;
1500 unsigned int ena_port = 0;
1501 bool ena = false;
1502 std::vector<PortDesc*> ctrl_ports;
1503 int pos = 0;
1504 unsigned int num_ports = lilv_plugin_get_num_ports(plugin);
1505
1506 LilvNode* is_ena = lilv_new_uri(world, LV2_CORE__enabled);
1507 const LilvPort* enabled_port = lilv_plugin_get_port_by_designation(plugin, lv2_ControlPort, is_ena);
1508 if (enabled_port) {
1509 ena_port = lilv_port_get_index(plugin, enabled_port);
1510 ena = true;
1511 }
1512 lilv_node_free(is_ena);
1513
1514 for (unsigned int n = 0; n < num_ports; n++) {
1515 const LilvPort* port = lilv_plugin_get_port_by_index(plugin, n);
1516 if (lilv_port_is_a(plugin, port, lv2_AudioPort)) {
1517 if (lilv_port_is_a(plugin, port, lv2_InputPort)) {
1518 n_in += 1;
1519 } else {
1520 n_out += 1;
1521 }
1522 } else if (lilv_port_is_a(plugin, port, lv2_ControlPort)) {
1523 LADSPA_PortRangeHint hint;
1524 hint.HintDescriptor = 0;
1525 hint.LowerBound = hint.UpperBound = 0;
1526 LilvNode *pdflt, *pmin, *pmax;
1527 lilv_port_get_range(plugin, port, &pdflt, &pmin, &pmax);
1528 if (pmin) {
1529 hint.LowerBound = lilv_node_as_float(pmin);
1530 hint.HintDescriptor |= LADSPA_HINT_BOUNDED_BELOW;
1531 lilv_node_free(pmin);
1532 }
1533 if (pmax) {
1534 hint.UpperBound = lilv_node_as_float(pmax);
1535 hint.HintDescriptor |= LADSPA_HINT_BOUNDED_ABOVE;
1536 lilv_node_free(pmax);
1537 }
1538 LilvNode* nm = lilv_port_get_name(plugin, port);
1539 PortDesc *pdesc = new PortDesc(n, pos, lilv_port_is_a(plugin, port, lv2_OutputPort), lilv_node_as_string(nm), hint);
1540 lilv_node_free(nm);
1541 if (pdflt) {
1542 pdesc->factory.set_dflt(lilv_node_as_float(pdflt));
1543 lilv_node_free(pdflt);
1544 }
1545 LilvNode* is_int = lilv_new_uri(world, LV2_CORE__integer);
1546 if (lilv_port_has_property(plugin, port, is_int)) {
1547 pdesc->factory.set_tp(tp_int);
1548 }
1549 lilv_node_free(is_int);
1550 LilvNode* is_tog = lilv_new_uri(world, LV2_CORE__toggled);
1551 if (lilv_port_has_property(plugin, port, is_tog)) {
1552 pdesc->factory.set_tp(tp_toggle);
1553 }
1554 lilv_node_free(is_tog);
1555 LilvScalePoints* sp = lilv_port_get_scale_points(plugin, port);
1556 int num_sp = lilv_scale_points_size(sp);
1557 if (num_sp > 0) {
1558 for (LilvIter* it = lilv_scale_points_begin(sp);
1559 !lilv_scale_points_is_end(sp, it);
1560 it = lilv_scale_points_next(sp, it)) {
1561 const LilvScalePoint* p = lilv_scale_points_get(sp, it);
1562 pdesc->factory.set_enumvalue(
1563 lilv_node_as_float(lilv_scale_point_get_value(p)),
1564 lilv_node_as_string(lilv_scale_point_get_label(p)));
1565 }
1566 pdesc->factory.set_tp(tp_enum);
1567 }
1568 lilv_scale_points_free(sp);
1569
1570 if (ena) {
1571 if (n == ena_port) {
1572 pdesc->factory.set_tp(tp_enabled);
1573 }
1574 }
1575
1576 ctrl_ports.push_back(pdesc);
1577 pos += 1;
1578 #if 0
1579 } else if (lilv_port_is_a(plugin, port, lv2_AtomPort)) {
1580 LADSPA_PortRangeHint hint;
1581 hint.HintDescriptor = 0;
1582 hint.LowerBound = hint.UpperBound = 0;
1583 LilvNode* nm = lilv_port_get_name(plugin, port);
1584 PortDesc *pdesc = new PortDesc(n, pos, lilv_port_is_a(plugin, port, lv2_OutputPort), lilv_node_as_string(nm), hint);
1585 lilv_node_free(nm);
1586 pdesc->factory.set_tp(tp_atom);
1587 ctrl_ports.push_back(pdesc);
1588 pos += 1;
1589 // NOT supported
1590 #endif
1591 } else {
1592 if (!lilv_port_has_property(plugin, port, lv2_connectionOptional)) {
1593 n_out = 0; // fail
1594 break;
1595 }
1596 }
1597 }
1598 int tp;
1599 if (n_in == 1 && n_out == 1) {
1600 tp = 0;
1601 } else if (n_in == 2 && n_out == 2) {
1602 tp = 1;
1603 } else {
1604 for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
1605 delete *i;
1606 }
1607 return;
1608 }
1609
1610 // check if plugin instantiate
1611 // LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000, 0);
1612 // if (!instance) {
1613 // return;
1614 // }
1615 // lilv_instance_free(instance);
1616
1617 PluginDesc* p = d[lilv_node_as_string(lilv_plugin_get_uri(plugin))] = new PluginDesc(world, plugin, tp, ctrl_ports);
1618 pdata.has_preset = false;
1619 if (options.reload_lv2_presets) {
1620 if (p->path.size() != 0) {
1621 pdata.sname = gx_system::encode_filename(p->path);
1622 pdata.ctrl_ports = ctrl_ports;
1623 pdata.num_ports = num_ports;
1624 pdata.plugin = const_cast<LilvPlugin*>(plugin);
1625 get_presets(&pdata);
1626 }
1627 }
1628
1629 }
1630
lv2_load(pluginmap & d,gx_system::CmdlineOptions & options)1631 void LadspaPluginList::lv2_load(pluginmap& d, gx_system::CmdlineOptions& options) {
1632 for (LilvIter* it = lilv_plugins_begin(lv2_plugins);
1633 !lilv_plugins_is_end(lv2_plugins, it);
1634 it = lilv_plugins_next(lv2_plugins, it)) {
1635 add_plugin(lilv_plugins_get(lv2_plugins, it), d, options);
1636 if (options.reload_lv2_presets) {
1637 if (pdata.has_preset && pdata.cline.size() != 0) {
1638 pdata.cline.replace(pdata.cline.end()-2,pdata.cline.end()-1,"");
1639 pdata.cline += "]\n";
1640 std::string pfile = options.get_lv2_preset_dir();
1641 pfile += "lv2_";
1642 pfile += pdata.sname;
1643 ofstream os (pfile.c_str());
1644 os << pdata.cline;
1645 os.close();
1646 }
1647 pdata.has_preset = false;
1648 }
1649 }
1650 options.reload_lv2_presets = false;
1651 }
1652
cmp_plugins(const PluginDesc * a,const PluginDesc * b)1653 static bool cmp_plugins(const PluginDesc *a, const PluginDesc *b) {
1654 return ustring(a->Name) < ustring(b->Name);
1655 }
1656
load(gx_system::CmdlineOptions & options,std::vector<std::string> & old_not_found)1657 void LadspaPluginList::load(gx_system::CmdlineOptions& options, std::vector<std::string>& old_not_found) {
1658 gx_system::PathList pl("LADSPA_PATH");
1659 if (!pl.size()) {
1660 pl.add("/usr/lib/ladspa");
1661 pl.add("/usr/local/lib/ladspa");
1662 pl.add("/usr/lib64/ladspa");
1663 pl.add("/usr/local/lib64/ladspa");
1664 }
1665 pluginmap d;
1666 for (gx_system::PathList::iterator it = pl.begin(); it != pl.end(); ++it) {
1667 Glib::RefPtr<Gio::File> file = *it;
1668 if (!file->query_exists()) {
1669 continue;
1670 }
1671 Glib::RefPtr<Gio::FileEnumerator> child_enumeration =
1672 file->enumerate_children(G_FILE_ATTRIBUTE_STANDARD_NAME
1673 "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
1674 "," G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
1675 Glib::RefPtr<Gio::FileInfo> file_info;
1676
1677 while ((file_info = child_enumeration->next_file())) {
1678 if (file_info->get_attribute_string(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE) == "application/x-sharedlib") {
1679 std::string nm = file_info->get_attribute_byte_string(G_FILE_ATTRIBUTE_STANDARD_NAME);
1680 if (lib_is_blacklisted(nm)) {
1681 continue;
1682 }
1683 //printf("opening %s/%s\n", file->get_path().c_str(), nm.c_str());
1684 load_defs(Glib::build_filename(file->get_path(), nm), d);
1685 }
1686 }
1687 }
1688 gx_system::PathList rpl("LADSPA_RDF_PATH");
1689 if (!rpl.size()) {
1690 rpl.add("/usr/share/ladspa/rdf");
1691 rpl.add("/usr/local/share/ladspa/rdf");
1692 }
1693 lrdf_init();
1694 for (gx_system::PathList::iterator it = rpl.begin(); it != rpl.end(); ++it) {
1695 Glib::RefPtr<Gio::File> file = *it;
1696 if (!file->query_exists()) {
1697 continue;
1698 }
1699 Glib::RefPtr<Gio::FileEnumerator> child_enumeration =
1700 file->enumerate_children(G_FILE_ATTRIBUTE_STANDARD_NAME
1701 "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
1702 "," G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
1703 Glib::RefPtr<Gio::FileInfo> file_info;
1704
1705 while ((file_info = child_enumeration->next_file())) {
1706 //if not f.endswith((".rdf",".rdfs")):
1707 if (file_info->get_attribute_string(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE) == "application/rdf+xml") {
1708 std::string nm = file_info->get_attribute_byte_string(G_FILE_ATTRIBUTE_STANDARD_NAME);
1709 if (lib_is_blacklisted(nm)) {
1710 continue;
1711 }
1712 Glib::ustring path = "file://"+Glib::build_filename(file->get_path(), nm);
1713 lrdf_read_file(path.c_str());
1714 }
1715 }
1716 }
1717 std::vector<unsigned long> not_found;
1718 std::set<unsigned long> seen;
1719 std::vector<ustring> base;
1720 locale_t loc = newlocale(LC_ALL, "C", 0);
1721 uselocale(loc);
1722 descend(LADSPA_BASE "Plugin", d, not_found, seen, base);
1723 uselocale(LC_GLOBAL_LOCALE);
1724 freelocale(loc);
1725 lrdf_cleanup();
1726
1727 lv2_load(d, options);
1728
1729 ifstream is(options.get_ladspa_config_filename().c_str());
1730 if (!is.fail()) {
1731 try {
1732 JsonParser jp(&is);
1733 jp.next(JsonParser::begin_array);
1734 while (jp.peek() == JsonParser::begin_array) {
1735 jp.next(JsonParser::begin_array);
1736 jp.next(JsonParser::value_string); // path
1737 std::string key = jp.current_value();
1738 jp.next(JsonParser::value_number); // index
1739 int idx = jp.current_value_int();
1740 jp.next(JsonParser::value_number); // UniqueID
1741 if (idx >= 0) {
1742 unsigned long uid = jp.current_value_uint();
1743 key = make_key(uid);
1744 }
1745 if (d.find(key) == d.end()) {
1746 old_not_found.push_back(key);
1747 } else {
1748 d[key]->set_active(true);
1749 d[key]->active_set = true;
1750 }
1751 jp.next(JsonParser::value_string); // Label
1752 jp.next(JsonParser::end_array);
1753 }
1754 jp.close();
1755 } catch(JsonException& e) {
1756 gx_print_error(
1757 "ladspalist", ustring::compose(
1758 _("error loading ladspa plugin selection data from file %1"),
1759 options.get_ladspa_config_filename()));
1760 }
1761 is.close();
1762 }
1763 for (pluginmap::iterator v = d.begin(); v != d.end(); ++v) {
1764 v->second->fixup();
1765 std::string s;
1766 if (v->second->is_lv2) {
1767 s = gx_system::encode_filename(v->second->path) + ".js";
1768 } else {
1769 s = gx_engine::LadspaLoader::get_ladspa_filename(v->first);
1770 }
1771 std::string fname = options.get_plugin_filepath(s);
1772 if (access(fname.c_str(), F_OK) != 0) {
1773 fname = options.get_factory_filepath(s);
1774 if (access(fname.c_str(), F_OK) != 0) {
1775 fname = "";
1776 }
1777 }
1778 if (!fname.empty()) {
1779 v->second->set_state(fname);
1780 }
1781 }
1782 for (pluginmap::iterator i = d.begin(); i != d.end(); ++i) {
1783 push_back(i->second);
1784 }
1785 std::sort(begin(), end(), cmp_plugins);
1786 }
1787
save(gx_system::CmdlineOptions & options)1788 void LadspaPluginList::save(gx_system::CmdlineOptions& options) {
1789 std::string fname = options.get_ladspa_config_filename();
1790 std::string tfname = fname + ".tmp";
1791 ofstream tfile(tfname.c_str());
1792 JsonWriter jw(&tfile);
1793 jw.begin_array(true);
1794 for (std::vector<PluginDesc*>::iterator p = begin(); p != end(); ++p) {
1795 if ((*p)->active) {
1796 (*p)->output_entry(jw);
1797 }
1798 }
1799 jw.end_array(true);
1800 jw.close();
1801 tfile.close();
1802 std::vector<std::pair<std::string,std::string> > fl;
1803 for (std::vector<PluginDesc*>::iterator p = begin(); p != end(); ++p) {
1804 std::string sname = ((*p)->is_lv2 ?
1805 gx_system::encode_filename((*p)->path) + ".js" :
1806 gx_engine::LadspaLoader::get_ladspa_filename((*p)->UniqueID));
1807 std::string cname = options.get_plugin_filepath(sname);
1808 if ((*p)->active || (*p)->has_settings) {
1809 std::string tcname = cname + ".tmp";
1810 ofstream tcfile(tcname.c_str());
1811 JsonWriter jw2(&tcfile);
1812 (*p)->output(jw2);
1813 jw2.close();
1814 tcfile.close();
1815 fl.push_back(std::pair<std::string,std::string>(tcname, cname));
1816 } else {
1817 fl.push_back(std::pair<std::string,std::string>("", cname));
1818 }
1819 }
1820 if (rename(tfname.c_str(), fname.c_str()) != 0) {
1821 char buf[100];
1822 strerror_r(errno, buf, sizeof(buf));
1823 gx_print_error(
1824 "ladspalist",ustring::compose(_("error renaming LADSPA config file '%1': %2"), fname, buf));
1825 return;
1826 }
1827 for (std::vector<std::pair<std::string,std::string> >::iterator i = fl.begin(); i != fl.end(); ++i) {
1828 if (i->first.empty()) {
1829 unlink(i->second.c_str());
1830 } else {
1831 if (rename(i->first.c_str(), i->second.c_str()) != 0) {
1832 char buf[100];
1833 strerror_r(errno, buf, sizeof(buf));
1834 gx_print_error(
1835 "ladspalist",
1836 ustring::compose("error renaming %1 to %2: %3\n", i->first, i->second, buf));
1837 }
1838 }
1839 }
1840 }
1841
1842
readJSON(gx_system::JsonParser & jp)1843 void LadspaPluginList::readJSON(gx_system::JsonParser& jp) {
1844 jp.next(gx_system::JsonParser::begin_array);
1845 while (jp.peek() != gx_system::JsonParser::end_array) {
1846 push_back(new ladspa::PluginDesc(jp));
1847 }
1848 jp.next(gx_system::JsonParser::end_array);
1849 }
1850
writeJSON(gx_system::JsonWriter & jw)1851 void LadspaPluginList::writeJSON(gx_system::JsonWriter& jw) {
1852 jw.begin_array();
1853 for (iterator i = begin(); i != end(); ++i) {
1854 (*i)->serializeJSON(jw);
1855 }
1856 jw.end_array();
1857 }
1858
~LadspaPluginList()1859 LadspaPluginList::~LadspaPluginList() {
1860 for (iterator i = begin(); i != end(); ++i) {
1861 delete *i;
1862 }
1863 lilv_node_free(lv2_AudioPort);
1864 lilv_node_free(lv2_ControlPort);
1865 lilv_node_free(lv2_InputPort);
1866 lilv_node_free(lv2_OutputPort);
1867 lilv_node_free(lv2_connectionOptional);
1868 lilv_node_free(lv2_AtomPort);
1869 lilv_world_free(world);
1870 }
1871
1872 } // namespace ladspa
1873