fix various issues with AU ID handling
[ardour2.git] / libs / ardour / plugin.cc
blob2c0519965b26077a3a523e59baa8b10e19d47f44
1 /*
2 Copyright (C) 2000-2002 Paul Davis
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <vector>
21 #include <string>
23 #include <cstdlib>
24 #include <cstdio> // so libraptor doesn't complain
25 #include <cmath>
26 #include <dirent.h>
27 #include <sys/stat.h>
28 #include <cerrno>
30 #include <lrdf.h>
32 #include <pbd/compose.h>
33 #include <pbd/error.h>
34 #include <pbd/pathscanner.h>
35 #include <pbd/xml++.h>
36 #include <pbd/stacktrace.h>
38 #include <ardour/ardour.h>
39 #include <ardour/session.h>
40 #include <ardour/audioengine.h>
41 #include <ardour/plugin.h>
42 #include <ardour/ladspa_plugin.h>
43 #include <ardour/plugin_manager.h>
45 #ifdef HAVE_AUDIOUNITS
46 #include <ardour/audio_unit.h>
47 #endif
49 #ifdef HAVE_SLV2
50 #include <ardour/lv2_plugin.h>
51 #endif
53 #include <pbd/stl_delete.h>
55 #include "i18n.h"
56 #include <locale.h>
58 using namespace ARDOUR;
59 using namespace PBD;
61 sigc::signal<bool> Plugin::PresetFileExists;
63 Plugin::Plugin (AudioEngine& e, Session& s)
64 : _engine (e), _session (s)
68 Plugin::Plugin (const Plugin& other)
69 : _engine (other._engine), _session (other._session), _info (other._info)
73 void
74 Plugin::setup_controls ()
76 uint32_t port_cnt = parameter_count();
78 /* set up a vector of null pointers for the controls.
79 we'll fill this in on an as-needed basis.
82 controls.assign (port_cnt, (PortControllable*) 0);
85 Plugin::~Plugin ()
87 for (vector<PortControllable*>::iterator i = controls.begin(); i != controls.end(); ++i) {
88 if (*i) {
89 delete *i;
94 void
95 Plugin::make_nth_control (uint32_t n, const XMLNode& node)
97 if (controls[n]) {
98 /* already constructed */
99 return;
102 Plugin::ParameterDescriptor desc;
104 get_parameter_descriptor (n, desc);
106 controls[n] = new PortControllable (node, *this, n,
107 desc.lower, desc.upper, desc.toggled, desc.logarithmic);
110 Controllable *
111 Plugin::get_nth_control (uint32_t n, bool do_not_create)
113 if (n >= parameter_count()) {
114 return 0;
117 if (controls[n] == 0 && !do_not_create) {
119 Plugin::ParameterDescriptor desc;
121 get_parameter_descriptor (n, desc);
123 controls[n] = new PortControllable (describe_parameter (n), *this, n,
124 desc.lower, desc.upper, desc.toggled, desc.logarithmic);
127 return controls[n];
130 Plugin::PortControllable::PortControllable (string name, Plugin& p, uint32_t port_id,
131 float low, float up, bool t, bool loga)
132 : Controllable (name), plugin (p), absolute_port (port_id)
134 toggled = t;
135 logarithmic = loga;
136 lower = low;
137 upper = up;
138 range = upper - lower;
141 Plugin::PortControllable::PortControllable (const XMLNode& node, Plugin& p, uint32_t port_id,
142 float low, float up, bool t, bool loga)
143 : Controllable (node), plugin (p), absolute_port (port_id)
145 toggled = t;
146 logarithmic = loga;
147 lower = low;
148 upper = up;
149 range = upper - lower;
152 void
153 Plugin::PortControllable::set_value (float value)
155 if (toggled) {
156 if (value > 0.5) {
157 value = 1.0;
158 } else {
159 value = 0.0;
161 } else {
163 if (!logarithmic) {
164 value = lower + (range * value);
165 } else {
166 float _lower = 0.0f;
167 if (lower > 0.0f) {
168 _lower = log(lower);
171 value = exp(_lower + log(range) * value);
175 plugin.set_parameter (absolute_port, value);
178 float
179 Plugin::PortControllable::get_value (void) const
181 float val = plugin.get_parameter (absolute_port);
183 if (toggled) {
185 return val;
187 } else {
189 if (logarithmic) {
190 val = log(val);
193 return ((val - lower) / range);
197 vector<string>
198 Plugin::get_presets()
200 vector<string> labels;
201 uint32_t id;
202 std::string unique (unique_id());
204 /* XXX problem: AU plugins don't have numeric ID's.
205 Solution: they have a different method of providing presets.
206 XXX sub-problem: implement it.
209 if (!isdigit (unique[0])) {
210 return labels;
213 id = atol (unique.c_str());
215 lrdf_uris* set_uris = lrdf_get_setting_uris(id);
217 if (set_uris) {
218 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
219 if (char* label = lrdf_get_label(set_uris->items[i])) {
220 labels.push_back(label);
221 presets[label] = set_uris->items[i];
224 lrdf_free_uris(set_uris);
227 // GTK2FIX find an equivalent way to do this with a vector (needed by GUI apis)
228 // labels.unique();
230 return labels;
233 bool
234 Plugin::load_preset(const string preset_label)
236 lrdf_defaults* defs = lrdf_get_setting_values(presets[preset_label].c_str());
238 if (defs) {
239 for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
240 // The defs->items[i].pid < defs->count check is to work around
241 // a bug in liblrdf that saves invalid values into the presets file.
242 if (((uint32_t) defs->items[i].pid < (uint32_t) defs->count) && parameter_is_input (defs->items[i].pid)) {
243 set_parameter(defs->items[i].pid, defs->items[i].value);
246 lrdf_free_setting_values(defs);
249 return true;
252 bool
253 Plugin::save_preset (string name, string domain)
255 lrdf_portvalue portvalues[parameter_count()];
256 lrdf_defaults defaults;
257 uint32_t id;
258 std::string unique (unique_id());
260 /* XXX problem: AU plugins don't have numeric ID's.
261 Solution: they have a different method of providing/saving presets.
262 XXX sub-problem: implement it.
265 if (!isdigit (unique[0])) {
266 return false;
269 id = atol (unique.c_str());
271 defaults.count = parameter_count();
272 defaults.items = portvalues;
274 for (uint32_t i = 0; i < parameter_count(); ++i) {
275 if (parameter_is_input (i)) {
276 portvalues[i].pid = i;
277 portvalues[i].value = get_parameter(i);
281 char* envvar;
282 if ((envvar = getenv ("HOME")) == 0) {
283 warning << _("Could not locate HOME. Preset not saved.") << endmsg;
284 return false;
287 string source(string_compose("file:%1/.%2/rdf/ardour-presets.n3", envvar, domain));
289 free(lrdf_add_preset(source.c_str(), name.c_str(), id, &defaults));
291 string path = string_compose("%1/.%2", envvar, domain);
292 if (g_mkdir_with_parents (path.c_str(), 0775)) {
293 warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
294 return false;
297 path += "/rdf";
298 if (g_mkdir_with_parents (path.c_str(), 0775)) {
299 warning << string_compose(_("Could not create %1. Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
300 return false;
303 if (lrdf_export_by_source(source.c_str(), source.substr(5).c_str())) {
304 warning << string_compose(_("Error saving presets file %1."), source) << endmsg;
305 return false;
308 return true;
311 PluginPtr
312 ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
314 PluginManager *mgr = PluginManager::the_manager();
315 PluginInfoList plugs;
317 switch (type) {
318 case ARDOUR::LADSPA:
319 plugs = mgr->ladspa_plugin_info();
320 break;
322 #ifdef HAVE_SLV2
323 case ARDOUR::LV2:
324 plugs = mgr->lv2_plugin_info();
325 break;
326 #endif
328 #ifdef VST_SUPPORT
329 case ARDOUR::VST:
330 plugs = mgr->vst_plugin_info();
331 break;
332 #endif
334 #ifdef HAVE_AUDIOUNITS
335 case ARDOUR::AudioUnit:
337 /* Ardour before 2.8.5 stored identifiers using a broken function
338 provided by Apple (StringForOSType()) that couldn't properly
339 handle some bytes stored in some plugins' multi-character literal
340 identifiers.
342 Ardour 2.8.5 switched to use a modified version of this
343 function, but one that was still problematic and not
344 backwards compatible.
346 So, if this is an AU and we didn't find it above, fix up
347 the identifier we are looking for and check again.
351 std::string fixed = AUPlugin::maybe_fix_broken_au_id (identifier);
352 if (fixed.empty()) {
353 error << string_compose (_("This session contains an AU plugin whose ID cannot be understood - ignored (%1)"), identifier) << endmsg;
354 return PluginPtr ((Plugin*) 0);
356 identifier = fixed;
358 plugs = mgr->au_plugin_info();
359 break;
360 #endif
362 default:
363 return PluginPtr ((Plugin *) 0);
366 PluginInfoList::iterator i;
368 for (i = plugs.begin(); i != plugs.end(); ++i) {
369 if (identifier == (*i)->unique_id){
370 return (*i)->load (session);
374 #ifdef VST_SUPPORT
375 /* hmm, we didn't find it. could be because in older versions of Ardour.
376 we used to store the name of a VST plugin, not its unique ID. so try
377 again.
379 switch (type) {
380 case ARDOUR::VST:
381 for (i = plugs.begin(); i != plugs.end(); ++i) {
382 if (identifier == (*i)->name){
383 return (*i)->load (session);
386 break;
387 default:
388 break;
390 #endif
392 return PluginPtr ((Plugin*) 0);
395 int32_t
396 Plugin::configure_io (int32_t in, int32_t out)
398 /* parent Plugin class assumes static output stream count.
399 Derived classes can override.
402 Glib::Mutex::Lock em (_session.engine().process_lock());
403 IO::MoreOutputs (output_streams());
405 return 0;
408 int32_t
409 Plugin::can_do (int32_t in, int32_t& out)
411 int32_t outputs = get_info()->n_outputs;
412 int32_t inputs = get_info()->n_inputs;
414 if (inputs == 0) {
416 /* instrument plugin, always legal, but it throws
417 away any existing active streams.
420 out = outputs;
421 return 1;
424 if (outputs == 1 && inputs == 1) {
425 /* mono plugin, replicate as needed */
426 out = in;
427 return in;
430 if (inputs == in) {
431 /* exact match */
432 out = outputs;
433 return 1;
436 if ((inputs < in) && (inputs % in == 0)) {
438 /* number of inputs is a factor of the requested input
439 configuration, so we can replicate.
442 int nplugs = in/inputs;
443 out = outputs * nplugs;
444 return nplugs;
447 /* sorry */
449 return -1;
452 uint32_t
453 Plugin::output_streams () const
455 /* LADSPA & VST should not get here because they do not
456 return negative i/o counts.
458 return 0;
461 uint32_t
462 Plugin::input_streams () const
464 /* LADSPA & VST should not get here because they do not
465 return negative i/o counts.
467 return 0;