CALF: revert upstream commit 460642bfae534679b4094e6887714828c90d8172

Upstream commit 460642bfae534679b4094e6887714828c90d8172 removes LADSPA
support from CALF which definitely is not desired for LMMS. Therefore
simply revert it in our sources.
This commit is contained in:
Tobias Doerffel
2012-02-02 21:59:03 +01:00
parent c1db55c56a
commit 88d0c59903
2 changed files with 599 additions and 0 deletions

View File

@@ -0,0 +1,130 @@
/* Calf DSP Library
* API wrappers for LADSPA/DSSI
*
* Copyright (C) 2007-2008 Krzysztof Foltman
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CALF_LADSPA_WRAP_H
#define __CALF_LADSPA_WRAP_H
#if USE_LADSPA
#include <string.h>
#include <ladspa.h>
#if USE_DSSI
#include <dssi.h>
#endif
#include "giface.h"
#include "preset.h"
namespace calf_plugins {
struct ladspa_plugin_metadata_set;
/// A template implementing plugin_ctl_iface for a given plugin
struct ladspa_instance: public plugin_ctl_iface
{
audio_module_iface *module;
const plugin_metadata_iface *metadata;
ladspa_plugin_metadata_set *ladspa;
bool activate_flag;
float **ins, **outs, **params;
#if USE_DSSI
dssi_feedback_sender *feedback_sender;
#endif
ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate);
virtual const line_graph_iface *get_line_graph_iface() const { return module->get_line_graph_iface(); }
virtual float get_param_value(int param_no);
virtual void set_param_value(int param_no, float value);
virtual bool activate_preset(int bank, int program);
virtual char *configure(const char *key, const char *value);
virtual float get_level(unsigned int port) { return 0.f; }
virtual void execute(int cmd_no) {
module->execute(cmd_no);
}
virtual void send_configures(send_configure_iface *sci) {
module->send_configures(sci);
}
virtual int send_status_updates(send_updates_iface *sui, int last_serial) { return module->send_status_updates(sui, last_serial); }
void run(unsigned long SampleCount);
#if USE_DSSI
/// Utility function: handle MIDI event (only handles a subset in this version)
void process_dssi_event(snd_seq_event_t &event);
void run_synth(unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount);
#endif
virtual const plugin_metadata_iface *get_metadata_iface() const
{
return metadata;
}
};
/// Set of metadata produced by LADSPA wrapper for LADSPA-related purposes
struct ladspa_plugin_metadata_set
{
/// LADSPA descriptor
LADSPA_Descriptor descriptor;
/// LADSPA descriptor for DSSI (uses a different name for the plugin, otherwise same as descriptor)
LADSPA_Descriptor descriptor_for_dssi;
#if USE_DSSI
/// Extended DSSI descriptor (points to descriptor_for_dssi for things like name/label/port info etc.)
DSSI_Descriptor dssi_descriptor;
DSSI_Program_Descriptor dssi_default_program;
std::vector<plugin_preset> *presets;
std::vector<DSSI_Program_Descriptor> *preset_descs;
#endif
int input_count, output_count, param_count;
const plugin_metadata_iface *metadata;
ladspa_plugin_metadata_set();
void prepare(const plugin_metadata_iface *md, LADSPA_Handle (*cb_instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate));
void prepare_dssi();
~ladspa_plugin_metadata_set();
};
/// A wrapper class for plugin class object (there is only one ladspa_wrapper singleton for many instances of the same plugin)
template<class Module>
struct ladspa_wrapper
{
static ladspa_plugin_metadata_set output;
private:
ladspa_wrapper(const plugin_metadata_iface *md)
{
output.prepare(md, cb_instantiate);
}
public:
/// LADSPA instantiation function (create a plugin instance)
static LADSPA_Handle cb_instantiate(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate)
{
return new ladspa_instance(new Module, &output, sample_rate);
}
/// Get a wrapper singleton - used to prevent initialization order problems which were present in older versions
static ladspa_plugin_metadata_set &get() {
static ladspa_wrapper instance(new typename Module::metadata_class);
return instance.output;
}
};
};
#endif
#endif

View File

@@ -19,6 +19,7 @@
* Boston, MA 02110-1301 USA
*/
#include <config.h>
#include <calf/ladspa_wrap.h>
#include <calf/lv2wrap.h>
#include <calf/modules.h>
#include <calf/modules_comp.h>
@@ -32,6 +33,447 @@
using namespace calf_plugins;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if USE_LADSPA
ladspa_instance::ladspa_instance(audio_module_iface *_module, ladspa_plugin_metadata_set *_ladspa, int sample_rate)
{
module = _module;
metadata = module->get_metadata_iface();
ladspa = _ladspa;
module->get_port_arrays(ins, outs, params);
activate_flag = true;
#if USE_DSSI
feedback_sender = NULL;
#endif
module->set_sample_rate(sample_rate);
module->post_instantiate();
}
float ladspa_instance::get_param_value(int param_no)
{
// XXXKF hack
if (param_no >= ladspa->param_count)
return 0;
return *params[param_no];
}
void ladspa_instance::set_param_value(int param_no, float value)
{
// XXXKF hack
if (param_no >= ladspa->param_count)
return;
*params[param_no] = value;
}
bool ladspa_instance::activate_preset(int bank, int program)
{
return false;
}
/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
void ladspa_instance::run(unsigned long SampleCount)
{
if (activate_flag)
{
module->activate();
activate_flag = false;
}
module->params_changed();
module->process_slice(0, SampleCount);
}
#if USE_DSSI
void ladspa_instance::run_synth(unsigned long SampleCount, snd_seq_event_t *Events, unsigned long EventCount)
{
if (activate_flag)
{
module->activate();
activate_flag = false;
}
module->params_changed();
uint32_t offset = 0;
for (uint32_t e = 0; e < EventCount; e++)
{
uint32_t timestamp = Events[e].time.tick;
if (timestamp != offset)
module->process_slice(offset, timestamp);
process_dssi_event(Events[e]);
offset = timestamp;
}
if (offset != SampleCount)
module->process_slice(offset, SampleCount);
}
#endif
char *ladspa_instance::configure(const char *key, const char *value)
{
#if USE_DSSI_GUI
if (!strcmp(key, "OSC:FEEDBACK_URI"))
{
const line_graph_iface *lgi = dynamic_cast<const line_graph_iface *>(metadata);
//if (!lgi)
// return NULL;
if (*value)
{
if (feedback_sender) {
delete feedback_sender;
feedback_sender = NULL;
}
feedback_sender = new dssi_feedback_sender(value, lgi);
feedback_sender->add_graphs(metadata->get_param_props(0), metadata->get_param_count());
}
else
{
if (feedback_sender) {
delete feedback_sender;
feedback_sender = NULL;
}
}
return NULL;
}
else
if (!strcmp(key, "OSC:UPDATE"))
{
if (feedback_sender)
feedback_sender->update();
return NULL;
}
else
if (!strcmp(key, "OSC:SEND_STATUS"))
{
if (!feedback_sender)
return NULL;
struct status_gatherer: public send_updates_iface
{
osc_inline_typed_strstream str;
void send_status(const char *key, const char *value)
{
str << key << value;
}
} sg;
int serial = atoi(value);
serial = module->send_status_updates(&sg, serial);
sg.str << (uint32_t)serial;
feedback_sender->client->send("/status_data", sg.str);
return NULL;
}
else
#endif
if (!strcmp(key, "ExecCommand"))
{
if (*value)
{
execute(atoi(value));
}
return NULL;
}
return module->configure(key, value);
}
template<class Module>
ladspa_plugin_metadata_set ladspa_wrapper<Module>::output;
#if USE_DSSI
/// Utility function: handle MIDI event (only handles a subset in this version)
void ladspa_instance::process_dssi_event(snd_seq_event_t &event)
{
switch(event.type) {
case SND_SEQ_EVENT_NOTEON:
module->note_on(event.data.note.channel, event.data.note.note, event.data.note.velocity);
break;
case SND_SEQ_EVENT_NOTEOFF:
module->note_off(event.data.note.channel, event.data.note.note, event.data.note.velocity);
break;
case SND_SEQ_EVENT_PGMCHANGE:
module->program_change(event.data.control.channel, event.data.control.value);
break;
case SND_SEQ_EVENT_CONTROLLER:
module->control_change(event.data.control.channel, event.data.control.param, event.data.control.value);
break;
case SND_SEQ_EVENT_PITCHBEND:
module->pitch_bend(event.data.control.channel, event.data.control.value);
break;
case SND_SEQ_EVENT_CHANPRESS:
module->channel_pressure(event.data.control.channel, event.data.control.value);
break;
}
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LADSPA callbacks
/// LADSPA activate function (note that at this moment the ports are not set)
static void cb_activate(LADSPA_Handle Instance)
{
((ladspa_instance *)(Instance))->activate_flag = true;
}
/// LADSPA run function - does set sample rate / activate logic when it's run first time after activation
static void cb_run(LADSPA_Handle Instance, unsigned long SampleCount) {
((ladspa_instance *)(Instance))->run(SampleCount);
}
/// LADSPA port connection function
static void cb_connect(LADSPA_Handle Instance, unsigned long port, LADSPA_Data *DataLocation)
{
ladspa_instance *const mod = (ladspa_instance *)Instance;
int first_out = mod->ladspa->input_count;
int first_param = first_out + mod->ladspa->output_count;
int ladspa_port_count = first_param + mod->ladspa->param_count;
if ((int)port < first_out)
mod->ins[port] = DataLocation;
else if ((int)port < first_param)
mod->outs[port - first_out] = DataLocation;
else if ((int)port < ladspa_port_count) {
int i = port - first_param;
mod->params[i] = DataLocation;
*mod->params[i] = mod->metadata->get_param_props(i)->def_value;
}
}
/// LADSPA deactivate function
static void cb_deactivate(LADSPA_Handle Instance) {
((ladspa_instance *)(Instance))->module->deactivate();
}
/// LADSPA cleanup (delete instance) function
static void cb_cleanup(LADSPA_Handle Instance) {
delete ((ladspa_instance *)(Instance));
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DSSI callbacks
#if USE_DSSI
/// DSSI "run synth" function, same as run() except it allows for event delivery
static void cb_run_synth(LADSPA_Handle Instance, unsigned long SampleCount,
snd_seq_event_t *Events, unsigned long EventCount) {
((ladspa_instance *)(Instance))->run_synth(SampleCount, Events, EventCount);
}
/// DSSI configure function (named properties)
static char *cb_configure(LADSPA_Handle Instance,
const char *Key,
const char *Value)
{
return ((ladspa_instance *)(Instance))->configure(Key, Value);
}
/// DSSI get program descriptor function; for 0, it returns the default program (from parameter properties table), for others, it uses global or user preset
static const DSSI_Program_Descriptor *cb_get_program(LADSPA_Handle Instance, unsigned long index)
{
ladspa_plugin_metadata_set *ladspa = ((ladspa_instance *)(Instance))->ladspa;
if (index > ladspa->presets->size())
return NULL;
if (index)
return &(*ladspa->preset_descs)[index - 1];
return &ladspa->dssi_default_program;
}
/// DSSI select program function; for 0, it sets the defaults, for others, it sets global or user preset
static void cb_select_program(LADSPA_Handle Instance, unsigned long Bank, unsigned long Program)
{
ladspa_instance *mod = (ladspa_instance *)Instance;
ladspa_plugin_metadata_set *ladspa = mod->ladspa;
unsigned int no = (Bank << 7) + Program - 1;
// printf("no = %d presets = %p:%d\n", no, presets, presets->size());
if (no == -1U) {
int rpc = ladspa->param_count;
for (int i =0 ; i < rpc; i++)
*mod->params[i] = mod->metadata->get_param_props(i)->def_value;
return;
}
if (no >= ladspa->presets->size())
return;
plugin_preset &p = (*ladspa->presets)[no];
// printf("activating preset %s\n", p.name.c_str());
p.activate(mod);
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
ladspa_plugin_metadata_set::ladspa_plugin_metadata_set()
{
metadata = NULL;
memset(&descriptor, 0, sizeof(descriptor));
#if USE_DSSI
presets = NULL;
preset_descs = NULL;
memset(&descriptor_for_dssi, 0, sizeof(descriptor_for_dssi));
memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
#endif
}
void ladspa_plugin_metadata_set::prepare(const plugin_metadata_iface *md, LADSPA_Handle (*cb_instantiate)(const struct _LADSPA_Descriptor * Descriptor, unsigned long sample_rate))
{
metadata = md;
input_count = md->get_input_count();
output_count = md->get_output_count();
param_count = md->get_param_count(); // XXXKF ladspa_instance<Module>::real_param_count();
const ladspa_plugin_info &plugin_info = md->get_plugin_info();
descriptor.UniqueID = plugin_info.unique_id;
descriptor.Label = plugin_info.label;
descriptor.Name = strdup((std::string(plugin_info.name) + " LADSPA").c_str());
descriptor.Maker = plugin_info.maker;
descriptor.Copyright = plugin_info.copyright;
descriptor.Properties = md->is_rt_capable() ? LADSPA_PROPERTY_HARD_RT_CAPABLE : 0;
descriptor.PortCount = input_count + output_count + param_count;
descriptor.PortNames = new char *[descriptor.PortCount];
descriptor.PortDescriptors = new LADSPA_PortDescriptor[descriptor.PortCount];
descriptor.PortRangeHints = new LADSPA_PortRangeHint[descriptor.PortCount];
int i;
for (i = 0; i < input_count + output_count; i++)
{
LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
((int *)descriptor.PortDescriptors)[i] = i < input_count ? LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO
: LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
prh.HintDescriptor = 0;
((const char **)descriptor.PortNames)[i] = md->get_port_names()[i];
}
for (; i < input_count + output_count + param_count; i++)
{
LADSPA_PortRangeHint &prh = ((LADSPA_PortRangeHint *)descriptor.PortRangeHints)[i];
const parameter_properties &pp = *md->get_param_props(i - input_count - output_count);
((int *)descriptor.PortDescriptors)[i] =
LADSPA_PORT_CONTROL | (pp.flags & PF_PROP_OUTPUT ? LADSPA_PORT_OUTPUT : LADSPA_PORT_INPUT);
prh.HintDescriptor = LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW;
((const char **)descriptor.PortNames)[i] = pp.name;
prh.LowerBound = pp.min;
prh.UpperBound = pp.max;
switch(pp.flags & PF_TYPEMASK) {
case PF_BOOL:
prh.HintDescriptor |= LADSPA_HINT_TOGGLED;
prh.HintDescriptor &= ~(LADSPA_HINT_BOUNDED_ABOVE | LADSPA_HINT_BOUNDED_BELOW);
break;
case PF_INT:
case PF_ENUM:
prh.HintDescriptor |= LADSPA_HINT_INTEGER;
break;
default: {
int defpt = (int)(100 * (pp.def_value - pp.min) / (pp.max - pp.min));
if ((pp.flags & PF_SCALEMASK) == PF_SCALE_LOG)
defpt = (int)(100 * log(pp.def_value / pp.min) / log(pp.max / pp.min));
if (defpt < 12)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM;
else if (defpt < 37)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_LOW;
else if (defpt < 63)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE;
else if (defpt < 88)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH;
else
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM;
}
}
if (pp.def_value == 0 || pp.def_value == 1 || pp.def_value == 100 || pp.def_value == 440 ) {
prh.HintDescriptor &= ~LADSPA_HINT_DEFAULT_MASK;
if (pp.def_value == 1)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_1;
else if (pp.def_value == 100)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_100;
else if (pp.def_value == 440)
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_440;
else
prh.HintDescriptor |= LADSPA_HINT_DEFAULT_0;
}
switch(pp.flags & PF_SCALEMASK) {
case PF_SCALE_LOG:
prh.HintDescriptor |= LADSPA_HINT_LOGARITHMIC;
break;
}
}
descriptor.ImplementationData = this;
descriptor.instantiate = cb_instantiate;
descriptor.connect_port = cb_connect;
descriptor.activate = cb_activate;
descriptor.run = cb_run;
descriptor.run_adding = NULL;
descriptor.set_run_adding_gain = NULL;
descriptor.deactivate = cb_deactivate;
descriptor.cleanup = cb_cleanup;
prepare_dssi();
}
void ladspa_plugin_metadata_set::prepare_dssi()
{
#if USE_DSSI
const ladspa_plugin_info &plugin_info = metadata->get_plugin_info();
memcpy(&descriptor_for_dssi, &descriptor, sizeof(descriptor));
descriptor_for_dssi.Name = strdup((std::string(plugin_info.name) + " DSSI").c_str());
memset(&dssi_descriptor, 0, sizeof(dssi_descriptor));
dssi_descriptor.DSSI_API_Version = 1;
dssi_descriptor.LADSPA_Plugin = &descriptor_for_dssi;
dssi_descriptor.configure = cb_configure;
dssi_descriptor.get_program = cb_get_program;
dssi_descriptor.select_program = cb_select_program;
if (metadata->get_midi())
dssi_descriptor.run_synth = cb_run_synth;
presets = new std::vector<plugin_preset>;
preset_descs = new std::vector<DSSI_Program_Descriptor>;
preset_list plist_tmp, plist;
plist.load_defaults(true);
plist_tmp.load_defaults(false);
plist.presets.insert(plist.presets.end(), plist_tmp.presets.begin(), plist_tmp.presets.end());
// XXXKF this assumes that plugin name in preset is case-insensitive equal to plugin label
// if I forget about this, I'll be in a deep trouble
dssi_default_program.Bank = 0;
dssi_default_program.Program = 0;
dssi_default_program.Name = "default";
int pos = 1;
for (unsigned int i = 0; i < plist.presets.size(); i++)
{
plugin_preset &pp = plist.presets[i];
if (strcasecmp(pp.plugin.c_str(), descriptor.Label))
continue;
DSSI_Program_Descriptor pd;
pd.Bank = pos >> 7;
pd.Program = pos++;
pd.Name = pp.name.c_str();
preset_descs->push_back(pd);
presets->push_back(pp);
}
#endif
}
ladspa_plugin_metadata_set::~ladspa_plugin_metadata_set()
{
delete []descriptor.PortNames;
delete []descriptor.PortDescriptors;
delete []descriptor.PortRangeHints;
#if USE_DSSI
if (presets)
presets->clear();
if (preset_descs)
preset_descs->clear();
delete presets;
delete preset_descs;
#endif
}
#endif
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#if USE_LV2
@@ -53,6 +495,33 @@ const LV2_Descriptor *lv2_descriptor(uint32_t index)
#endif
#if USE_LADSPA
extern "C" {
const LADSPA_Descriptor *ladspa_descriptor(unsigned long Index)
{
#define PER_MODULE_ITEM(name, isSynth, jackname) if (!isSynth && !(Index--)) return &ladspa_wrapper<name##_audio_module>::get().descriptor;
#include <calf/modulelist.h>
return NULL;
}
};
#if USE_DSSI
extern "C" {
const DSSI_Descriptor *dssi_descriptor(unsigned long Index)
{
#define PER_MODULE_ITEM(name, isSynth, jackname) if (!(Index--)) return &calf_plugins::ladspa_wrapper<name##_audio_module>::get().dssi_descriptor;
#include <calf/modulelist.h>
return NULL;
}
};
#endif
#endif
#if USE_JACK
extern "C" {