diff options
Diffstat (limited to 'libs/ardour/plugin.cc')
-rw-r--r-- | libs/ardour/plugin.cc | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc new file mode 100644 index 0000000000..dc85e1d721 --- /dev/null +++ b/libs/ardour/plugin.cc @@ -0,0 +1,351 @@ +/* + Copyright (C) 2000-2002 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + $Id$ +*/ + +#include <vector> +#include <string> + +#include <cstdlib> +#include <cstdio> // so libraptor doesn't complain +#include <cmath> +#include <dirent.h> +#include <sys/stat.h> +#include <cerrno> + +#include <lrdf.h> + +#include <pbd/compose.h> +#include <pbd/error.h> +#include <pbd/pathscanner.h> +#include <pbd/xml++.h> + +#include <midi++/manager.h> + +#include <ardour/ardour.h> +#include <ardour/session.h> +#include <ardour/audioengine.h> +#include <ardour/plugin.h> + +#include <pbd/stl_delete.h> + +#include "i18n.h" +#include <locale.h> + +using namespace ARDOUR; + +Plugin::Plugin (AudioEngine& e, Session& s) + : _engine (e), _session (s) +{ +} + +Plugin::Plugin (const Plugin& other) + : _engine (other._engine), _session (other._session), _info (other._info) +{ +} + +void +Plugin::setup_midi_controls () +{ + uint32_t port_cnt; + + port_cnt = parameter_count(); + + /* set up a vector of null pointers for the MIDI controls. + we'll fill this in on an as-needed basis. + */ + + for (uint32_t i = 0; i < port_cnt; ++i) { + midi_controls.push_back (0); + } +} + +Plugin::~Plugin () +{ + for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i) { + if (*i) { + delete *i; + } + } +} + +MIDI::Controllable * +Plugin::get_nth_midi_control (uint32_t n) +{ + if (n >= parameter_count()) { + return 0; + } + + if (midi_controls[n] == 0) { + + Plugin::ParameterDescriptor desc; + + get_parameter_descriptor (n, desc); + + midi_controls[n] = new MIDIPortControl (*this, n, _session.midi_port(), desc.lower, desc.upper, desc.toggled, desc.logarithmic); + } + + return midi_controls[n]; +} + +Plugin::MIDIPortControl::MIDIPortControl (Plugin& p, uint32_t port_id, MIDI::Port *port, + float low, float up, bool t, bool loga) + : MIDI::Controllable (port, 0), plugin (p), absolute_port (port_id) +{ + toggled = t; + logarithmic = loga; + lower = low; + upper = up; + range = upper - lower; + last_written = 0; /* XXX need a good out-of-bound-value */ + setting = false; +} + +void +Plugin::MIDIPortControl::set_value (float value) +{ + if (toggled) { + if (value > 0.5) { + value = 1.0; + } else { + value = 0.0; + } + } else { + value = lower + (range * value); + + if (logarithmic) { + value = exp(value); + } + } + + setting = true; + plugin.set_parameter (absolute_port, value); + setting = false; +} + +void +Plugin::MIDIPortControl::send_feedback (float value) +{ + + if (!setting && get_midi_feedback()) { + MIDI::byte val; + MIDI::channel_t ch = 0; + MIDI::eventType ev = MIDI::none; + MIDI::byte additional = 0; + MIDI::EventTwoBytes data; + + if (toggled) { + val = (MIDI::byte) (value * 127.0f); + } else { + if (logarithmic) { + value = log(value); + } + + val = (MIDI::byte) (((value - lower) / range) * 127.0f); + } + + if (get_control_info (ch, ev, additional)) { + data.controller_number = additional; + data.value = val; + + plugin.session().send_midi_message (get_port(), ev, ch, data); + } + } + +} + +MIDI::byte* +Plugin::MIDIPortControl::write_feedback (MIDI::byte* buf, int32_t& bufsize, float value, bool force) +{ + if (get_midi_feedback() && bufsize > 2) { + MIDI::channel_t ch = 0; + MIDI::eventType ev = MIDI::none; + MIDI::byte additional = 0; + + if (get_control_info (ch, ev, additional)) { + + MIDI::byte val; + + if (toggled) { + + val = (MIDI::byte) (value * 127.0f); + + } else { + + if (logarithmic) { + value = log(value); + } + + val = (MIDI::byte) (((value - lower) / range) * 127.0f); + } + + if (val != last_written || force) { + *buf++ = MIDI::controller & ch; + *buf++ = additional; /* controller number */ + *buf++ = val; + last_written = val; + bufsize -= 3; + } + } + } + + return buf; +} + + +void +Plugin::reset_midi_control (MIDI::Port* port, bool on) +{ + MIDI::channel_t chn; + MIDI::eventType ev; + MIDI::byte extra; + + for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i) { + if (*i == 0) + continue; + (*i)->get_control_info (chn, ev, extra); + if (!on) { + chn = -1; + } + (*i)->midi_rebind (port, chn); + } +} + +void +Plugin::send_all_midi_feedback () +{ + if (_session.get_midi_feedback()) { + float val = 0.0; + uint32_t n = 0; + + for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i, ++n) { + if (*i == 0) { + continue; + } + + val = (*i)->plugin.get_parameter (n); + (*i)->send_feedback (val); + } + + } +} + +MIDI::byte* +Plugin::write_midi_feedback (MIDI::byte* buf, int32_t& bufsize) +{ + if (_session.get_midi_feedback()) { + float val = 0.0; + uint32_t n = 0; + + for (vector<MIDIPortControl*>::iterator i = midi_controls.begin(); i != midi_controls.end(); ++i, ++n) { + if (*i == 0) { + continue; + } + + val = (*i)->plugin.get_parameter (n); + buf = (*i)->write_feedback (buf, bufsize, val); + } + } + + return buf; +} + +list<string> +Plugin::get_presets() +{ + list<string> labels; + lrdf_uris* set_uris = lrdf_get_setting_uris(unique_id()); + + if (set_uris) { + for (uint32_t i = 0; i < set_uris->count; ++i) { + if (char* label = lrdf_get_label(set_uris->items[i])) { + labels.push_back(label); + presets[label] = set_uris->items[i]; + } + } + lrdf_free_uris(set_uris); + } + + labels.unique(); + + return labels; +} + +bool +Plugin::load_preset(const string preset_label) +{ + lrdf_defaults* defs = lrdf_get_setting_values(presets[preset_label].c_str()); + + if (defs) { + for (uint32_t i = 0; i < defs->count; ++i) { + // The defs->items[i].pid < defs->count check is to work around + // a bug in liblrdf that saves invalid values into the presets file. + if (((uint32_t) defs->items[i].pid < defs->count) && parameter_is_input (defs->items[i].pid)) { + set_parameter(defs->items[i].pid, defs->items[i].value); + } + } + lrdf_free_setting_values(defs); + } + + return true; +} + +bool +Plugin::save_preset (string name, string domain) +{ + lrdf_portvalue portvalues[parameter_count()]; + lrdf_defaults defaults; + defaults.count = parameter_count(); + defaults.items = portvalues; + + for (uint32_t i = 0; i < parameter_count(); ++i) { + if (parameter_is_input (i)) { + portvalues[i].pid = i; + portvalues[i].value = get_parameter(i); + } + } + + char* envvar; + if ((envvar = getenv ("HOME")) == 0) { + warning << _("Could not locate HOME. Preset not saved.") << endmsg; + return false; + } + + string source(compose("file:%1/.%2/rdf/ardour-presets.n3", envvar, domain)); + + free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults)); + + string path = compose("%1/.%2", envvar, domain); + if (mkdir(path.c_str(), 0775) && errno != EEXIST) { + warning << compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg; + return false; + } + + path += "/rdf"; + if (mkdir(path.c_str(), 0775) && errno != EEXIST) { + warning << compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg; + return false; + } + + if (lrdf_export_by_source(source.c_str(), source.substr(5).c_str())) { + warning << compose(_("Error saving presets file %1."), source) << endmsg; + return false; + } + + return true; +} |