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 std::abs(v1 - v2) <= 1e-5 * std::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), stereo_to_mono(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), stereo_to_mono(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  stereo_to_mono(),
774  old(0) {
776  while (jp.peek() != gx_system::JsonParser::end_object) {
778  if (jp.read_kv("UniqueID", UniqueID) ||
779  jp.read_kv("Label", Label) ||
780  jp.read_kv("Name", Name) ||
781  jp.read_kv("shortname", shortname) ||
782  jp.read_kv("Maker", Maker) ||
783  jp.read_kv("MasterIdx", MasterIdx) ||
784  jp.read_kv("MasterLabel", MasterLabel) ||
785  jp.read_kv("tp", tp) ||
786  jp.read_kv("path", path) ||
787  jp.read_kv("index", index) ||
788  jp.read_kv("category", category) ||
789  jp.read_kv("deduced_category", deduced_category) ||
790  jp.read_kv("quirks", quirks) ||
791  jp.read_kv("quirks_default", quirks_default) ||
792  jp.read_kv("is_lv2", is_lv2) ||
793  jp.read_kv("ladspa_category", ladspa_category) ||
794  jp.read_kv("active", active) ||
795  jp.read_kv("active_set", active_set) ||
796  jp.read_kv("has_settings", has_settings) ||
797  jp.read_kv("add_wet_dry", add_wet_dry) ||
798  jp.read_kv("stereo_to_mono", stereo_to_mono)) {
799  } else if (jp.current_value() == "old") {
800  old = new PluginDesc(jp);
801  } else if (jp.current_value() == "ctrl_ports") {
803  while (jp.peek() != gx_system::JsonParser::end_array) {
804  ctrl_ports.push_back(new PortDesc(jp));
805  }
807  } else {
809  "ladspa::PluginDesc", Glib::ustring::compose("unknown key: %1", jp.current_value()));
810  jp.skip_object();
811  }
812  }
814 }
815 
816 void PluginDesc::serializeJSON(gx_system::JsonWriter& jw) {
817  jw.begin_object();
818  jw.write_kv("UniqueID", static_cast<unsigned int>(UniqueID));
819  jw.write_kv("Label", Label);
820  jw.write_kv("Name", Name);
821  jw.write_kv("shortname", shortname);
822  jw.write_kv("Maker", Maker);
823  jw.write_kv("MasterIdx", MasterIdx);
824  jw.write_kv("MasterLabel", MasterLabel);
825  jw.write_kv("tp", tp);
826  jw.write_kv("path", path);
827  jw.write_kv("index", index);
828  jw.write_kv("category", category);
829  jw.write_kv("deduced_category", deduced_category);
830  jw.write_kv("quirks", quirks);
831  jw.write_kv("quirks_default", quirks_default);
832  jw.write_kv("is_lv2", is_lv2);
833  jw.write_kv("ladspa_category", ladspa_category);
834  jw.write_kv("active", active);
835  jw.write_kv("active_set", active_set);
836  jw.write_kv("has_settings", has_settings);
837  jw.write_kv("add_wet_dry", add_wet_dry);
838  jw.write_kv("stereo_to_mono", stereo_to_mono);
839  if (old) {
840  jw.write_key("old");
841  old->serializeJSON(jw);
842  }
843  jw.write_key("ctrl_ports");
844  jw.begin_array();
845  for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
846  (*i)->serializeJSON(jw);
847  }
848  jw.end_array();
849  jw.end_object();
850 }
851 
853  int flag = 0;
854  for (int i = 0; quirk_list[i].flag; i++) {
855  for (int j = 0; quirk_list[i].ids[j]; j++) {
856  if (UniqueID == quirk_list[i].ids[j]) {
857  flag |= quirk_list[i].flag;
858  }
859  }
860  }
861  return flag;
862 }
863 
864 bool cmp_ctrl_ports(const PortDesc *a, const PortDesc *b) {
865  return a->pos < b->pos;
866 }
867 
869  shortname = Name;
870  MasterIdx = -1;
871  MasterLabel = "";
872  add_wet_dry = 0;
873  category = deduced_category;
874  quirks = quirks_default;
875  has_settings = false;
876  std::sort(ctrl_ports.begin(), ctrl_ports.end(), cmp_ctrl_ports);
877  for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
878  (*p)->reset();
879  }
880 }
881 
883  assert(ctrl_ports.size() == 0);
884  for (std::vector<PortDesc*>::iterator i = p->ctrl_ports.begin(); i != p->ctrl_ports.end(); ++i) {
885  ctrl_ports.push_back(new PortDesc(**i));
886  }
887 }
888 
889 //static
890 void LadspaPluginList::add_plugin(const LADSPA_Descriptor& desc, pluginmap& d, const std::string& path, int index) {
891  for (unsigned int j = 0; j < sizeof(blacklist)/sizeof(blacklist[0]); j++) {
892  if (desc.UniqueID == blacklist[j]) {
893  return;
894  }
895  }
896 #ifdef HARD_RT_ONLY
897  if (!LADSPA_IS_HARD_RT_CAPABLE(desc.Properties)) {
898  return;
899  }
900 #endif
901  int n_in = 0;
902  int n_out = 0;
903  std::vector<PortDesc*> ctrl_ports;
904  int pos = 0;
905  for (unsigned int n = 0; n < desc.PortCount; n++) {
906  LADSPA_PortDescriptor pd = desc.PortDescriptors[n];
907  if (LADSPA_IS_PORT_AUDIO(pd)) {
908  if (LADSPA_IS_PORT_INPUT(pd)) {
909  n_in += 1;
910  } else {
911  n_out += 1;
912  }
913  } else {
914  ctrl_ports.push_back(new PortDesc(n, pos, LADSPA_IS_PORT_OUTPUT(pd), desc.PortNames[n], desc.PortRangeHints[n]));
915  pos += 1;
916  }
917  }
918  int tp;
919  if (n_in == 1 && n_out == 1) {
920  tp = 0;
921  } else if (n_in == 2 && n_out == 2) {
922  tp = 1;
923  } else {
924  for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
925  delete *i;
926  }
927  return;
928  }
929  d[make_key(desc.UniqueID)] = new PluginDesc(desc, tp, ctrl_ports, path, index);
930 }
931 
932 //static
933 void LadspaPluginList::load_defs(const std::string& path, pluginmap& d) {
934  void *handle;
935  handle = dlopen(path.c_str(), RTLD_LOCAL|RTLD_NOW);
936  if (!handle) {
938  "ladspalist",
939  ustring::compose(_("Cannot open plugin: %1\n"), dlerror()));
940  return;
941  }
942  LADSPA_Descriptor_Function ladspa_descriptor = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
943  const char *dlsym_error = dlerror();
944  if (dlsym_error) {
945  gx_print_warning("ladspalist", dlsym_error);
946  dlclose(handle);
947  handle = 0;
948  return;
949  }
950  int i = 0;
951  while (true) {
952  const LADSPA_Descriptor *desc = ladspa_descriptor(i);
953  if (!desc) {
954  break;
955  }
956  add_plugin(*desc, d, path, i);
957  i += 1;
958  }
959  dlclose(handle);
960 }
961 
963  if (!old) {
964  return false;
965  }
966  if (UniqueID != old->UniqueID) {
967  return true;
968  }
969  if (Label != old->Label) {
970  return true;
971  }
972  if (Name != old->Name) {
973  return true;
974  }
975  if (shortname != old->shortname) {
976  return true;
977  }
978  if (Maker != old->Maker) {
979  return true;
980  }
981  if (MasterIdx != old->MasterIdx) {
982  return true;
983  }
984  if (MasterIdx > -1 && MasterLabel != old->MasterLabel) {
985  return true;
986  }
987  if (add_wet_dry != old->add_wet_dry) {
988  return true;
989  }
990  if (stereo_to_mono != old->stereo_to_mono) {
991  return true;
992  }
993  if (tp != old->tp) {
994  return true;
995  }
996  if (path != old->path) {
997  return true;
998  }
999  if (index != old->index) {
1000  return true;
1001  }
1002  if (category != old->category) {
1003  return true;
1004  }
1005  if (deduced_category != old->deduced_category) {
1006  return true;
1007  }
1008  if (quirks != old->quirks) {
1009  return true;
1010  }
1011  if (quirks_default != old->quirks_default) {
1012  return true;
1013  }
1014  if (ladspa_category != old->ladspa_category) {
1015  return true;
1016  }
1017  for (unsigned int i = 0; i < ctrl_ports.size(); ++i) {
1018  if (ctrl_ports[i]->check_changed(*old->ctrl_ports[i])) {
1019  return true;
1020  }
1021  }
1022  return false;
1023 }
1024 
1026  if (shortname != Name) {
1027  return true;
1028  }
1029  if (category != deduced_category) {
1030  return true;
1031  }
1032  if (quirks != quirks_default) {
1033  return true;
1034  }
1035  if (MasterIdx != -1) {
1036  return true;
1037  }
1038  for (int i = 0; i < static_cast<int>(ctrl_ports.size()); ++i) {
1039  if (i != ctrl_ports[i]->get_pos()) {
1040  return true;
1041  }
1042  if (ctrl_ports[i]->has_settings()) {
1043  return true;
1044  }
1045  }
1046  return false;
1047 }
1048 
1050  has_settings = _i_check_has_settings();
1051 }
1052 
1054  if (v == active) {
1055  return 0;
1056  }
1057  active = v;
1058  if (v == active_set) {
1059  return -1;
1060  }
1061  return 1;
1062 }
1063 
1065  if (v) {
1066  add_wet_dry = 1;
1067  } else {
1068  add_wet_dry = 0;
1069  }
1070 }
1071 
1073  if (v) {
1074  stereo_to_mono = 1;
1075  } else {
1076  stereo_to_mono = 0;
1077  }
1078 }
1079 
1081  int i = 0;
1082  for (unsigned int n = 0; n < ctrl_ports.size(); ++n) {
1083  bool newrow = false;
1084  if (ctrl_ports[n]->get_tp() != tp_none) {
1085  newrow = (i % 6 == 0 && i != 0);
1086  i += 1;
1087  }
1088  ctrl_ports[n]->fixup(newrow);
1089  }
1090 }
1091 
1092 void PluginDesc::set_category(const std::vector<ustring>& s) {
1093  bool found = false;
1094  ustring t = "";
1095  for (std::vector<ustring>::const_iterator i = s.begin(); i != s.end(); ++i) {
1096  if (!t.empty()) {
1097  t += "/";
1098  }
1099  t += *i;
1100  if (!found) {
1101  for (const char *(*p)[2] = cat_subst; (*p)[0]; ++p) {
1102  if (*i == (*p)[0]) {
1103  category = deduced_category = (*p)[1];
1104  found = true;
1105  break;
1106  }
1107  }
1108  }
1109  }
1110  ladspa_category = t;
1111 }
1112 
1113 void PluginDesc::set_default(int idx, float value, const ustring& label) {
1114  for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1115  if ((*p)->idx == idx) {
1116  (*p)->set_default(value, label);
1117  return;
1118  }
1119  }
1120 }
1121 
1123  ustring s = shortname;
1124  if (s == Name) {
1125  s = "";
1126  }
1127  int idx = -1;
1128  ustring sm = "";
1129  if (MasterIdx >= 0) {
1130  for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1131  ++idx;
1132  if ((*p)->pos == MasterIdx) {
1133  sm = MasterLabel;
1134  if (sm == (*p)->get_name()) {
1135  sm = "";
1136  }
1137  break;
1138  }
1139  }
1140  }
1141  jw.begin_array();
1142  jw.write(3); // version
1143  jw.write(s);
1144  jw.write(category);
1145  jw.write(idx);
1146  jw.write(sm);
1147  jw.write(quirks | (is_lv2 ? gx_engine::is_lv2 : 0));
1148  jw.write(add_wet_dry);
1149  jw.write(stereo_to_mono);
1150  jw.begin_array(true);
1151  for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1152  (*p)->output(jw);
1153  }
1154  jw.end_array(true);
1155  jw.end_array(true);
1156 }
1157 
1159  jw.begin_array();
1160  jw.write(path);
1161  if (is_lv2) {
1162  jw.write(-1);
1163  } else {
1164  jw.write(index);
1165  }
1166  jw.write(uint(UniqueID));
1167  jw.write(Label);
1168  jw.end_array(true);
1169 }
1170 
1171 void PluginDesc::set_state(const ustring& fname) {
1172  ifstream is(fname.c_str());
1173  if (is.fail()) {
1174  gx_print_error("ladspalist", ustring::compose(_("can't open %1"), fname));
1175  return;
1176  }
1177  try {
1178  JsonParser jp(&is);
1179  jp.next(JsonParser::begin_array);
1180  jp.next(JsonParser::value_number);
1181  int version = jp.current_value_int();
1182  jp.next(JsonParser::value_string);
1183  shortname = jp.current_value();
1184  if (shortname.empty()) {
1185  shortname = Name;
1186  }
1187  jp.next(JsonParser::value_string);
1188  category = jp.current_value();
1189  jp.next(JsonParser::value_number);
1190  MasterIdx = jp.current_value_int();
1191  jp.next(JsonParser::value_string);
1192  MasterLabel = jp.current_value();
1193  jp.next(JsonParser::value_number);
1194  quirks = jp.current_value_int();
1195  if (quirks & gx_engine::is_lv2) {
1196  quirks &= ~gx_engine::is_lv2;
1197  is_lv2 = true;
1198  }
1199  jp.next(JsonParser::value_number);
1200  add_wet_dry = jp.current_value_int();
1201  if (jp.peek() == JsonParser::value_number) {
1202  jp.next(JsonParser::value_number);
1203  stereo_to_mono = jp.current_value_int();
1204  }
1205  std::vector<PortDesc*> ports;
1206  jp.next(JsonParser::begin_array);
1207  int n = 0;
1208  int m_idx = MasterIdx;
1209  while (jp.peek() != JsonParser::end_array) {
1210  jp.next(JsonParser::begin_array);
1211  jp.next(JsonParser::value_number);
1212  int idx = jp.current_value_int();
1213  for (std::vector<PortDesc*>::iterator p = ctrl_ports.begin(); p != ctrl_ports.end(); ++p) {
1214  if ((*p)->idx == idx) {
1215  if (m_idx == n) {
1216  MasterIdx = (*p)->pos;
1217  }
1218  (*p)->set_state(jp, version);
1219  ports.push_back((*p));
1220  break;
1221  }
1222  }
1223  n++;
1224  jp.next(JsonParser::end_array);
1225  }
1226  jp.next(JsonParser::end_array);
1227  assert(ctrl_ports.size() == ports.size());
1228  ctrl_ports = ports;
1229  jp.next(JsonParser::end_array);
1230  jp.next(JsonParser::end_token);
1231  jp.close();
1232  } catch(JsonException& e) {
1234  "ladspalist",
1235  ustring::compose(_("error parsing LADSPA plugin config file %1: %2"), fname, e.what()));
1236  return;
1237  }
1238  is.close();
1239  check_has_settings();
1240 }
1241 
1243  old = new PluginDesc(*this);
1244  old->ctrl_ports.clear();
1245  old->copy_ports(this);
1246 }
1247 
1248 /****************************************************************
1249  ** class LadspaPluginList
1250  */
1251 
1252 static struct {
1253  unsigned long from, to;
1254 } ranges_1_based[] = {
1255  // swh
1256  {1181, 1440},
1257  {1605, 1605},
1258  {1881, 1922},
1259  // blop
1260  {1641, 1680},
1261  {2021, 2038},
1262 };
1263 
1265  : std::vector<PluginDesc*>(),
1266  world(lilv_world_new()),
1267  lv2_plugins(),
1268  lv2_AudioPort(lilv_new_uri(world, LV2_CORE__AudioPort)),
1269  lv2_ControlPort(lilv_new_uri(world, LV2_CORE__ControlPort)),
1270  lv2_InputPort(lilv_new_uri(world, LV2_CORE__InputPort)),
1271  lv2_OutputPort(lilv_new_uri(world, LV2_CORE__OutputPort)),
1272  lv2_connectionOptional(lilv_new_uri(world, LV2_CORE__connectionOptional)) {
1273  LilvNode* false_val = lilv_new_bool(world, false);
1274  lilv_world_set_option(world,LILV_OPTION_DYN_MANIFEST, false_val);
1275  lilv_world_load_all(world);
1276  lv2_plugins = lilv_world_get_all_plugins(world);
1277  lilv_node_free(false_val);
1278 }
1279 
1280 static bool in_1_based_range(unsigned long uid) {
1281  for (unsigned int i = 0; i < sizeof(ranges_1_based)/sizeof(ranges_1_based[0]); ++i) {
1282  if (uid >= ranges_1_based[i].from && uid <= ranges_1_based[i].to) {
1283  return true;
1284  }
1285  }
1286  return false;
1287 }
1288 
1289 //static
1290 void LadspaPluginList::set_instances(const char *uri, pluginmap& d, std::vector<ustring>& label,
1291  std::vector<unsigned long>& not_found, std::set<unsigned long>& seen) {
1292  lrdf_uris *uris = lrdf_get_instances(uri);
1293  if (uris) {
1294  for (unsigned int i = 0; i < uris->count; ++i) {
1295  const char *u = uris->items[i];
1296  unsigned long uid = lrdf_get_uid(u);
1297  std::string uid_key = make_key(uid);
1298  if (d.find(uid_key) == d.end()) {
1299  not_found.push_back(uid);
1300  seen.insert(uid);
1301  continue;
1302  }
1303  if (seen.find(uid) == seen.end()) {
1304  PluginDesc *pd = d[uid_key];
1305  pd->set_category(label);
1306  for (unsigned int n = 0; n < pd->ctrl_ports.size(); n++) {
1307  PortDesc *p = pd->ctrl_ports[n];
1308  lrdf_defaults *sval = lrdf_get_scale_values(uid, p->idx);
1309  if (sval) {
1310  for (unsigned int nn = 0; nn < sval[0].count; nn++) {
1311  lrdf_portvalue& t = sval[0].items[nn];
1312  p->factory.set_enumvalue(t.value, t.label);
1313  }
1314  lrdf_free_setting_values(sval);
1315  if (LADSPA_IS_HINT_INTEGER(p->hint_desc)) {
1316  p->factory.set_tp(tp_enum);
1317  }
1318  }
1319  }
1320  uri = lrdf_get_default_uri(uid);
1321  if (uri) {
1322  lrdf_defaults *sval = lrdf_get_setting_values(uri);
1323  if (sval) {
1324  for (unsigned int nn = 0; nn < sval[0].count; nn++) {
1325  lrdf_portvalue& t = sval[0].items[nn];
1326  int idx = t.pid;
1327  if (in_1_based_range(uid)) {
1328  idx -= 1;
1329  }
1330  pd->set_default(idx, t.value, t.label);
1331  }
1332  lrdf_free_setting_values(sval);
1333  }
1334  }
1335  }
1336  seen.insert(uid);
1337  }
1338  lrdf_free_uris(uris);
1339  }
1340 }
1341 
1342 //static
1343 void LadspaPluginList::descend(const char *uri, pluginmap& d,
1344  std::vector<unsigned long>& not_found,
1345  std::set<unsigned long>& seen,
1346  std::vector<ustring>& base) {
1347  lrdf_uris *uris = lrdf_get_subclasses(uri);
1348  if (uris) {
1349  for (unsigned int i = 0; i < uris->count; ++i) {
1350  const char *u = uris->items[i];
1351  base.push_back(lrdf_get_label(u));
1352  set_instances(u, d, base, not_found, seen);
1353  descend(u, d, not_found, seen, base);
1354  base.pop_back();
1355  }
1356  lrdf_free_uris(uris);
1357  }
1358 }
1359 
1360 
1361 char** LadspaPluginList::uris = NULL;
1362 size_t LadspaPluginList::n_uris = 0;
1363 
1364 LV2_URID LadspaPluginList::map_uri(LV2_URID_Map_Handle handle, const char* uri) {
1365  for (size_t i = 0; i < n_uris; ++i) {
1366  if (!strcmp(uris[i], uri)) {
1367  return i + 1;
1368  }
1369  }
1370 
1371  uris = (char**)realloc(uris, ++n_uris * sizeof(char*));
1372  uris[n_uris - 1] = const_cast<char*>(uri);
1373  return n_uris;
1374 }
1375 
1376 const char* LadspaPluginList::unmap_uri(LV2_URID_Map_Handle handle, LV2_URID urid) {
1377  if (urid > 0 && urid <= n_uris) {
1378  return uris[urid - 1];
1379  }
1380  return NULL;
1381 }
1382 
1383 void LadspaPluginList::get_preset_values(const char* port_symbol,
1384  void* user_data,
1385  const void* value,
1386  uint32_t size,
1387  uint32_t type) {
1388  LV2Preset* pdata = (LV2Preset*)user_data;
1389  for (unsigned int i=0;i< pdata->num_ports;i++) {
1390  const LilvPort* port = lilv_plugin_get_port_by_index(pdata->plugin, i);
1391  const char* sym = lilv_node_as_string(lilv_port_get_symbol(pdata->plugin,port));
1392  if (strcmp(sym, port_symbol) ==0) {
1393  float fvalue = *(const float*)value;
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 += gx_system::to_string(fvalue);
1401  pdata->cline += "\n";
1402 
1403  }
1404  }
1405  }
1406 
1407 void LadspaPluginList::set_preset_values(Glib::ustring port_symbol,
1408  LV2Preset* pdata,
1409  Glib::ustring value) {
1410  for (unsigned int i=0;i< pdata->num_ports;i++) {
1411  const LilvPort* port = lilv_plugin_get_port_by_index(pdata->plugin, i);
1412  Glib::ustring sym = lilv_node_as_string(lilv_port_get_symbol(pdata->plugin,port));
1413  if (sym.compare(port_symbol) ==0) {
1414  Glib::ustring port_id = pdata->sname ;
1415  pdata->cline += " \"lv2_";
1416  pdata->cline += port_id ;
1417  pdata->cline += "." ;
1418  pdata->cline += gx_system::to_string(i) ;
1419  pdata->cline += "\": " ;
1420  pdata->cline += value;
1421  pdata->cline += "\n";
1422  break;
1423  }
1424  }
1425  }
1426 
1427 void LadspaPluginList::get_presets(LV2Preset *pdata) {
1428  LV2_URID_Map map = { NULL, map_uri };
1429  LV2_URID_Unmap unmap = { NULL, unmap_uri };
1430  pdata->cline ="[\"gx_plugin_version\", 1,\n";
1431  LilvNodes* presets = lilv_plugin_get_related(pdata->plugin,
1432  lilv_new_uri(world,LV2_PRESETS__Preset));
1433  LILV_FOREACH(nodes, i, presets) {
1434  const LilvNode* preset = lilv_nodes_get(presets, i);
1435  lilv_world_load_resource(world, preset);
1436  LilvNodes* labels = lilv_world_find_nodes(
1437  world, preset, lilv_new_uri(world, LILV_NS_RDFS "label"), NULL);
1438  if (labels) {
1439  const LilvNode* label = lilv_nodes_get_first(labels);
1440  if (label) {
1441  Glib::ustring set = lilv_node_as_string(label);
1442  pdata->has_preset = true;
1443  LilvState* state = lilv_state_new_from_world(world, &map, preset);
1444  pdata->cline +=" \"" + set + "\"" + " {\n";
1445 
1446  Glib::ustring stt = lilv_state_to_string(world,&map,&unmap,state,"<>",NULL);
1447  std::istringstream stream(stt);
1448  std::string st;
1449  Glib::ustring symbol = "";
1450  Glib::ustring value = "";
1451  while (std::getline(stream, st)) {
1452  std::size_t found = st.find("lv2:symbol");
1453  if(found !=Glib::ustring::npos) {
1454  std::size_t found1 = st.find("\"",found)+1;
1455  std::size_t found2 = st.find("\"",found1);
1456  if(found2 !=Glib::ustring::npos) {
1457  symbol = st.substr(found1, (found2-found1));
1458  } else {
1459  continue;
1460  }
1461  }
1462  found = st.find("pset:value");
1463  if(found !=Glib::ustring::npos) {
1464  std::size_t found1 = st.find(" ",found)+1;
1465  if(found1 !=Glib::ustring::npos) {
1466  value = st.substr(found1);
1467  set_preset_values(symbol,pdata,value);
1468  } else {
1469  continue;
1470  }
1471  }
1472  }
1473  //lilv_state_emit_port_values(state, get_preset_values, pdata);
1474  lilv_state_free(state);
1475  pdata->cline += " },\n";
1476  }
1477  }
1478  lilv_nodes_free(labels);
1479  }
1480  lilv_nodes_free(presets);
1481 }
1482 
1483 void LadspaPluginList::add_plugin(const LilvPlugin* plugin, pluginmap& d, gx_system::CmdlineOptions& options) {
1484 
1485  // check for requested features
1486  LilvNodes* requests = lilv_plugin_get_required_features(plugin);
1487  LILV_FOREACH(nodes, f, requests) {
1488  const char* uri = lilv_node_as_uri(lilv_nodes_get(requests, f));
1489  if (uri) {
1490  lilv_nodes_free(requests);
1491  return;
1492  }
1493  }
1494  lilv_nodes_free(requests);
1495 
1496  int n_in = 0;
1497  int n_out = 0;
1498  std::vector<PortDesc*> ctrl_ports;
1499  int pos = 0;
1500  unsigned int num_ports = lilv_plugin_get_num_ports(plugin);
1501  for (unsigned int n = 0; n < num_ports; n++) {
1502  const LilvPort* port = lilv_plugin_get_port_by_index(plugin, n);
1503  if (lilv_port_is_a(plugin, port, lv2_AudioPort)) {
1504  if (lilv_port_is_a(plugin, port, lv2_InputPort)) {
1505  n_in += 1;
1506  } else {
1507  n_out += 1;
1508  }
1509  } else if (lilv_port_is_a(plugin, port, lv2_ControlPort)) {
1510  LADSPA_PortRangeHint hint;
1511  hint.HintDescriptor = 0;
1512  hint.LowerBound = hint.UpperBound = 0;
1513  LilvNode *pdflt, *pmin, *pmax;
1514  lilv_port_get_range(plugin, port, &pdflt, &pmin, &pmax);
1515  if (pmin) {
1516  hint.LowerBound = lilv_node_as_float(pmin);
1517  hint.HintDescriptor |= LADSPA_HINT_BOUNDED_BELOW;
1518  lilv_node_free(pmin);
1519  }
1520  if (pmax) {
1521  hint.UpperBound = lilv_node_as_float(pmax);
1522  hint.HintDescriptor |= LADSPA_HINT_BOUNDED_ABOVE;
1523  lilv_node_free(pmax);
1524  }
1525  LilvNode* nm = lilv_port_get_name(plugin, port);
1526  PortDesc *pdesc = new PortDesc(n, pos, lilv_port_is_a(plugin, port, lv2_OutputPort), lilv_node_as_string(nm), hint);
1527  lilv_node_free(nm);
1528  if (pdflt) {
1529  pdesc->factory.set_dflt(lilv_node_as_float(pdflt));
1530  lilv_node_free(pdflt);
1531  }
1532  LilvNode* is_int = lilv_new_uri(world, LV2_CORE__integer);
1533  if (lilv_port_has_property(plugin, port, is_int)) {
1534  pdesc->factory.set_tp(tp_int);
1535  }
1536  lilv_node_free(is_int);
1537  LilvNode* is_tog = lilv_new_uri(world, LV2_CORE__toggled);
1538  if (lilv_port_has_property(plugin, port, is_tog)) {
1539  pdesc->factory.set_tp(tp_toggle);
1540  }
1541  lilv_node_free(is_tog);
1542  LilvScalePoints* sp = lilv_port_get_scale_points(plugin, port);
1543  int num_sp = lilv_scale_points_size(sp);
1544  if (num_sp > 0) {
1545  for (LilvIter* it = lilv_scale_points_begin(sp);
1546  !lilv_scale_points_is_end(sp, it);
1547  it = lilv_scale_points_next(sp, it)) {
1548  const LilvScalePoint* p = lilv_scale_points_get(sp, it);
1549  pdesc->factory.set_enumvalue(
1550  lilv_node_as_float(lilv_scale_point_get_value(p)),
1551  lilv_node_as_string(lilv_scale_point_get_label(p)));
1552  }
1553  pdesc->factory.set_tp(tp_enum);
1554  }
1555  lilv_scale_points_free(sp);
1556  ctrl_ports.push_back(pdesc);
1557  pos += 1;
1558  } else {
1559  if (!lilv_port_has_property(plugin, port, lv2_connectionOptional)) {
1560  n_out = 0; // fail
1561  break;
1562  }
1563  }
1564  }
1565  int tp;
1566  if (n_in == 1 && n_out == 1) {
1567  tp = 0;
1568  } else if (n_in == 2 && n_out == 2) {
1569  tp = 1;
1570  } else {
1571  for (std::vector<PortDesc*>::iterator i = ctrl_ports.begin(); i != ctrl_ports.end(); ++i) {
1572  delete *i;
1573  }
1574  return;
1575  }
1576 
1577  // check if plugin instantiate
1578  // LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000, 0);
1579  // if (!instance) {
1580  // return;
1581  // }
1582  // lilv_instance_free(instance);
1583 
1584  PluginDesc* p = d[lilv_node_as_string(lilv_plugin_get_uri(plugin))] = new PluginDesc(world, plugin, tp, ctrl_ports);
1585  pdata.has_preset = false;
1586  if (options.reload_lv2_presets) {
1587  if (p->path.size() != 0) {
1589  pdata.ctrl_ports = ctrl_ports;
1590  pdata.num_ports = num_ports;
1591  pdata.plugin = const_cast<LilvPlugin*>(plugin);
1592  get_presets(&pdata);
1593  }
1594  }
1595 
1596 }
1597 
1598 void LadspaPluginList::lv2_load(pluginmap& d, gx_system::CmdlineOptions& options) {
1599  for (LilvIter* it = lilv_plugins_begin(lv2_plugins);
1600  !lilv_plugins_is_end(lv2_plugins, it);
1601  it = lilv_plugins_next(lv2_plugins, it)) {
1602  add_plugin(lilv_plugins_get(lv2_plugins, it), d, options);
1603  if (options.reload_lv2_presets) {
1604  if (pdata.has_preset && pdata.cline.size() != 0) {
1605  pdata.cline.replace(pdata.cline.end()-2,pdata.cline.end()-1,"");
1606  pdata.cline += "]\n";
1607  std::string pfile = options.get_lv2_preset_dir();
1608  pfile += "lv2_";
1609  pfile += pdata.sname;
1610  ofstream os (pfile.c_str());
1611  os << pdata.cline;
1612  os.close();
1613  }
1614  pdata.has_preset = false;
1615  }
1616  }
1617  options.reload_lv2_presets = false;
1618 }
1619 
1620 static bool cmp_plugins(const PluginDesc *a, const PluginDesc *b) {
1621  return ustring(a->Name) < ustring(b->Name);
1622 }
1623 
1624 void LadspaPluginList::load(gx_system::CmdlineOptions& options, std::vector<std::string>& old_not_found) {
1625  gx_system::PathList pl("LADSPA_PATH");
1626  if (!pl.size()) {
1627  pl.add("/usr/lib/ladspa");
1628  pl.add("/usr/local/lib/ladspa");
1629  pl.add("/usr/lib64/ladspa");
1630  pl.add("/usr/local/lib64/ladspa");
1631  }
1632  pluginmap d;
1633  for (gx_system::PathList::iterator it = pl.begin(); it != pl.end(); ++it) {
1634  Glib::RefPtr<Gio::File> file = *it;
1635  if (!file->query_exists()) {
1636  continue;
1637  }
1638  Glib::RefPtr<Gio::FileEnumerator> child_enumeration =
1639  file->enumerate_children(G_FILE_ATTRIBUTE_STANDARD_NAME
1640  "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
1641  "," G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
1642  Glib::RefPtr<Gio::FileInfo> file_info;
1643 
1644  while ((file_info = child_enumeration->next_file())) {
1645  if (file_info->get_attribute_string(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE) == "application/x-sharedlib") {
1646  std::string nm = file_info->get_attribute_byte_string(G_FILE_ATTRIBUTE_STANDARD_NAME);
1647  if (lib_is_blacklisted(nm)) {
1648  continue;
1649  }
1650  //printf("opening %s/%s\n", file->get_path().c_str(), nm.c_str());
1651  load_defs(Glib::build_filename(file->get_path(), nm), d);
1652  }
1653  }
1654  }
1655  gx_system::PathList rpl("LADSPA_RDF_PATH");
1656  if (!rpl.size()) {
1657  rpl.add("/usr/share/ladspa/rdf");
1658  rpl.add("/usr/local/share/ladspa/rdf");
1659  }
1660  lrdf_init();
1661  for (gx_system::PathList::iterator it = rpl.begin(); it != rpl.end(); ++it) {
1662  Glib::RefPtr<Gio::File> file = *it;
1663  if (!file->query_exists()) {
1664  continue;
1665  }
1666  Glib::RefPtr<Gio::FileEnumerator> child_enumeration =
1667  file->enumerate_children(G_FILE_ATTRIBUTE_STANDARD_NAME
1668  "," G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
1669  "," G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE);
1670  Glib::RefPtr<Gio::FileInfo> file_info;
1671 
1672  while ((file_info = child_enumeration->next_file())) {
1673  //if not f.endswith((".rdf",".rdfs")):
1674  if (file_info->get_attribute_string(G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE) == "application/rdf+xml") {
1675  std::string nm = file_info->get_attribute_byte_string(G_FILE_ATTRIBUTE_STANDARD_NAME);
1676  if (lib_is_blacklisted(nm)) {
1677  continue;
1678  }
1679  lrdf_read_file(("file://"+Glib::build_filename(file->get_path(), nm)).c_str());
1680  }
1681  }
1682  }
1683  std::vector<unsigned long> not_found;
1684  std::set<unsigned long> seen;
1685  std::vector<ustring> base;
1686  locale_t loc = newlocale(LC_ALL, "C", 0);
1687  uselocale(loc);
1688  descend(LADSPA_BASE "Plugin", d, not_found, seen, base);
1689  uselocale(LC_GLOBAL_LOCALE);
1690  freelocale(loc);
1691  lrdf_cleanup();
1692 
1693  lv2_load(d, options);
1694 
1695  ifstream is(options.get_ladspa_config_filename().c_str());
1696  if (!is.fail()) {
1697  try {
1698  JsonParser jp(&is);
1699  jp.next(JsonParser::begin_array);
1700  while (jp.peek() == JsonParser::begin_array) {
1701  jp.next(JsonParser::begin_array);
1702  jp.next(JsonParser::value_string); // path
1703  std::string key = jp.current_value();
1704  jp.next(JsonParser::value_number); // index
1705  int idx = jp.current_value_int();
1706  jp.next(JsonParser::value_number); // UniqueID
1707  if (idx >= 0) {
1708  unsigned long uid = jp.current_value_uint();
1709  key = make_key(uid);
1710  }
1711  if (d.find(key) == d.end()) {
1712  old_not_found.push_back(key);
1713  } else {
1714  d[key]->set_active(true);
1715  d[key]->active_set = true;
1716  }
1717  jp.next(JsonParser::value_string); // Label
1718  jp.next(JsonParser::end_array);
1719  }
1720  jp.close();
1721  } catch(JsonException& e) {
1723  "ladspalist", ustring::compose(
1724  _("error loading ladspa plugin selection data from file %1"),
1725  options.get_ladspa_config_filename()));
1726  }
1727  is.close();
1728  }
1729  for (pluginmap::iterator v = d.begin(); v != d.end(); ++v) {
1730  v->second->fixup();
1731  std::string s;
1732  if (v->second->is_lv2) {
1733  s = gx_system::encode_filename(v->second->path) + ".js";
1734  } else {
1736  }
1737  std::string fname = options.get_plugin_filepath(s);
1738  if (access(fname.c_str(), F_OK) != 0) {
1739  fname = options.get_factory_filepath(s);
1740  if (access(fname.c_str(), F_OK) != 0) {
1741  fname = "";
1742  }
1743  }
1744  if (!fname.empty()) {
1745  v->second->set_state(fname);
1746  }
1747  }
1748  for (pluginmap::iterator i = d.begin(); i != d.end(); ++i) {
1749  push_back(i->second);
1750  }
1751  std::sort(begin(), end(), cmp_plugins);
1752 }
1753 
1755  std::string fname = options.get_ladspa_config_filename();
1756  std::string tfname = fname + ".tmp";
1757  ofstream tfile(tfname.c_str());
1758  JsonWriter jw(&tfile);
1759  jw.begin_array(true);
1760  for (std::vector<PluginDesc*>::iterator p = begin(); p != end(); ++p) {
1761  if ((*p)->active) {
1762  (*p)->output_entry(jw);
1763  }
1764  }
1765  jw.end_array(true);
1766  jw.close();
1767  tfile.close();
1768  std::vector<std::pair<std::string,std::string> > fl;
1769  for (std::vector<PluginDesc*>::iterator p = begin(); p != end(); ++p) {
1770  std::string sname = ((*p)->is_lv2 ?
1771  gx_system::encode_filename((*p)->path) + ".js" :
1773  std::string cname = options.get_plugin_filepath(sname);
1774  if ((*p)->active || (*p)->has_settings) {
1775  std::string tcname = cname + ".tmp";
1776  ofstream tcfile(tcname.c_str());
1777  JsonWriter jw2(&tcfile);
1778  (*p)->output(jw2);
1779  jw2.close();
1780  tcfile.close();
1781  fl.push_back(std::pair<std::string,std::string>(tcname, cname));
1782  } else {
1783  fl.push_back(std::pair<std::string,std::string>("", cname));
1784  }
1785  }
1786  if (rename(tfname.c_str(), fname.c_str()) != 0) {
1787  char buf[100];
1788  char *p = strerror_r(errno, buf, sizeof(buf));
1790  "ladspalist",ustring::compose(_("error renaming LADSPA config file '%1': %2"), fname, p));
1791  return;
1792  }
1793  for (std::vector<std::pair<std::string,std::string> >::iterator i = fl.begin(); i != fl.end(); ++i) {
1794  if (i->first.empty()) {
1795  unlink(i->second.c_str());
1796  } else {
1797  if (rename(i->first.c_str(), i->second.c_str()) != 0) {
1798  char buf[100];
1799  char *p = strerror_r(errno, buf, sizeof(buf));
1801  "ladspalist",
1802  ustring::compose("error renaming %1 to %2: %3\n", i->first, i->second, p));
1803  }
1804  }
1805  }
1806 }
1807 
1808 
1811  while (jp.peek() != gx_system::JsonParser::end_array) {
1812  push_back(new ladspa::PluginDesc(jp));
1813  }
1815 }
1816 
1818  jw.begin_array();
1819  for (iterator i = begin(); i != end(); ++i) {
1820  (*i)->serializeJSON(jw);
1821  }
1822  jw.end_array();
1823 }
1824 
1826  for (iterator i = begin(); i != end(); ++i) {
1827  delete *i;
1828  }
1829  free(uris);
1830  uris = NULL;
1831  lilv_node_free(lv2_AudioPort);
1832  lilv_node_free(lv2_ControlPort);
1833  lilv_node_free(lv2_InputPort);
1834  lilv_node_free(lv2_OutputPort);
1835  lilv_node_free(lv2_connectionOptional);
1836  lilv_world_free(world);
1837 }
1838 
1839 } // namespace ladspa
int set_active(bool v)
CmdConnection::msg_type end
Definition: jsonrpc.cpp:256
bool check_changed(const PortDesc &vp) const
Definition: ladspaback.cpp:381
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
std::string get_factory_filepath(const std::string &basename) const
Definition: gx_system.h:465
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:196
void set_state(const Glib::ustring &fname)
std::string cline
Definition: ladspaback.h:197
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:193
void set_add_wet_dry_controller(bool v)
STL namespace.
std::map< int, Glib::ustring >::iterator enum_end()
Definition: ladspaback.h:69
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)
int get_excl_flags(DisplayType tp) const
Definition: ladspaback.cpp:180
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:882
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:194
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:195
void save(gx_system::CmdlineOptions &options)
std::string get_plugin_filepath(const std::string &basename) const
Definition: gx_system.h:464
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
bool is_set(int f) const
Definition: ladspaback.h:51
std::string to_string(const T &t)
Definition: gx_system.h:525
virtual const char * what() const
Definition: gx_json.h:46
void output(gx_system::JsonWriter &jw)
Definition: ladspaback.cpp:592
std::string get_ladspa_config_filename() const
Definition: gx_system.h:479
unsigned long to
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)
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
string current_value() const
Definition: gx_json.h:143
const std::string & get_lv2_preset_dir() const
Definition: gx_system.h:475
friend bool cmp_ctrl_ports(const PortDesc *a, const PortDesc *b)
Definition: ladspaback.cpp:864
Glib::ustring get_enum(int idx)
Definition: ladspaback.cpp:368
int flag
Definition: ladspaback.cpp:55
void set_stereo_to_mono(bool v)
static std::string get_ladspa_filename(unsigned long uid)
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
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:1001