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