Diff of /trunk/src/gx_head/engine/ladspaplugin.cpp [c0a1dc] .. [935f5c]  Maximize  Restore

  Switch to side-by-side view

--- a/trunk/src/gx_head/engine/ladspaplugin.cpp
+++ b/trunk/src/gx_head/engine/ladspaplugin.cpp
@@ -600,15 +600,402 @@
 
 
 /****************************************************************
+ ** class Lv2Dsp
+ */
+
+class Lv2Dsp: public PluginDef {
+private:
+    static void init(unsigned int samplingFreq, PluginDef *plugin);
+    static void mono_process(int count, float *input, float *output, PluginDef *plugin);
+    static void stereo_process(int count, float *input1, float *input2, float *output1, float *output2, PluginDef *plugin);
+    static int activate(bool start, PluginDef *plugin);
+    static int registerparam(const ParamReg& reg);
+    static int uiloader(const UiBuilder& builder, int form);
+    static void del_instance(PluginDef *plugin);
+    //
+    const LadspaLoader& loader;
+    const LilvPlugin* plugin;
+    LilvNode* name_node;
+    LilvInstance* instance;
+    LADSPA_Data *ports;
+    Glib::ustring name_str;
+    const plugdesc *pd;
+    bool is_activated;
+    void connect(const LilvNode* tp, int i, float *v);
+    inline void cleanup();
+    void set_shortname();
+    float dry_wet;
+    std::string idd;
+    inline void mono_dry_wet(int count, float *input0, float *input1, float *output0);
+    inline void stereo_dry_wet(int count, float *input0, float *input1, float *input2, float *input3, float *output0, float *output1);
+    std::string make_id(const paradesc& p);
+    Lv2Dsp(const plugdesc *plug, const LilvPlugin* plugin_, const LadspaLoader& loader_, bool mono);
+    ~Lv2Dsp();
+public:
+    static Lv2Dsp *create(const plugdesc *plug, const LadspaLoader& loader);
+    void set_plugdesc(const plugdesc* pd_);
+};
+
+Lv2Dsp *Lv2Dsp::create(const plugdesc *plug, const LadspaLoader& loader) {
+    LilvNode* plugin_uri = lilv_new_uri(loader.world, plug->path.c_str());
+    const LilvPlugin* plugin = lilv_plugins_get_by_uri(loader.lv2_plugins, plugin_uri);
+    lilv_node_free(plugin_uri);
+    if (!plugin) {
+	gx_print_error("lv2loader",ustring::compose(_("Cannot open LV2 plugin: %1"), plug->path));
+	return NULL;
+    }
+    int num_inputs = lilv_plugin_get_num_ports_of_class(plugin, loader.lv2_AudioPort, loader.lv2_InputPort, 0);
+    int num_outputs = lilv_plugin_get_num_ports_of_class(plugin, loader.lv2_AudioPort, loader.lv2_OutputPort, 0);
+    bool mono;
+    if (num_inputs == 1 && num_outputs == 1) {
+	mono = true;
+    } else if (num_inputs == 2 && num_outputs == 2) {
+	mono = false;
+    } else {
+	LilvNode *nm = lilv_plugin_get_name(plugin);
+	gx_print_error(
+	    "lv2loader",ustring::compose(
+		_("cannot use LV2 plugin %1 with %2 inputs and %3 outputs"),
+		lilv_node_as_string(nm), num_inputs, num_outputs));
+	lilv_node_free(nm);
+	return NULL;
+    }
+    return new Lv2Dsp(plug, plugin, loader, mono);
+}
+
+Lv2Dsp::Lv2Dsp(const plugdesc *plug, const LilvPlugin* plugin_, const LadspaLoader& loader_, bool mono)
+    : PluginDef(), loader(loader_), plugin(plugin_), name_node(lilv_plugin_get_name(plugin_)), instance(),
+      ports(new LADSPA_Data[lilv_plugin_get_num_ports(plugin_)]), name_str(), pd(plug), is_activated(false) {
+    version = PLUGINDEF_VERSION;
+    id = pd->id_str.c_str();
+    category = pd->category.c_str();
+    description = lilv_node_as_string(name_node);
+    name = lilv_node_as_string(name_node);
+    set_shortname();
+    set_samplerate = init;
+    if (mono) {
+	mono_audio = mono_process;
+    } else {
+	stereo_audio = stereo_process;
+    }
+    activate_plugin = activate;
+    register_params = registerparam;
+    load_ui = uiloader;
+    delete_instance = del_instance;
+}
+
+inline void Lv2Dsp::cleanup() {
+    if (instance) {
+	if (pd->quirks & need_activate) {
+	    activate(true, this);
+	}
+	activate(false, this);
+	if (!(pd->quirks & no_cleanup)) {
+	    lilv_instance_free(instance);
+	}
+	instance = 0;
+    }
+}
+
+Lv2Dsp::~Lv2Dsp() {
+    cleanup();
+    delete[] ports;
+    lilv_node_free(name_node);
+}
+
+int Lv2Dsp::activate(bool start, PluginDef *plugin) {
+    Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
+    if (start == self.is_activated) {
+	return 0;
+    }
+    self.is_activated = start;
+    if (start) {
+	lilv_instance_activate(self.instance);
+    } else {
+	lilv_instance_deactivate(self.instance);
+    }
+    return 0;
+}
+
+void Lv2Dsp::connect(const LilvNode* tp, int i, float *v) {
+    unsigned int num_ports = lilv_plugin_get_num_ports(plugin);
+    for (unsigned int n = 0; n < num_ports; ++n) {
+	const LilvPort* port = lilv_plugin_get_port_by_index(plugin, n);
+	if (!lilv_port_is_a(plugin, port, loader.lv2_AudioPort)) {
+	    continue;
+	}
+	if (lilv_port_is_a(plugin, port, tp)) {
+	    if (i == 0) {
+		lilv_instance_connect_port(instance, n, v);
+		return;
+	    }
+	    i -= 1;
+	}
+    }
+    gx_print_error("lv2loader", _("audio port not found"));
+}
+
+void Lv2Dsp::set_plugdesc(const plugdesc* pd_) {
+    pd = pd_;
+    id = pd->id_str.c_str();
+    category = pd->category.c_str();
+    set_shortname();
+}
+
+void Lv2Dsp::set_shortname() {
+    if (!pd->shortname.empty()) {
+	shortname = pd->shortname.c_str();
+    } else {
+	name_str = lilv_node_as_string(name_node);
+	if (name_str.size() > 15) {
+	    name_str.erase(15);
+	}
+	shortname = name_str.c_str();
+    }
+}
+
+void Lv2Dsp::init(unsigned int samplingFreq, PluginDef *pldef) {
+    Lv2Dsp& self = *static_cast<Lv2Dsp*>(pldef);
+    self.cleanup();
+    if (samplingFreq == 0) {
+	return;
+    }
+    self.instance = lilv_plugin_instantiate(self.plugin, samplingFreq, 0);
+    int n = 0;
+    for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
+	lilv_instance_connect_port(self.instance, (*it)->index, &self.ports[(*it)->index]);
+    }
+}
+
+inline void Lv2Dsp::mono_dry_wet(int count, float *input0, float *input1, float *output0)
+{
+	double 	fSlow0 = (0.01 * dry_wet);
+	double 	fSlow1 = (1 - fSlow0);
+	for (int i=0; i<count; i++) {
+		output0[i] = ((fSlow0 * (double)input1[i]) + (fSlow1 * (double)input0[i]));
+	}
+}
+
+void Lv2Dsp::mono_process(int count, float *input, float *output, PluginDef *plugin) {
+    Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
+    assert(self.is_activated);
+    if (self.pd->add_wet_dry) {
+	float wet_out[count];
+	self.connect(self.loader.lv2_InputPort, 0, input);
+	self.connect(self.loader.lv2_OutputPort, 0, wet_out);
+	lilv_instance_run(self.instance, count);
+	self.mono_dry_wet(count, input, wet_out, output);
+    } else {
+	self.connect(self.loader.lv2_InputPort, 0, input);
+	self.connect(self.loader.lv2_OutputPort, 0, output);
+	lilv_instance_run(self.instance, count);
+    }
+}
+
+inline void Lv2Dsp::stereo_dry_wet(int count, float *input0, float *input1, float *input2, float *input3, float *output0, float *output1)
+{
+	double 	fSlow0 = (0.01 * dry_wet);
+	double 	fSlow1 = (1 - fSlow0);
+	for (int i=0; i<count; i++) {
+		output0[i] = ((fSlow0 * (double)input2[i]) + (fSlow1 * (double)input0[i]));
+		output1[i] = ((fSlow0 * (double)input3[i]) + (fSlow1 * (double)input1[i]));
+	}
+}
+
+void Lv2Dsp::stereo_process(int count, float *input1, float *input2, float *output1, float *output2, PluginDef *plugin) {
+    Lv2Dsp& self = *static_cast<Lv2Dsp*>(plugin);
+    assert(self.is_activated);
+    if (self.pd->add_wet_dry) {
+	float wet_out1[count];
+	float wet_out2[count];
+	self.connect(self.loader.lv2_InputPort, 0, input1);
+	self.connect(self.loader.lv2_InputPort, 1, input2);
+	self.connect(self.loader.lv2_OutputPort, 0, wet_out1);
+	self.connect(self.loader.lv2_OutputPort, 1, wet_out2);
+	lilv_instance_run(self.instance, count);
+	self.stereo_dry_wet(count, input1, input2, wet_out1, wet_out2, output1, output2);
+    } else {
+	self.connect(self.loader.lv2_InputPort, 0, input1);
+	self.connect(self.loader.lv2_InputPort, 1, input2);
+	self.connect(self.loader.lv2_OutputPort, 0, output1);
+	self.connect(self.loader.lv2_OutputPort, 1, output2);
+	lilv_instance_run(self.instance, count);
+    }
+}
+
+std::string Lv2Dsp::make_id(const paradesc& p) {
+    return pd->id_str + "." + to_string(p.index);
+}
+
+int Lv2Dsp::registerparam(const ParamReg& reg) {
+    Lv2Dsp& self = *static_cast<Lv2Dsp*>(reg.plugin);
+    int n = 0;
+    int cnt_in_row = 0;
+    int left = 0;
+    for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
+	paradesc *d = *it;
+	if (d->tp != tp_none) {
+	    left -= 1;
+	    if (left < 0) {
+		cnt_in_row = 1;
+		std::vector<paradesc*>::const_iterator it2 = it+1;
+		while (it2 != self.pd->names.end() && !(*it2)->newrow) {
+		    if ((*it2)->tp != tp_none) {
+			++cnt_in_row;
+		    }
+		    ++it2;
+		}
+		left = cnt_in_row;
+	    }
+	}
+	const LilvPort* port = lilv_plugin_get_port_by_index(self.plugin, d->index);
+	LilvNode* nm_node = lilv_port_get_name(self.plugin, port);
+	const char *nm = lilv_node_as_string(nm_node);
+	Glib::ustring snm(d->name);
+	if (snm.empty() && d->tp != tp_none) {
+	    snm = TrimLabel(nm, cnt_in_row);
+	}
+	if (d->tp == tp_enum) {
+	    reg.registerEnumVar(self.make_id(*d).c_str(), snm.c_str(), "S", nm, d->values, &self.ports[d->index],
+				d->dflt, d->low, d->up, d->step);
+	} else {
+	    const char *tp = 0;
+	    switch (d->tp) {
+	    case tp_none:           tp = "S";  break;
+	    case tp_int:            tp = "S";  break;
+	    case tp_scale:          tp = "S";  break;
+	    case tp_scale_log:      tp = "SL"; break;
+	    case tp_toggle:         tp = "B";  break;
+	    case tp_display:        tp = "SO"; break;
+	    case tp_display_toggle: tp = "BO"; break;
+	    default: assert(false);
+	    }
+	    reg.registerVar(self.make_id(*d).c_str(), snm.c_str(), tp, nm, &self.ports[d->index],
+			    d->dflt, d->low, d->up, d->step);
+	}
+	lilv_node_free(nm_node);
+    }
+    self.idd = self.pd->id_str + ".dry_wet";
+    reg.registerVar(self.idd.c_str(),"","S","dry/wet",&self.dry_wet, 100, 0, 100, 1);
+    return 0;
+}
+
+int Lv2Dsp::uiloader(const UiBuilder& b, int form) {
+    if (!(form & UI_FORM_STACK)) {
+	return -1;
+    }
+    Lv2Dsp& self = *static_cast<Lv2Dsp*>(b.plugin);
+    b.openHorizontalhideBox("");
+    if (self.pd->master_idx >= 0) {
+	int n = 0;
+	for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
+	    if ((n)==self.pd->master_idx) {
+		switch ((*it)->tp) {
+		case tp_enum:
+		    b.create_selector_no_caption(self.make_id(*self.pd->names[self.pd->master_idx]).c_str());
+		    break;
+		default:
+		    const char *p = self.pd->master_label.c_str();
+		    if (!*p) {
+			p = 0;
+		    }
+		    b.create_master_slider(self.make_id(*self.pd->names[self.pd->master_idx]).c_str(), p);
+		    break;
+		}
+	    }
+	}
+    }
+    b.closeBox();
+    b.openVerticalBox("");
+    b.openHorizontalBox("");
+    int n = 0;
+    for (std::vector<paradesc*>::const_iterator it = self.pd->names.begin(); it != self.pd->names.end(); ++it, ++n) {
+	if ((*it)->newrow) {
+	    b.closeBox();
+	    b.openHorizontalBox("");
+	}
+	const char *p = 0;
+	std::string id = self.make_id(**it);
+	switch ((*it)->tp) {
+	case tp_scale:
+	case tp_scale_log:
+	    if (!(*it)->has_caption) {
+		p = "";
+	    }
+	    b.create_small_rackknob(id.c_str(), p);
+	    break;
+	case tp_toggle:
+	    if ((*it)->has_caption) {
+		b.create_switch("switch",id.c_str(), 0);
+	    } else {
+		b.create_switch_no_caption("switchit",id.c_str());
+	    }
+	    break;
+	case tp_display:
+	    if (!(*it)->has_caption) {
+		p = "";
+	    }
+	    b.create_port_display(id.c_str(), p);
+	    break;
+	case tp_display_toggle:
+	    if ((*it)->has_caption) {
+		b.create_switch("led",id.c_str(), 0);
+	    } else {
+		b.create_switch_no_caption("led",id.c_str());
+	    }
+	    break;
+	case tp_int:
+	    b.create_spin_value(id.c_str(), 0);
+	    break;
+	case tp_enum:
+	    if ((*it)->has_caption) {
+		b.create_selector(id.c_str(), 0);
+	    } else {
+		b.create_selector_no_caption(id.c_str());
+	    }
+	    break;
+	case tp_none:
+	    break;
+	default:
+	    assert(false);
+	}
+    }
+    if (self.pd->add_wet_dry) {
+	b.create_small_rackknob(self.idd.c_str(), "dry/wet");
+    }
+    b.closeBox();
+    b.closeBox();
+    return 0;
+}
+
+void Lv2Dsp::del_instance(PluginDef *plugin) {
+    delete static_cast<Lv2Dsp*>(plugin);
+}
+
+
+/****************************************************************
  ** class LadspaLoader
  */
 
 PluginDef *LadspaLoader::create(const plugdesc *p) {
-    return LadspaDsp::create(p);
+    if (p->quirks & is_lv2) {
+	return Lv2Dsp::create(p, *this);
+    } else {
+	return LadspaDsp::create(p);
+    }
 }
 
 LadspaLoader::LadspaLoader(const gx_system::CmdlineOptions& options_)
-    : options(options_), plugins() {
+    : options(options_),
+      plugins(),
+      world(lilv_world_new()),
+      lv2_plugins(),
+      lv2_AudioPort(lilv_new_uri(world, LV2_CORE__AudioPort)),
+      lv2_ControlPort(lilv_new_uri(world, LV2_CORE__ControlPort)),
+      lv2_InputPort(lilv_new_uri(world, LV2_CORE__InputPort)),
+      lv2_OutputPort(lilv_new_uri(world, LV2_CORE__OutputPort)) {
+    lilv_world_load_all(world);
+    lv2_plugins = lilv_world_get_all_plugins(world);
     load(plugins);
 }
 
@@ -616,6 +1003,11 @@
     for (pluginarray::iterator i = plugins.begin(); i != plugins.end(); ++i) {
 	delete *i;
     }
+    lilv_node_free(lv2_OutputPort);
+    lilv_node_free(lv2_InputPort);
+    lilv_node_free(lv2_ControlPort);
+    lilv_node_free(lv2_AudioPort);
+    lilv_world_free(world);
 }
 
 bool LadspaLoader::load(pluginarray& ml) {
@@ -635,17 +1027,27 @@
     plugins = new_plugins;
 }
 
-LadspaLoader::pluginarray::iterator LadspaLoader::find(unsigned long uniqueid) {
+LadspaLoader::pluginarray::iterator LadspaLoader::find(plugdesc *desc) {
     for (pluginarray::iterator i = begin(); i != end(); ++i) {
-	if ((*i)->UniqueID == uniqueid) {
-	    return i;
+	if (desc->quirks & is_lv2) {
+	    if ((*i)->path == desc->path) {
+		return i;
+	    }
+	} else {
+	    if ((*i)->UniqueID == desc->UniqueID) {
+		return i;
+	    }
 	}
     }
     return end();
 }
 
 void LadspaLoader::update_instance(PluginDef *pdef, plugdesc *pdesc) {
-    static_cast<LadspaDsp*>(pdef)->set_plugdesc(pdesc);
+    if (pdesc->quirks & is_lv2) {
+	static_cast<Lv2Dsp*>(pdef)->set_plugdesc(pdesc);
+    } else {
+	static_cast<LadspaDsp*>(pdef)->set_plugdesc(pdesc);
+    }
 }
 
 paradesc::~paradesc() {
@@ -742,13 +1144,22 @@
 	plugdesc *p = new plugdesc;
 	p->path = jp.current_value();
 	jp.next(gx_system::JsonParser::value_number);
-	p->index = jp.current_value_int();
+	int idx = jp.current_value_int();
+	if (idx < 0) {
+	    p->quirks |= is_lv2;
+	}
+	p->index = idx;
 	jp.next(gx_system::JsonParser::value_number);
 	p->UniqueID = jp.current_value_int();
 	jp.next(gx_system::JsonParser::value_string);
 	p->Label = jp.current_value();
 	jp.next(gx_system::JsonParser::end_array);
-	std::string s = get_ladspa_filename(p->UniqueID);
+	std::string s;
+	if (idx < 0) {
+	    s = gx_system::encode_filename(p->path) + ".js";
+	} else {
+	    s = get_ladspa_filename(p->UniqueID);
+	}
 	std::string fname = options.get_plugin_filepath(s);
 	if (access(fname.c_str(), F_OK) != 0) {
 	    fname = options.get_factory_filepath(s);
@@ -763,8 +1174,11 @@
 		gx_print_error("ladspaloader",ustring::compose(_("read error in file %1: %2"), s, e.what()));
 	    }
 	}
-	p->id_str = "ladspa_";
-	p->id_str += to_string(p->UniqueID);
+	if (p->quirks & is_lv2) {
+	    p->id_str = "lv2_" + gx_system::encode_filename(p->path);
+	} else {
+	    p->id_str = "ladspa_" + to_string(p->UniqueID);
+	}
 	ml.push_back(p);
     }
     jp.close();

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks