Guitarix
ladspaplugin.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 <dlfcn.h>
20 #include <ladspa.h>
21 
22 #include "engine.h"
23 
27 using Glib::ustring;
28 
29 namespace gx_engine {
30 
31 /****************************************************************
32  ** class LadspaDsp
33  */
34 
35 class LadspaDsp: public PluginDef {
36 private:
37  static void init(unsigned int samplingFreq, PluginDef *plugin);
38  static void mono_process(int count, float *input, float *output, PluginDef *plugin);
39  static void to_mono_process(int count, float *input, float *output, PluginDef *plugin);
40  static void stereo_process(int count, float *input1, float *input2, float *output1, float *output2, PluginDef *plugin);
41  static int activate(bool start, PluginDef *plugin);
42  static int registerparam(const ParamReg& reg);
43  static int uiloader(const UiBuilder& builder, int form);
44  static void del_instance(PluginDef *plugin);
45  //
46  const LADSPA_Descriptor *desc;
47  void *handle;
48  LADSPA_Handle instance;
49  LADSPA_Data *ports;
50  Glib::ustring name_str;
51  Glib::ustring dest_str;
52  const plugdesc *pd;
53  bool is_activated;
54  void connect(int tp, int i, float *v);
55  inline void cleanup();
56  void set_shortname();
57  float dry_wet;
58  std::string idd;
59  inline void mono_dry_wet(int count, float *input0, float *input1, float *output0);
60  inline void stereo_dry_wet(int count, float *input0, float *input1, float *input2, float *input3, float *output0, float *output1);
61  inline void down_to_mono(int count, float *input0, float *input1, float *output0);
62  inline void up_to_stereo(int count, float *input0, float *output0, float *output1);
63  std::string make_id(const paradesc& p);
64  LadspaDsp(const plugdesc *plug, void *handle_, const LADSPA_Descriptor *desc_, bool mono, bool to_mono);
65  ~LadspaDsp();
66 public:
67  static LadspaDsp *create(const plugdesc *plug);
68  void set_plugdesc(const plugdesc* pd_);
69 };
70 
72  void *handle;
73  handle = dlopen(plug->path.c_str(), RTLD_LOCAL|RTLD_NOW);
74  if (!handle) {
75  gx_print_error("ladspaloader",ustring::compose(_("Cannot open plugin: %1 [%2]"), plug->path, dlerror()));
76  return NULL;
77  }
78  LADSPA_Descriptor_Function ladspa_descriptor = (LADSPA_Descriptor_Function)dlsym(handle, "ladspa_descriptor");
79  const char *dlsym_error = dlerror();
80  if (dlsym_error) {
81  gx_print_error("ladspaloader",ustring::compose(_("Cannot load symbol 'ladspa_descriptor': %1"), dlsym_error));
82  dlclose(handle);
83  handle = 0;
84  return NULL;
85  }
86  const LADSPA_Descriptor *desc = ladspa_descriptor(plug->index);
87  if (!desc || desc->UniqueID != plug->UniqueID) {
88  for (int i = 0; ; i++) {
89  desc = ladspa_descriptor(i);
90  if (!desc) {
91  break;
92  }
93  if (desc->UniqueID == plug->UniqueID) {
94  break;
95  }
96  }
97  }
98  if (!desc) {
99  gx_print_error("ladspaloader",ustring::compose(_("Cannot load ladspa descriptor #%1 from %2"), plug->index, plug->path));
100  dlclose(handle);
101  handle = 0;
102  return NULL;
103  }
104  if (desc->UniqueID == 4069 || desc->UniqueID == 4070) {
105  gx_print_error("ladspaloader",_("ladspa_guitarix not loaded"));
106  dlclose(handle);
107  handle = 0;
108  return NULL;
109  }
110  int num_inputs = 0;
111  int num_outputs = 0;
112  for (unsigned int i = 0; i < desc->PortCount; ++i) {
113  if (LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[i])) {
114  if (LADSPA_IS_PORT_INPUT(desc->PortDescriptors[i])) {
115  num_inputs += 1;
116  } else { // LADSPA_IS_PORT_OUTPUT(desc->PortDescriptors[i])
117  num_outputs += 1;
118  }
119  }
120  }
121  bool mono;
122  bool to_mono = false;
123  if (num_inputs == 1 && num_outputs == 1) {
124  mono = true;
125  } else if (num_inputs == 2 && num_outputs == 2) {
126  mono = false;
127  if (plug->stereo_to_mono) to_mono = true;
128  } else {
130  "ladspaloader",ustring::compose(
131  _("cannot use ladspa plugin %1 with %2 inputs and %3 outputs"),
132  desc->Label, num_inputs, num_outputs));
133  dlclose(handle);
134  handle = 0;
135  return NULL;
136  }
137 
138  LadspaDsp* self = new LadspaDsp(plug, handle, desc, mono, to_mono);
139  PluginDef& pl = *static_cast<PluginDef*>(self);
140  pl.flags |=PGNI_IS_LADSPA;
141  return self;
142 }
143 
144 LadspaDsp::LadspaDsp(const plugdesc *plug, void *handle_, const LADSPA_Descriptor *desc_, bool mono, bool to_mono)
145  : PluginDef(), desc(desc_), handle(handle_), instance(),
146  ports(new LADSPA_Data[desc->PortCount]), name_str(), dest_str(), pd(plug), is_activated(false) {
148  id = pd->id_str.c_str();
149  category = pd->category.c_str();
150  dest_str = "LADSPA ";
151  dest_str += desc->Name;
152  dest_str += " by ";
153  dest_str += desc->Maker;
154  description = dest_str.c_str();
155  name = desc->Name;
156  set_shortname();
157  set_samplerate = init;
158  if (mono) {
159  mono_audio = mono_process;
160  } else {
161  if (to_mono) mono_audio = to_mono_process;
162  else stereo_audio = stereo_process;
163  }
164  activate_plugin = activate;
165  register_params = registerparam;
166  load_ui = uiloader;
167  delete_instance = del_instance;
168 }
169 
170 inline void LadspaDsp::cleanup() {
171  if (instance) {
172  if (pd->quirks & need_activate) {
173  activate(true, this);
174  }
175  activate(false, this);
176  if (!(pd->quirks & no_cleanup)) {
177  desc->cleanup(instance);
178  }
179  instance = 0;
180  }
181 }
182 
185  while (jp.peek() != gx_system::JsonParser::end_object) {
187  if (jp.read_kv("index", index) ||
188  jp.read_kv("name", name) ||
189  jp.read_kv("dflt", dflt) ||
190  jp.read_kv("low", low) ||
191  jp.read_kv("up", up) ||
192  jp.read_kv("step", step) ||
193  jp.read_kv("tp", tp) ||
194  jp.read_kv("newrow", newrow) ||
195  jp.read_kv("has_caption", has_caption)) {
196  } else if (jp.current_value() == "values") {
197  std::vector<std::string> v;
199  while (jp.peek() != gx_system::JsonParser::end_array) {
201  v.push_back(jp.current_value());
202  }
204  set_valuelist(v);
205  } else {
206  assert(false);
207  }
208  }
210 }
211 
213  jw.begin_object();
214  jw.write_kv("index", index);
215  jw.write_kv("name", name);
216  jw.write_kv("dflt", dflt);
217  jw.write_kv("low", low);
218  jw.write_kv("up", up);
219  jw.write_kv("step", step);
220  jw.write_kv("tp", tp);
221  jw.write_kv("newrow", newrow);
222  jw.write_kv("has_caption", has_caption);
223  if (values) {
224  jw.write_key("values");
225  jw.begin_array();
226  for (value_pair *p = values; p->value_id; p++) {
227  jw.begin_array();
228  jw.write(p->value_id);
229  jw.write(p->value_label);
230  jw.end_array();
231  }
232  jw.end_array();
233  }
234  jw.end_object();
235 }
236 
239  while (jp.peek() != gx_system::JsonParser::end_object) {
241  if (jp.read_kv("path", path) ||
242  jp.read_kv("index", index) ||
243  jp.read_kv("UniqueID", UniqueID) ||
244  jp.read_kv("Label", Label) ||
245  jp.read_kv("shortname", shortname) ||
246  jp.read_kv("category", category) ||
247  jp.read_kv("quirks", quirks) ||
248  jp.read_kv("add_wet_dry", add_wet_dry) ||
249  jp.read_kv("stereo_to_mono", stereo_to_mono) ||
250  jp.read_kv("master_idx", master_idx) ||
251  jp.read_kv("master_label", master_label) ||
252  jp.read_kv("id_str", id_str)) {
253  } else if (jp.current_value() == "names") {
255  while (jp.peek() != gx_system::JsonParser::end_array) {
256  paradesc *p = new paradesc();
257  p->readJSON(jp);
258  names.push_back(p);
259  }
261  } else {
262  assert(false);
263  }
264  }
266 }
267 
269  jw.begin_object();
270  jw.write_kv("path", path);
271  jw.write_kv("index", index);
272  jw.write_kv("UniqueID", static_cast<unsigned int>(UniqueID));
273  jw.write_kv("Label", Label);
274  jw.write_kv("shortname", shortname);
275  jw.write_kv("category", category);
276  jw.write_kv("quirks", quirks);
277  jw.write_kv("add_wet_dry", add_wet_dry);
278  jw.write_kv("stereo_to_mono", stereo_to_mono);
279  jw.write_kv("master_idx", master_idx);
280  jw.write_kv("master_label", master_label);
281  jw.write_kv("id_str", id_str);
282  jw.write_key("names");
283  jw.begin_array();
284  for (std::vector<paradesc*>::iterator i = names.begin(); i != names.end(); ++i) {
285  (*i)->writeJSON(jw);
286  }
287  jw.end_array();
288  jw.end_object();
289 }
290 
291 plugdesc::~plugdesc() {
292  for (std::vector<paradesc*>::const_iterator it = names.begin(); it != names.end(); ++it) {
293  delete *it;
294  }
295 }
296 
297 LadspaDsp::~LadspaDsp() {
298  cleanup();
299  if (handle && !(pd->quirks & no_cleanup)) {
300  dlclose(handle);
301  }
302  delete[] ports;
303 }
304 
305 int LadspaDsp::activate(bool start, PluginDef *plugin) {
306  LadspaDsp& self = *static_cast<LadspaDsp*>(plugin);
307  if (start == self.is_activated) {
308  return 0;
309  }
310  self.is_activated = start;
311  if (start) {
312  if (self.desc->activate) {
313  self.desc->activate(self.instance);
314  }
315  } else {
316  if (self.desc->deactivate) {
317  self.desc->deactivate(self.instance);
318  }
319  }
320  return 0;
321 }
322 
323 void LadspaDsp::connect(int tp, int i, float *v) {
324  for (unsigned int n = 0; n < desc->PortCount; ++n) {
325  if (!LADSPA_IS_PORT_AUDIO(desc->PortDescriptors[n])) {
326  continue;
327  }
328  if (desc->PortDescriptors[n] & tp) {
329  if (i == 0) {
330  desc->connect_port(instance, n, v);
331  return;
332  }
333  i -= 1;
334  }
335  }
336  gx_print_error("ladspaloader", _("audio port not found"));
337 }
338 
340  pd = pd_;
341  id = pd->id_str.c_str();
342  category = pd->category.c_str();
343  set_shortname();
344 }
345 
346 void LadspaDsp::set_shortname() {
347  if (!pd->shortname.empty()) {
348  shortname = pd->shortname.c_str();
349  } else {
350  name_str = desc->Name;
351  if (name_str.size() > 15) {
352  name_str.erase(15);
353  }
354  shortname = name_str.c_str();
355  }
356 }
357 
358 void LadspaDsp::init(unsigned int samplingFreq, PluginDef *plugin) {
359  LadspaDsp& self = *static_cast<LadspaDsp*>(plugin);
360  self.cleanup();
361  if (samplingFreq == 0) {
362  return;
363  }
364  self.instance = self.desc->instantiate(self.desc, samplingFreq);
365  int n = 0;
366  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
367  self.desc->connect_port(self.instance, (*it)->index, &self.ports[(*it)->index]);
368  }
369 }
370 
371 inline void LadspaDsp::mono_dry_wet(int count, float *input0, float *input1, float *output0)
372 {
373  double fSlow0 = (0.01 * dry_wet);
374  double fSlow1 = (1 - fSlow0);
375  for (int i=0; i<count; i++) {
376  output0[i] = ((fSlow0 * (double)input1[i]) + (fSlow1 * (double)input0[i]));
377  }
378 }
379 
380 void LadspaDsp::mono_process(int count, float *input, float *output, PluginDef *plugin) {
381  LadspaDsp& self = *static_cast<LadspaDsp*>(plugin);
382  assert(self.is_activated);
383  if (self.pd->add_wet_dry) {
384  float wet_out[count];
385  self.connect(LADSPA_PORT_INPUT, 0, input);
386  self.connect(LADSPA_PORT_OUTPUT, 0, wet_out);
387  self.desc->run(self.instance, count);
388  self.mono_dry_wet(count, input, wet_out, output);
389  } else {
390  self.connect(LADSPA_PORT_INPUT, 0, input);
391  self.connect(LADSPA_PORT_OUTPUT, 0, output);
392  self.desc->run(self.instance, count);
393  }
394 }
395 
396 void LadspaDsp::up_to_stereo(int count, float *input0, float *output0, float *output1) {
397  memcpy(output0, input0, count * sizeof(float));
398  memcpy(output1, input0, count * sizeof(float));
399 }
400 
401 void LadspaDsp::down_to_mono(int count, float *input0, float *input1, float *output0) {
402  for (int i=0; i<count; i++) {
403  output0[i] = 0.5 * (input0[i] + input1[i]);
404  }
405 }
406 
407 void LadspaDsp::to_mono_process(int count, float *input, float *output, PluginDef *plugin) {
408  LadspaDsp& self = *static_cast<LadspaDsp*>(plugin);
409  assert(self.is_activated);
410  if (self.pd->add_wet_dry) {
411  float wet_out[count];
412  float inputs[count];
413  float inputs1[count];
414  float outputs[count];
415  float outputs1[count];
416  self.up_to_stereo(count,input,inputs, inputs1);
417  self.connect(LADSPA_PORT_INPUT, 0, inputs);
418  self.connect(LADSPA_PORT_INPUT, 1, inputs1);
419  self.connect(LADSPA_PORT_INPUT, 0, outputs);
420  self.connect(LADSPA_PORT_INPUT, 1, outputs1);
421  self.desc->run(self.instance, count);
422  self.down_to_mono(count,outputs,outputs1,wet_out);
423  self.mono_dry_wet(count, input, wet_out, output);
424  } else {
425  float inputs[count];
426  float inputs1[count];
427  float outputs[count];
428  float outputs1[count];
429  self.up_to_stereo(count,input,inputs, inputs1);
430  self.connect(LADSPA_PORT_INPUT, 0, inputs);
431  self.connect(LADSPA_PORT_INPUT, 1, inputs1);
432  self.connect(LADSPA_PORT_INPUT, 0, outputs);
433  self.connect(LADSPA_PORT_INPUT, 1, outputs1);
434  self.desc->run(self.instance, count);
435  self.down_to_mono(count,outputs,outputs1,output);
436  }
437 }
438 
439 inline void LadspaDsp::stereo_dry_wet(int count, float *input0, float *input1, float *input2, float *input3, float *output0, float *output1)
440 {
441  double fSlow0 = (0.01 * dry_wet);
442  double fSlow1 = (1 - fSlow0);
443  for (int i=0; i<count; i++) {
444  output0[i] = ((fSlow0 * (double)input2[i]) + (fSlow1 * (double)input0[i]));
445  output1[i] = ((fSlow0 * (double)input3[i]) + (fSlow1 * (double)input1[i]));
446  }
447 }
448 
449 void LadspaDsp::stereo_process(int count, float *input1, float *input2, float *output1, float *output2, PluginDef *plugin) {
450  LadspaDsp& self = *static_cast<LadspaDsp*>(plugin);
451  assert(self.is_activated);
452  if (self.pd->add_wet_dry) {
453  float wet_out1[count];
454  float wet_out2[count];
455  self.connect(LADSPA_PORT_INPUT, 0, input1);
456  self.connect(LADSPA_PORT_INPUT, 1, input2);
457  self.connect(LADSPA_PORT_OUTPUT, 0, wet_out1);
458  self.connect(LADSPA_PORT_OUTPUT, 1, wet_out2);
459  self.desc->run(self.instance, count);
460  self.stereo_dry_wet(count, input1, input2, wet_out1, wet_out2, output1, output2);
461  } else {
462  self.connect(LADSPA_PORT_INPUT, 0, input1);
463  self.connect(LADSPA_PORT_INPUT, 1, input2);
464  self.connect(LADSPA_PORT_OUTPUT, 0, output1);
465  self.connect(LADSPA_PORT_OUTPUT, 1, output2);
466  self.desc->run(self.instance, count);
467  }
468 }
469 
470 static Glib::ustring TrimLabel(const char *label, int cnt_in_row) {
471  const size_t minlen = 60 / cnt_in_row - 1;
472  const size_t maxlen = minlen + 10;
473  const size_t cutlen = (maxlen + minlen) / 2;
474  Glib::ustring pn(label);
475  size_t rem = pn.find_first_of("([");
476  if(rem != Glib::ustring::npos) {
477  pn.erase(rem);
478  }
479  while ((rem = pn.find_last_of(" ")) == pn.size()-1) {
480  pn.erase(rem);
481  }
482  rem = 0;
483  size_t rem1 = 0;
484  size_t lastpos = 0;
485  while (true) {
486  rem1 = pn.find_first_of(" ", rem1);
487  if (rem1 == Glib::ustring::npos) {
488  rem1 = pn.size();
489  }
490  while (rem1 > rem + minlen) {
491  if (lastpos > rem) {
492  rem = lastpos;
493  pn.replace(lastpos, 1, 1, '\n');
494  } else if (rem1 < rem + maxlen) {
495  if (rem1 == pn.size()) {
496  break;
497  }
498  rem = rem1;
499  pn.replace(rem1, 1, 1, '\n');
500  } else {
501  rem += cutlen;
502  pn.insert(rem, "\n");
503  }
504  rem += 1;
505  }
506  lastpos = rem1;
507  rem1 += 1;
508  if (rem1 >= pn.size()) {
509  break;
510  }
511  }
512  return pn;
513 }
514 
515 static Glib::ustring TrimEffectLabel(const char *label, int cnt_in_row) {
516  const size_t minlen = 60 / cnt_in_row - 1;
517  const size_t maxlen = minlen + 10;
518  const size_t cutlen = (maxlen + minlen) / 2;
519  Glib::ustring pn(label);
520  size_t rem = 0;
521  size_t rem1 = 0;
522  size_t lastpos = 0;
523  while (true) {
524  rem1 = pn.find_first_of(" ", rem1);
525  if (rem1 == Glib::ustring::npos) {
526  rem1 = pn.size();
527  }
528  while (rem1 > rem + minlen) {
529  if (lastpos > rem) {
530  rem = lastpos;
531  pn.replace(lastpos, 1, 1, '\n');
532  } else if (rem1 < rem + maxlen) {
533  if (rem1 == pn.size()) {
534  break;
535  }
536  rem = rem1;
537  pn.replace(rem1, 1, 1, '\n');
538  } else {
539  rem += cutlen;
540  pn.insert(rem, "\n");
541  }
542  rem += 1;
543  }
544  lastpos = rem1;
545  rem1 += 1;
546  if (rem1 >= pn.size()) {
547  break;
548  }
549  }
550  return pn;
551 }
552 
553 std::string LadspaDsp::make_id(const paradesc& p) {
554  return pd->id_str + "." + to_string(p.index);
555 }
556 
557 int LadspaDsp::registerparam(const ParamReg& reg) {
558  LadspaDsp& self = *static_cast<LadspaDsp*>(reg.plugin);
559  int n = 0;
560  int cnt_in_row = 0;
561  int left = 0;
562  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
563  paradesc *d = *it;
564  if (d->tp != tp_none) {
565  left -= 1;
566  if (left < 0) {
567  cnt_in_row = 1;
568  std::vector<paradesc*>::const_iterator it2 = it+1;
569  while (it2 != self.pd->names.end() && !(*it2)->newrow) {
570  if ((*it2)->tp != tp_none) {
571  ++cnt_in_row;
572  }
573  ++it2;
574  }
575  left = cnt_in_row;
576  }
577  }
578  const char *nm = self.desc->PortNames[d->index];
579  Glib::ustring snm(d->name);
580  if (snm.empty() && d->tp != tp_none) {
581  snm = TrimLabel(nm, cnt_in_row);
582  }
583  if (d->tp == tp_enum) {
584  reg.registerEnumVar(self.make_id(*d).c_str(), snm.c_str(), "S", nm, d->values, &self.ports[d->index],
585  d->dflt, d->low, d->up, d->step);
586  } else {
587  const char *tp = 0;
588  switch (d->tp) {
589  case tp_none: tp = "S"; break;
590  case tp_int: tp = "S"; break;
591  case tp_scale: tp = "S"; break;
592  case tp_scale_log: tp = "SL"; break;
593  case tp_toggle: tp = "B"; break;
594  case tp_display: tp = "SO"; break;
595  case tp_display_toggle: tp = "BO"; break;
596  default: assert(false);
597  }
598  reg.registerVar(self.make_id(*d).c_str(), snm.c_str(), tp, nm, &self.ports[d->index],
599  d->dflt, d->low, d->up, d->step);
600  }
601  }
602  self.idd = self.pd->id_str + ".dry_wet";
603  reg.registerVar(self.idd.c_str(),"","S","dry/wet",&self.dry_wet, 100, 0, 100, 1);
604  return 0;
605 }
606 
607 int LadspaDsp::uiloader(const UiBuilder& b, int form) {
608  if (!(form & UI_FORM_STACK)) {
609  return -1;
610  }
611  LadspaDsp& self = *static_cast<LadspaDsp*>(b.plugin);
612  b.openHorizontalhideBox("");
613  if (self.pd->master_idx >= 0) {
614  int n = 0;
615  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
616  if ((n)==self.pd->master_idx) {
617  switch ((*it)->tp) {
618  case tp_enum:
619  b.create_selector_no_caption(self.make_id(*self.pd->names[self.pd->master_idx]).c_str());
620  break;
621  default:
622  const char *p = self.pd->master_label.c_str();
623  if (!*p) {
624  p = "";
625  }
626  b.create_master_slider(self.make_id(*self.pd->names[self.pd->master_idx]).c_str(), p);
627  break;
628  }
629  }
630  }
631  }
632  int rows = 0;
633  int n = 0;
634  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
635  if ((*it)->newrow) {
636  rows +=1;
637  }
638  }
639  b.closeBox();
640  b.openVerticalBox("");
641  if (rows > 0) {
642  b.insertSpacer();
643  b.insertSpacer();
644  }
645  b.openHorizontalBox("");
646  n = 0;
647  int row = 0;
648  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
649  if ((*it)->newrow) {
650  b.closeBox();
651  if ( (rows == 1) || ( rows > 1 && row > 0 )) {
652  b.insertSpacer();
653  b.insertSpacer();
654  b.insertSpacer();
655  }
656  b.openHorizontalBox("");
657  row +=1;
658  }
659  const char *p1 = self.desc->PortNames[(*it)->index];
660  if (!(*it)->name.empty())
661  p1 = (*it)->name.c_str();
662  Glib::ustring trim = TrimEffectLabel(p1, 4);
663  const char *p = trim.c_str();
664  std::string id = self.make_id(**it);
665  if ((row == 1 && rows == 1 ) || (row >1 && rows >1 )) {
667  }
668  switch ((*it)->tp) {
669  case tp_scale:
670  case tp_scale_log:
671  if (!(*it)->has_caption) {
672  p = "";
673  }
674  b.create_small_rackknobr(id.c_str(), p);
675  break;
676  case tp_toggle:
677  if ((*it)->has_caption) {
678  b.create_switch("switch",id.c_str(), p);
679  } else {
680  b.create_switch_no_caption("switchit",id.c_str());
681  }
682  break;
683  case tp_display:
684  if (!(*it)->has_caption) {
685  p = "";
686  }
687  b.create_port_display(id.c_str(), p);
688  break;
689  case tp_display_toggle:
690  if ((*it)->has_caption) {
691  b.create_switch("led",id.c_str(), p);
692  } else {
693  b.create_switch_no_caption("led",id.c_str());
694  }
695  break;
696  case tp_int:
697  if (!(*it)->has_caption) {
698  p = "";
699  }
700  if (((*it)->up - (*it)->low)<200) {
701  b.create_small_rackknob(id.c_str(), p);
702  } else {
703  b.create_spin_value(id.c_str(), p);
704  }
705  break;
706  case tp_enum:
707  if ((*it)->has_caption) {
708  b.create_selector(id.c_str(), p);
709  } else {
710  b.create_selector_no_caption(id.c_str());
711  }
712  break;
713  case tp_none:
714  break;
715  default:
716  assert(false);
717  }
718  }
719  if (self.pd->add_wet_dry) {
720  b.create_small_rackknobr(self.idd.c_str(), "dry/wet");
721  }
722  b.closeBox();
723  b.closeBox();
724  return 0;
725 }
726 
727 void LadspaDsp::del_instance(PluginDef *plugin) {
728  delete static_cast<LadspaDsp*>(plugin);
729 }
730 
731 
732 /****************************************************************
733  ** class LV2Features
734  */
735 
736 static const int32_t min_block_length = 1;
737 static const int32_t max_block_length = 8192;
738 
739 
740 static std::vector<std::string> gx_uri_mapping = {
741  LV2_ATOM__Int,
742  LV2_ATOM__Long,
743  LV2_ATOM__Float,
744  LV2_ATOM__Double,
745  LV2_BUF_SIZE__maxBlockLength,
746  LV2_BUF_SIZE__minBlockLength,
747 };
748 
749 
750 LV2_Options_Option LV2Features::gx_options[2] = {
751  { LV2_OPTIONS_INSTANCE, 0, lv2_urid_map(NULL,LV2_BUF_SIZE__minBlockLength),
752  sizeof(int32_t), lv2_urid_map(NULL,LV2_ATOM__Int), &min_block_length },
753  { LV2_OPTIONS_INSTANCE, 0, lv2_urid_map(NULL,LV2_BUF_SIZE__maxBlockLength),
754  sizeof(int32_t), lv2_urid_map(NULL,LV2_ATOM__Int), &max_block_length },
755 };
756 
757 LV2_Feature LV2Features::gx_options_feature = {
758  LV2_OPTIONS__options, gx_options
759 };
760 
761 LV2_URID LV2Features::lv2_urid_map(LV2_URID_Map_Handle, const char* const uri_) {
762  if (uri_ == nullptr || uri_[0] == '\0') {
763  return 0;
764  }
765 
766  const std::string uri(uri_);
767 
768  LV2_URID urid = 1;
769  for (const std::string& uri2 : gx_uri_mapping)
770  {
771  if (uri2 == uri) {
772  //fprintf(stderr, "%s uri match\n", uri.c_str());
773  return urid;
774  }
775  ++urid;
776  }
777 
778  gx_uri_mapping.push_back(uri);
779  return urid;
780 }
781 
782 LV2_URID_Map LV2Features::gx_urid_map = {
783  NULL, lv2_urid_map
784 };
785 
786 LV2_Feature LV2Features::gx_urid_map_feature = {
787  LV2_URID__map, &gx_urid_map
788 };
789 
790 uint32_t LV2Features::lv2_uri_to_id(LV2_URI_Map_Callback_Data handle, const char*, const char* uri) {
791  return lv2_urid_map(handle, uri);
792 }
793 
794 LV2_URI_Map_Feature LV2Features::gx_uri_map = {
795  NULL, lv2_uri_to_id
796 };
797 
798 LV2_Feature LV2Features::gx_uri_map_feature = {
799  LV2_URI_MAP_URI, &gx_uri_map
800 };
801 
802 const char* LV2Features::lv2_urid_unmap(LV2_URID_Unmap_Handle, const LV2_URID urid) {
803  if (urid == 0 || urid >= gx_uri_mapping.size())
804  return nullptr;
805 
806  return gx_uri_mapping[urid-1].c_str();
807 }
808 
809 LV2_URID_Unmap LV2Features::gx_urid_unmap = {
810  NULL, lv2_urid_unmap
811 };
812 
813 LV2_Feature LV2Features::gx_urid_unmap_feature = {
814  LV2_URID__unmap, &gx_urid_unmap
815 };
816 
817 LV2_Feature* LV2Features::gx_features[] = {
818  &gx_urid_map_feature,
819  &gx_uri_map_feature,
820  &gx_urid_unmap_feature,
821  &gx_options_feature,
822  nullptr
823 };
824 
825 /****************************************************************
826  ** class Lv2Dsp
827  */
828 
829 class Lv2Dsp: public PluginDef {
830 private:
831  static void init(unsigned int samplingFreq, PluginDef *plugin);
832  static void mono_process(int count, float *input, float *output, PluginDef *plugin);
833  static void to_mono_process(int count, float *input, float *output, PluginDef *plugin);
834  static void stereo_process(int count, float *input1, float *input2, float *output1, float *output2, PluginDef *plugin);
835  static int activate(bool start, PluginDef *plugin);
836  static int registerparam(const ParamReg& reg);
837  static int uiloader(const UiBuilder& builder, int form);
838  static void del_instance(PluginDef *plugin);
839  //
840  const LadspaLoader& loader;
841  const LilvPlugin* plugin;
842  LilvNode* name_node;
843  LilvInstance* instance;
844  LADSPA_Data *ports;
845  Glib::ustring name_str;
846  Glib::ustring dest_str;
847  const plugdesc *pd;
848  bool is_activated;
849  void connect(const LilvNode* tp, int i, float *v);
850  inline void cleanup();
851  void set_shortname();
852  float dry_wet;
853  std::string idd;
854  inline void mono_dry_wet(int count, float *input0, float *input1, float *output0);
855  inline void stereo_dry_wet(int count, float *input0, float *input1, float *input2, float *input3, float *output0, float *output1);
856  inline void down_to_mono(int count, float *input0, float *input1, float *output0);
857  inline void up_to_stereo(int count, float *input0, float *output0, float *output1);
858  std::string make_id(const paradesc& p);
859  Lv2Dsp(const plugdesc *plug, const LilvPlugin* plugin_, const LadspaLoader& loader_, bool mono, bool to_mono);
860  ~Lv2Dsp();
861 public:
862  static Lv2Dsp *create(const plugdesc *plug, const LadspaLoader& loader);
863  void set_plugdesc(const plugdesc* pd_);
864 };
865 
866 Lv2Dsp *Lv2Dsp::create(const plugdesc *plug, const LadspaLoader& loader) {
867  LilvNode* plugin_uri = lilv_new_uri(loader.world, plug->path.c_str());
868  const LilvPlugin* plugin = lilv_plugins_get_by_uri(loader.lv2_plugins, plugin_uri);
869  lilv_node_free(plugin_uri);
870  if (!plugin) {
871  gx_print_error("lv2loader",ustring::compose(_("Cannot open LV2 plugin: %1"), plug->path));
872  return NULL;
873  }
874 
875  int num_inputs = lilv_plugin_get_num_ports_of_class(plugin, loader.lv2_AudioPort, loader.lv2_InputPort, 0);
876  int num_outputs = lilv_plugin_get_num_ports_of_class(plugin, loader.lv2_AudioPort, loader.lv2_OutputPort, 0);
877  int num_controls = lilv_plugin_get_num_ports_of_class(plugin, loader.lv2_ControlPort, 0);
878 
879  bool mono;
880  bool to_mono = false;
881  if (num_inputs == 1 && num_outputs == 1) {
882  mono = true;
883  } else if (num_inputs == 2 && num_outputs == 2) {
884  mono = false;
885  if (plug->stereo_to_mono) to_mono = true;
886  } else {
887  LilvNode *nm = lilv_plugin_get_name(plugin);
889  "lv2loader",ustring::compose(
890  _("cannot use LV2 plugin %1 with %2 inputs and %3 outputs"),
891  lilv_node_as_string(nm), num_inputs, num_outputs));
892  lilv_node_free(nm);
893  return NULL;
894  }
895  Lv2Dsp* self = new Lv2Dsp(plug, plugin, loader, mono, to_mono);
896  int desk_controls = 0;
897  for (std::vector<paradesc*>::const_iterator it = self->pd->names.begin(); it != self->pd->names.end(); ++it, ++desk_controls) ;
898  if (num_controls != desk_controls) {
899  LilvNode *nm = lilv_plugin_get_name(plugin);
901  "lv2loader",ustring::compose(
902  _("LV2 plugin %1 has changed it's ports, this may result in errors!!\nPlease go to the LADSPA/LV2 loader and select %1\nSelect 'Show Details' and press 'Restore Defaults'\nUn-load %1 (un-tick the box) and press 'save'.\nAfter this you could re-load %1 with it's new ports"),
903  lilv_node_as_string(nm)));
904  lilv_node_free(nm);
905  }
906  PluginDef& pl = *static_cast<PluginDef*>(self);
907  pl.flags |=PGNI_IS_LV2;
908  return self;
909 }
910 
911 Lv2Dsp::Lv2Dsp(const plugdesc *plug, const LilvPlugin* plugin_, const LadspaLoader& loader_, bool mono, bool to_mono)
912  : PluginDef(), loader(loader_), plugin(plugin_), name_node(lilv_plugin_get_name(plugin_)), instance(),
913  ports(new LADSPA_Data[lilv_plugin_get_num_ports(plugin_)]), name_str(), dest_str(), pd(plug), is_activated(false) {
915  id = pd->id_str.c_str();
916  category = pd->category.c_str();
917  dest_str = "LV2 ";
918  dest_str += lilv_node_as_string(name_node);
919  LilvNode *nd = lilv_plugin_get_author_name(plugin);
920  if (!nd) {
921  nd = lilv_plugin_get_project(plugin);
922  }
923  if (nd) {
924  dest_str += " by ";
925  dest_str += lilv_node_as_string(nd);
926  }
927  lilv_node_free(nd);
928  description = dest_str.c_str();
929  name = lilv_node_as_string(name_node);
930  set_shortname();
931  set_samplerate = init;
932  if (mono) {
933  mono_audio = mono_process;
934  } else {
935  if (to_mono) mono_audio = to_mono_process;
936  else stereo_audio = stereo_process;
937  }
938  activate_plugin = activate;
939  register_params = registerparam;
940  load_ui = uiloader;
941  delete_instance = del_instance;
942 }
943 
944 inline void Lv2Dsp::cleanup() {
945  if (instance) {
946  if (pd->quirks & need_activate) {
947  activate(true, this);
948  }
949  activate(false, this);
950  if (!(pd->quirks & no_cleanup)) {
951  lilv_instance_free(instance);
952  }
953  instance = 0;
954  }
955 }
956 
957 Lv2Dsp::~Lv2Dsp() {
958  cleanup();
959  delete[] ports;
960  lilv_node_free(name_node);
961 }
962 
963 int Lv2Dsp::activate(bool start, PluginDef *plugin) {
964  Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
965  if (start == self.is_activated) {
966  return 0;
967  }
968  if (!self.instance) {
969  gx_print_warning("Lv2Dsp", ustring::compose("cant activate plugin %1", self.name));
970  return 1;
971  }
972  self.is_activated = start;
973  if (start) {
974  lilv_instance_activate(self.instance);
975  } else {
976  lilv_instance_deactivate(self.instance);
977  }
978  return 0;
979 }
980 
981 void Lv2Dsp::connect(const LilvNode* tp, int i, float *v) {
982  unsigned int num_ports = lilv_plugin_get_num_ports(plugin);
983  for (unsigned int n = 0; n < num_ports; ++n) {
984  const LilvPort* port = lilv_plugin_get_port_by_index(plugin, n);
985  if (!lilv_port_is_a(plugin, port, loader.lv2_AudioPort)) {
986  continue;
987  }
988  if (lilv_port_is_a(plugin, port, tp)) {
989  if (i == 0) {
990  lilv_instance_connect_port(instance, n, v);
991  return;
992  }
993  i -= 1;
994  }
995  }
996  gx_print_error("lv2loader", _("audio port not found"));
997 }
998 
999 void Lv2Dsp::set_plugdesc(const plugdesc* pd_) {
1000  pd = pd_;
1001  id = pd->id_str.c_str();
1002  category = pd->category.c_str();
1003  set_shortname();
1004 }
1005 
1006 void Lv2Dsp::set_shortname() {
1007  if (!pd->shortname.empty()) {
1008  shortname = pd->shortname.c_str();
1009  } else {
1010  name_str = lilv_node_as_string(name_node);
1011  if (name_str.size() > 15) {
1012  name_str.erase(15);
1013  }
1014  shortname = name_str.c_str();
1015  }
1016 }
1017 
1018 
1019 void Lv2Dsp::init(unsigned int samplingFreq, PluginDef *pldef) {
1020  Lv2Dsp& self = *static_cast<Lv2Dsp*>(pldef);
1021  self.cleanup();
1022  if (samplingFreq == 0) {
1023  return;
1024  }
1025  self.instance = lilv_plugin_instantiate(self.plugin, samplingFreq, LV2Features::getInstance().gx_features);
1026  if (!self.instance) {
1027  gx_print_error("Lv2Dsp", ustring::compose("cant init plugin: %1 \n uri: %2", self.name, self.pd->path));
1028  return;
1029  }
1030  int n = 0;
1031  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
1032  lilv_instance_connect_port(self.instance, (*it)->index, &self.ports[(*it)->index]);
1033  }
1034 }
1035 
1036 inline void Lv2Dsp::mono_dry_wet(int count, float *input0, float *input1, float *output0)
1037 {
1038  double fSlow0 = (0.01 * dry_wet);
1039  double fSlow1 = (1 - fSlow0);
1040  for (int i=0; i<count; i++) {
1041  output0[i] = ((fSlow0 * (double)input1[i]) + (fSlow1 * (double)input0[i]));
1042  }
1043 }
1044 
1045 void Lv2Dsp::mono_process(int count, float *input, float *output, PluginDef *plugin) {
1046  Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
1047  assert(self.is_activated);
1048  if (self.pd->add_wet_dry) {
1049  float wet_out[count];
1050  self.connect(self.loader.lv2_InputPort, 0, input);
1051  self.connect(self.loader.lv2_OutputPort, 0, wet_out);
1052  lilv_instance_run(self.instance, count);
1053  self.mono_dry_wet(count, input, wet_out, output);
1054  } else {
1055  self.connect(self.loader.lv2_InputPort, 0, input);
1056  self.connect(self.loader.lv2_OutputPort, 0, output);
1057  lilv_instance_run(self.instance, count);
1058  }
1059 }
1060 
1061 void Lv2Dsp::up_to_stereo(int count, float *input0, float *output0, float *output1) {
1062  memcpy(output0, input0, count * sizeof(float));
1063  memcpy(output1, input0, count * sizeof(float));
1064 }
1065 
1066 void Lv2Dsp::down_to_mono(int count, float *input0, float *input1, float *output0) {
1067  for (int i=0; i<count; i++) {
1068  output0[i] = 0.5 * (input0[i] + input1[i]);
1069  }
1070 }
1071 
1072 void Lv2Dsp::to_mono_process(int count, float *input, float *output, PluginDef *plugin) {
1073  Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
1074  assert(self.is_activated);
1075  if (self.pd->add_wet_dry) {
1076  float wet_out[count];
1077  float inputs[count];
1078  float inputs1[count];
1079  float outputs[count];
1080  float outputs1[count];
1081  self.up_to_stereo(count,input,inputs, inputs1);
1082  self.connect(self.loader.lv2_InputPort, 0, inputs);
1083  self.connect(self.loader.lv2_InputPort, 1, inputs1);
1084  self.connect(self.loader.lv2_OutputPort, 0, outputs);
1085  self.connect(self.loader.lv2_OutputPort, 1, outputs1);
1086  lilv_instance_run(self.instance, count);
1087  self.down_to_mono(count,outputs,outputs1,wet_out);
1088  self.mono_dry_wet(count, input, wet_out, output);
1089  } else {
1090  float inputs[count];
1091  float inputs1[count];
1092  float outputs[count];
1093  float outputs1[count];
1094  self.up_to_stereo(count,input,inputs, inputs1);
1095  self.connect(self.loader.lv2_InputPort, 0, inputs);
1096  self.connect(self.loader.lv2_InputPort, 1, inputs1);
1097  self.connect(self.loader.lv2_OutputPort, 0, outputs);
1098  self.connect(self.loader.lv2_OutputPort, 1, outputs1);
1099  lilv_instance_run(self.instance, count);
1100  self.down_to_mono(count,outputs,outputs1,output);
1101  }
1102 }
1103 
1104 inline void Lv2Dsp::stereo_dry_wet(int count, float *input0, float *input1, float *input2, float *input3, float *output0, float *output1)
1105 {
1106  double fSlow0 = (0.01 * dry_wet);
1107  double fSlow1 = (1 - fSlow0);
1108  for (int i=0; i<count; i++) {
1109  output0[i] = ((fSlow0 * (double)input2[i]) + (fSlow1 * (double)input0[i]));
1110  output1[i] = ((fSlow0 * (double)input3[i]) + (fSlow1 * (double)input1[i]));
1111  }
1112 }
1113 
1114 void Lv2Dsp::stereo_process(int count, float *input1, float *input2, float *output1, float *output2, PluginDef *plugin) {
1115  Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
1116  assert(self.is_activated);
1117  if (self.pd->add_wet_dry) {
1118  float wet_out1[count];
1119  float wet_out2[count];
1120  self.connect(self.loader.lv2_InputPort, 0, input1);
1121  self.connect(self.loader.lv2_InputPort, 1, input2);
1122  self.connect(self.loader.lv2_OutputPort, 0, wet_out1);
1123  self.connect(self.loader.lv2_OutputPort, 1, wet_out2);
1124  lilv_instance_run(self.instance, count);
1125  self.stereo_dry_wet(count, input1, input2, wet_out1, wet_out2, output1, output2);
1126  } else {
1127  self.connect(self.loader.lv2_InputPort, 0, input1);
1128  self.connect(self.loader.lv2_InputPort, 1, input2);
1129  self.connect(self.loader.lv2_OutputPort, 0, output1);
1130  self.connect(self.loader.lv2_OutputPort, 1, output2);
1131  lilv_instance_run(self.instance, count);
1132  }
1133 }
1134 
1135 std::string Lv2Dsp::make_id(const paradesc& p) {
1136  return pd->id_str + "." + to_string(p.index);
1137 }
1138 
1139 int Lv2Dsp::registerparam(const ParamReg& reg) {
1140  Lv2Dsp& self = *static_cast<Lv2Dsp*>(reg.plugin);
1141  int n = 0;
1142  int cnt_in_row = 0;
1143  int left = 0;
1144  int num_controls = lilv_plugin_get_num_ports_of_class(self.plugin, self.loader.lv2_ControlPort, 0);
1145  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
1146  if (n>=num_controls) break;
1147  paradesc *d = *it;
1148  if (d->tp != tp_none) {
1149  left -= 1;
1150  if (left < 0) {
1151  cnt_in_row = 1;
1152  std::vector<paradesc*>::const_iterator it2 = it+1;
1153  while (it2 != self.pd->names.end() && !(*it2)->newrow) {
1154  if ((*it2)->tp != tp_none) {
1155  ++cnt_in_row;
1156  }
1157  ++it2;
1158  }
1159  left = cnt_in_row;
1160  }
1161  }
1162  const LilvPort* port = lilv_plugin_get_port_by_index(self.plugin, d->index);
1163  LilvNode* nm_node = lilv_port_get_name(self.plugin, port);
1164  const char *nm = lilv_node_as_string(nm_node);
1165  Glib::ustring snm(d->name);
1166  if (snm.empty() && d->tp != tp_none) {
1167  snm = TrimLabel(nm, cnt_in_row);
1168  }
1169  if (d->tp == tp_enum) {
1170  reg.registerEnumVar(self.make_id(*d).c_str(), snm.c_str(), "S", nm, d->values, &self.ports[d->index],
1171  d->dflt, d->low, d->up, d->step);
1172  } else {
1173  const char *tp = 0;
1174  switch (d->tp) {
1175  case tp_none: tp = "S"; break;
1176  case tp_int: tp = "S"; break;
1177  case tp_scale: tp = "S"; break;
1178  case tp_scale_log: tp = "SL"; break;
1179  case tp_toggle: tp = "B"; break;
1180  case tp_display: tp = "SO"; break;
1181  case tp_display_toggle: tp = "BO"; break;
1182  default: assert(false);
1183  }
1184  reg.registerVar(self.make_id(*d).c_str(), snm.c_str(), tp, nm, &self.ports[d->index],
1185  d->dflt, d->low, d->up, d->step);
1186  }
1187  lilv_node_free(nm_node);
1188  }
1189  self.idd = self.pd->id_str + ".dry_wet";
1190  reg.registerVar(self.idd.c_str(),"","S","dry/wet",&self.dry_wet, 100, 0, 100, 1);
1191  return 0;
1192 }
1193 
1194 int Lv2Dsp::uiloader(const UiBuilder& b, int form) {
1195  if (!(form & UI_FORM_STACK)) {
1196  return -1;
1197  }
1198  Lv2Dsp& self = *static_cast<Lv2Dsp*>(b.plugin);
1199  b.openHorizontalhideBox("");
1200  if (self.pd->master_idx >= 0) {
1201  int n = 0;
1202  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
1203  if ((n)==self.pd->master_idx) {
1204  switch ((*it)->tp) {
1205  case tp_enum:
1206  b.create_selector_no_caption(self.make_id(*self.pd->names[self.pd->master_idx]).c_str());
1207  break;
1208  default:
1209  const char *p = self.pd->master_label.c_str();
1210  if (!*p) {
1211  p = "";
1212  }
1213  b.create_master_slider(self.make_id(*self.pd->names[self.pd->master_idx]).c_str(), p);
1214  break;
1215  }
1216  }
1217  }
1218  }
1219  b.closeBox();
1220  b.openVerticalBox("");
1221  b.openHorizontalBox("");
1222  int rows = 0;
1223  int n = 0;
1224  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
1225  if ((*it)->newrow) {
1226  rows +=1;
1227  }
1228  }
1229  n = 0;
1230  int row = 0;
1231  int num_controls = lilv_plugin_get_num_ports_of_class(self.plugin, self.loader.lv2_ControlPort, 0);
1232  for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
1233  if (n>=num_controls) break;
1234  if ((*it)->newrow) {
1235  b.closeBox();
1236  if ( (rows == 1) || ( rows > 1 && row > 0 )) {
1237  b.insertSpacer();
1238  b.insertSpacer();
1239  b.insertSpacer();
1240  }
1241  b.openHorizontalBox("");
1242  row +=1;
1243  }
1244  const LilvPort* port = lilv_plugin_get_port_by_index(self.plugin, (*it)->index);
1245  LilvNode* nm_node = lilv_port_get_name(self.plugin, port);
1246  const char *p1 = lilv_node_as_string(nm_node);
1247  if (!(*it)->name.empty())
1248  p1 = (*it)->name.c_str();
1249  Glib::ustring trim = TrimEffectLabel(p1, 4);
1250  const char *p = trim.c_str();
1251  std::string id = self.make_id(**it);
1252  if (num_controls<30) {
1253  if ((row == 1 && rows == 1 ) || (row >1 && rows >1 )) {
1255  }
1256  } else if (num_controls<35) {
1257  if ((row == 2 && rows == 2 ) || (row >2 && rows >2 )) {
1259  }
1260  } else {
1261  if ((row == 3 && rows == 3 ) || (row >3 && rows >3 )) {
1263  }
1264  }
1265  switch ((*it)->tp) {
1266  case tp_scale:
1267  case tp_scale_log:
1268  if (!(*it)->has_caption) {
1269  p = "";
1270  }
1271  b.create_small_rackknobr(id.c_str(), p);
1272  break;
1273  case tp_toggle:
1274  if ((*it)->has_caption) {
1275  b.create_switch("switch_mid",id.c_str(), p);
1276  } else {
1277  b.create_switch_no_caption("switchit",id.c_str());
1278  }
1279  break;
1280  case tp_display:
1281  if (!(*it)->has_caption) {
1282  p = "";
1283  }
1284  b.create_port_display(id.c_str(), p);
1285  break;
1286  case tp_display_toggle:
1287  if ((*it)->has_caption) {
1288  b.create_switch("led",id.c_str(), p);
1289  } else {
1290  b.create_switch_no_caption("led",id.c_str());
1291  }
1292  break;
1293  case tp_int:
1294  if (!(*it)->has_caption) {
1295  p = "";
1296  }
1297  if (((*it)->up - (*it)->low)<200) {
1298  b.create_small_rackknob(id.c_str(), p);
1299  } else {
1300  b.create_spin_value(id.c_str(), p);
1301  }
1302  break;
1303  case tp_enum:
1304  if ((*it)->has_caption) {
1305  b.create_selector(id.c_str(), p);
1306  } else {
1307  b.create_selector_no_caption(id.c_str());
1308  }
1309  break;
1310  case tp_none:
1311  break;
1312  default:
1313  assert(false);
1314  }
1315  lilv_node_free(nm_node);
1316  }
1317  if (self.pd->add_wet_dry) {
1318  b.create_small_rackknobr(self.idd.c_str(), "dry/wet");
1319  }
1320  b.closeBox();
1321  b.closeBox();
1322  return 0;
1323 }
1324 
1325 void Lv2Dsp::del_instance(PluginDef *plugin) {
1326  delete static_cast<Lv2Dsp*>(plugin);
1327 }
1328 
1329 
1330 /****************************************************************
1331  ** class LadspaLoader
1332  */
1333 
1335  if (p->quirks & is_lv2) {
1336  return Lv2Dsp::create(p, *this);
1337  } else {
1338  return LadspaDsp::create(p);
1339  }
1340 }
1341 
1343  : options(options_),
1344  plugins(),
1345  world(lilv_world_new()),
1346  lv2_plugins(),
1347  lv2_AudioPort(lilv_new_uri(world, LV2_CORE__AudioPort)),
1348  lv2_ControlPort(lilv_new_uri(world, LV2_CORE__ControlPort)),
1349  lv2_InputPort(lilv_new_uri(world, LV2_CORE__InputPort)),
1350  lv2_OutputPort(lilv_new_uri(world, LV2_CORE__OutputPort)) {
1351  lilv_world_load_all(world);
1352  lv2_plugins = lilv_world_get_all_plugins(world);
1353  load(plugins);
1354 }
1355 
1357  for (pluginarray::iterator i = plugins.begin(); i != plugins.end(); ++i) {
1358  delete *i;
1359  }
1360  lilv_node_free(lv2_OutputPort);
1361  lilv_node_free(lv2_InputPort);
1362  lilv_node_free(lv2_ControlPort);
1363  lilv_node_free(lv2_AudioPort);
1364  lilv_world_free(world);
1365 }
1366 
1368  try {
1369  read_module_list(ml);
1370  } catch (JsonException &e) {
1371  gx_print_error("ladspaloader",ustring::compose(_("Exception in LADSPA list reader: %1"), e.what()));
1372  return false;
1373  }
1374  return true;
1375 }
1376 
1378  for (pluginarray::iterator i = plugins.begin(); i != plugins.end(); ++i) {
1379  delete *i;
1380  }
1381  plugins = new_plugins;
1382 }
1383 
1385  //for (pluginarray::iterator i = plugins.begin(); i != plugins.end(); ++i) {
1386  //delete *i;
1387  //}
1388  plugins = new_plugins;
1389 }
1390 
1391 LadspaLoader::pluginarray::iterator LadspaLoader::find(plugdesc *desc) {
1392  for (pluginarray::iterator i = begin(); i != end(); ++i) {
1393  if (desc->quirks & is_lv2) {
1394  if ((*i)->path == desc->path) {
1395  return i;
1396  }
1397  } else {
1398  if ((*i)->UniqueID == desc->UniqueID) {
1399  return i;
1400  }
1401  }
1402  }
1403  return end();
1404 }
1405 
1407  if (pdesc->quirks & is_lv2) {
1408  static_cast<Lv2Dsp*>(pdef)->set_plugdesc(pdesc);
1409  } else {
1410  static_cast<LadspaDsp*>(pdef)->set_plugdesc(pdesc);
1411  }
1412 }
1413 
1415  for (value_pair *p = values; p->value_id; ++p) {
1416  g_free(const_cast<char*>(p->value_id));
1417  }
1418  delete[] values;
1419 }
1420 
1421 void paradesc::set_valuelist(const std::vector<std::string>& v) {
1422  values = new value_pair[v.size()+1];
1423  int n = 0;
1424  for (std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i, ++n) {
1425  const char *p = g_strdup(i->c_str());
1426  values[n].value_id = p;
1427  values[n].value_label = p;
1428  }
1429  values[n].value_id = 0;
1430  values[n].value_label = 0;
1431 }
1432 
1433 void LadspaLoader::read_module_config(const std::string& filename, plugdesc *p) {
1434  std::ifstream ifs(filename.c_str());
1435  if (ifs.fail()) {
1436  gx_print_error("ladspaloader", ustring::compose(_("can't open %1"), filename));
1437  return;
1438  }
1439  gx_system::JsonParser jp(&ifs);
1442  jp.current_value_int(); // int version
1444  p->shortname = jp.current_value();
1446  p->category = jp.current_value();
1448  p->master_idx = jp.current_value_int();
1450  p->master_label = jp.current_value();
1452  p->quirks = jp.current_value_int();
1454  p->add_wet_dry= jp.current_value_int();
1455  // new monobox for stereo plugs
1459  }
1461  while (jp.peek() != gx_system::JsonParser::end_array) {
1462  paradesc *para = new paradesc;
1465  para->index = jp.current_value_int();
1466  jp.skip_object(); // meta data
1468  para->name = jp.current_value();
1471  para->dflt = jp.current_value_float();
1473  para->low = jp.current_value_float();
1475  para->up = jp.current_value_float();
1477  para->step = jp.current_value_float();
1479  para->tp = static_cast<widget_type>(jp.current_value_int()); //FIXME (check valid)
1481  para->newrow = jp.current_value_int();
1483  para->has_caption = jp.current_value_int();
1485  std::vector<std::string> v;
1486  while (jp.peek() != gx_system::JsonParser::end_array) {
1488  v.push_back(jp.current_value());
1489  }
1491  para->set_valuelist(v);
1493  p->names.push_back(para);
1494  }
1496  jp.close();
1497  ifs.close();
1498 }
1499 
1500 void LadspaLoader::read_module_list(pluginarray& ml) {
1501  std::ifstream ifs(options.get_user_filepath("ladspa_defs.js").c_str());
1502  if (ifs.fail()) {
1503  return;
1504  }
1505  gx_system::JsonParser jp(&ifs);
1507  while (jp.peek() != gx_system::JsonParser::end_array) {
1510  plugdesc *p = new plugdesc;
1511  p->path = jp.current_value();
1513  int idx = jp.current_value_int();
1514  if (idx < 0) {
1515  p->quirks |= is_lv2;
1516  }
1517  p->index = idx;
1519  p->UniqueID = jp.current_value_int();
1521  p->Label = jp.current_value();
1523  std::string s;
1524  if (idx < 0) {
1525  s = gx_system::encode_filename(p->path) + ".js";
1526  } else {
1527  s = get_ladspa_filename(p->UniqueID);
1528  }
1529  std::string fname = options.get_plugin_filepath(s);
1530  if (access(fname.c_str(), F_OK) != 0) {
1531  fname = options.get_factory_filepath(s);
1532  if (access(fname.c_str(), F_OK) != 0) {
1533  fname = "";
1534  }
1535  }
1536  if (!fname.empty()) {
1537  try {
1538  read_module_config(fname, p);
1539  } catch (JsonException &e) {
1540  gx_print_error("ladspaloader",ustring::compose(_("read error in file %1: %2"), s, e.what()));
1541  }
1542  }
1543  if (p->quirks & is_lv2) {
1544  p->id_str = "lv2_" + gx_system::encode_filename(p->path);
1545  } else {
1546  p->id_str = "ladspa_" + to_string(p->UniqueID);
1547  }
1548  ml.push_back(p);
1549  }
1550  jp.close();
1551  ifs.close();
1552 }
1553 
1554 } // namespace gx_engine
static LV2_URID_Unmap gx_urid_unmap
void write_kv(const char *key, float v)
Definition: gx_json.h:81
CmdConnection::msg_type start
Definition: jsonrpc.cpp:257
void begin_array(bool nl=false)
Definition: gx_json.cpp:184
void * LADSPA_Handle
Definition: ladspa.h:363
pluginarray::iterator end()
void(* insertSpacer)()
Definition: gx_plugin.h:78
std::string get_factory_filepath(const std::string &basename) const
Definition: gx_system.h:467
void(* cleanup)(LADSPA_Handle Instance)
Definition: ladspa.h:558
PluginDef * plugin
Definition: gx_plugin.h:64
void end_array(bool nl=false)
Definition: gx_json.cpp:192
#define LADSPA_PORT_INPUT
Definition: ladspa.h:155
void writeJSON(gx_system::JsonWriter &jw)
int(* uiloader)(const UiBuilder &builder, int format)
Definition: gx_plugin.h:158
const char * value_id
Definition: gx_plugin.h:118
void set_plugins(pluginarray &new_plugins)
PluginDef * plugin
Definition: gx_plugin.h:123
void set_plugdesc(const plugdesc *pd_)
LadspaLoader(const gx_system::CmdlineOptions &options)
virtual void close()
Definition: gx_json.cpp:277
const char * name
Definition: gx_plugin.h:188
std::vector< plugdesc * > pluginarray
void(* deactivate)(LADSPA_Handle Instance)
Definition: ladspa.h:549
void set_plugdesc(const plugdesc *pd_)
const char * Name
Definition: ladspa.h:393
#define UI_LABEL_INVERSE
Definition: gx_plugin.h:45
float *(* registerVar)(const char *id, const char *name, const char *tp, const char *tooltip, float *var, float val, float low, float up, float step)
Definition: gx_plugin.h:124
void(* create_switch_no_caption)(const char *sw_type, const char *id)
Definition: gx_plugin.h:89
void(* registerEnumVar)(const char *id, const char *name, const char *tp, const char *tooltip, const value_pair *values, float *var, float val, float low, float up, float step)
Definition: gx_plugin.h:132
const char * description
Definition: gx_plugin.h:191
void(* closeBox)()
Definition: gx_plugin.h:77
pluginarray::iterator find(plugdesc *desc)
void write_key(const char *p, bool nl=false)
Definition: gx_json.cpp:200
unsigned long UniqueID
Definition: ladspa.h:379
const char * shortname
Definition: gx_plugin.h:193
bool load(pluginarray &p)
const char * category
Definition: gx_plugin.h:192
void readJSON(gx_system::JsonParser &jp)
const char * Label
Definition: ladspa.h:386
void(* activate)(LADSPA_Handle Instance)
Definition: ladspa.h:489
deletefunc delete_instance
Definition: gx_plugin.h:206
static LadspaDsp * create(const plugdesc *plug)
static Lv2Dsp * create(const plugdesc *plug, const LadspaLoader &loader)
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
void(* create_selector)(const char *id, const char *label)
Definition: gx_plugin.h:95
PluginDef * create(unsigned int idx)
#define PLUGINDEF_VERSION
Definition: gx_plugin.h:181
void(* openHorizontalBox)(const char *label)
Definition: gx_plugin.h:71
registerfunc register_params
Definition: gx_plugin.h:202
float LADSPA_Data
Definition: ladspa.h:84
void(* create_port_display)(const char *id, const char *label)
Definition: gx_plugin.h:92
std::string get_plugin_filepath(const std::string &basename) const
Definition: gx_system.h:466
void begin_object(bool nl=false)
Definition: gx_json.cpp:168
void(* create_small_rackknobr)(const char *id, const char *label)
Definition: gx_plugin.h:98
int flags
Definition: gx_plugin.h:185
static LV2_URID_Map gx_urid_map
unsigned long PortCount
Definition: ladspa.h:406
std::string to_string(const T &t)
Definition: gx_system.h:529
virtual const char * what() const
Definition: gx_json.h:46
void(* create_small_rackknob)(const char *id, const char *label)
Definition: gx_plugin.h:86
#define UI_FORM_STACK
Definition: gx_plugin.h:60
std::vector< paradesc * > names
void gx_print_warning(const char *, const std::string &)
Definition: gx_logging.cpp:161
void(* openHorizontalhideBox)(const char *label)
Definition: gx_plugin.h:72
#define LADSPA_IS_PORT_AUDIO(x)
Definition: ladspa.h:171
activatefunc activate_plugin
Definition: gx_plugin.h:201
static LV2Features & getInstance()
void(* create_spin_value)(const char *id, const char *label)
Definition: gx_plugin.h:91
process_stereo_audio stereo_audio
Definition: gx_plugin.h:198
std::string get_user_filepath(const std::string &basename) const
Definition: gx_system.h:371
const char * Maker
Definition: ladspa.h:397
void update_instance(PluginDef *pdef, plugdesc *pdesc)
#define LADSPA_IS_PORT_INPUT(x)
Definition: ladspa.h:168
pluginarray::iterator begin()
string current_value() const
Definition: gx_json.h:143
void readJSON(gx_system::JsonParser &jp)
void(* set_next_flags)(int flags)
Definition: gx_plugin.h:79
inifunc set_samplerate
Definition: gx_plugin.h:200
#define LADSPA_PORT_OUTPUT
Definition: ladspa.h:158
void writeJSON(gx_system::JsonWriter &jw)
process_mono_audio mono_audio
Definition: gx_plugin.h:197
void set_valuelist(const std::vector< std::string > &v)
static std::string get_ladspa_filename(unsigned long uid)
const LADSPA_Descriptor *(* LADSPA_Descriptor_Function)(unsigned long Index)
Definition: ladspa.h:593
float current_value_float()
Definition: gx_json.h:146
token next(token expect=no_token)
Definition: gx_json.cpp:496
void write(float v, bool nl=false)
Definition: gx_json.cpp:116
int version
Definition: gx_plugin.h:184
const LADSPA_Descriptor * ladspa_descriptor(unsigned long Index)
void(* create_switch)(const char *sw_type, const char *id, const char *label)
Definition: gx_plugin.h:94
uiloader load_ui
Definition: gx_plugin.h:203
void(* connect_port)(LADSPA_Handle Instance, unsigned long Port, LADSPA_Data *DataLocation)
Definition: ladspa.h:466
static LV2_Feature * gx_features[]
void change_plugins(pluginarray &new_plugins)
void(* create_master_slider)(const char *id, const char *label)
Definition: gx_plugin.h:84
void end_object(bool nl=false)
Definition: gx_json.cpp:176
void(* create_selector_no_caption)(const char *id)
Definition: gx_plugin.h:88
void(* openVerticalBox)(const char *label)
Definition: gx_plugin.h:68
const LADSPA_PortDescriptor * PortDescriptors
Definition: ladspa.h:410
std::string encode_filename(const std::string &s)
Definition: gx_system.cpp:1013