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