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