Fix sketchy casts.
[ardour.git] / libs / ardour / plugin.cc
1 /*
2     Copyright (C) 2000-2002 Paul Davis
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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "libardour-config.h"
22 #endif
23
24 #include <vector>
25 #include <string>
26
27 #include <cstdlib>
28 #include <cstdio> // so libraptor doesn't complain
29 #include <cmath>
30 #include <dirent.h>
31 #include <sys/stat.h>
32 #include <cerrno>
33 #include <utility>
34
35 #include <lrdf.h>
36
37 #include "pbd/compose.h"
38 #include "pbd/error.h"
39 #include "pbd/xml++.h"
40
41 #include "ardour/ardour.h"
42 #include "ardour/session.h"
43 #include "ardour/audioengine.h"
44 #include "ardour/plugin.h"
45 #include "ardour/ladspa_plugin.h"
46 #include "ardour/plugin_manager.h"
47
48 #ifdef HAVE_AUDIOUNITS
49 #include "ardour/audio_unit.h"
50 #endif
51
52 #ifdef HAVE_SLV2
53 #include "ardour/lv2_plugin.h"
54 #endif
55
56 #include "pbd/stl_delete.h"
57
58 #include "i18n.h"
59 #include <locale.h>
60
61 using namespace std;
62 using namespace ARDOUR;
63 using namespace PBD;
64
65 Plugin::Plugin (AudioEngine& e, Session& s)
66         : _engine (e)
67         , _session (s)
68         , _cycles (0)
69 {
70 }
71
72 Plugin::Plugin (const Plugin& other)
73         : StatefulDestructible()
74         , Latent()
75         , _engine (other._engine)
76         , _session (other._session)
77         , _info (other._info)
78         , _cycles (0)
79         , presets (other.presets)
80 {
81 }
82
83 Plugin::~Plugin ()
84 {
85 }
86
87 const Plugin::PresetRecord*
88 Plugin::preset_by_label(const string& label)
89 {
90         // FIXME: O(n)
91         for (map<string,PresetRecord>::const_iterator i = presets.begin(); i != presets.end(); ++i) {
92                 if (i->second.label == label) {
93                         return &i->second;
94                 }
95         }
96         return NULL;
97 }
98
99 const Plugin::PresetRecord*
100 Plugin::preset_by_uri(const string& uri)
101 {
102         map<string,PresetRecord>::const_iterator pr = presets.find(uri);
103         if (pr != presets.end()) {
104                 return &pr->second;
105         } else {
106                 return NULL;
107         }
108 }
109
110 vector<Plugin::PresetRecord>
111 Plugin::get_presets()
112 {
113         vector<PresetRecord> result;
114         uint32_t id;
115         std::string unique (unique_id());
116
117         /* XXX problem: AU plugins don't have numeric ID's.
118            Solution: they have a different method of providing presets.
119            XXX sub-problem: implement it.
120         */
121
122         if (!isdigit (unique[0])) {
123                 return result;
124         }
125
126         id = atol (unique.c_str());
127
128         lrdf_uris* set_uris = lrdf_get_setting_uris(id);
129
130         if (set_uris) {
131                 for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
132                         if (char* label = lrdf_get_label(set_uris->items[i])) {
133                                 PresetRecord rec(set_uris->items[i], label);
134                                 result.push_back(rec);
135                                 presets.insert(std::make_pair(set_uris->items[i], rec));
136                         }
137                 }
138                 lrdf_free_uris(set_uris);
139         }
140
141         return result;
142 }
143
144 bool
145 Plugin::load_preset(const string preset_uri)
146 {
147         lrdf_defaults* defs = lrdf_get_setting_values(preset_uri.c_str());
148
149         if (defs) {
150                 for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
151                         // The defs->items[i].pid < defs->count check is to work around
152                         // a bug in liblrdf that saves invalid values into the presets file.
153                         if (((uint32_t) defs->items[i].pid < (uint32_t) defs->count) && parameter_is_input (defs->items[i].pid)) {
154                                 set_parameter(defs->items[i].pid, defs->items[i].value);
155                         }
156                 }
157                 lrdf_free_setting_values(defs);
158         }
159
160         return true;
161 }
162
163 bool
164 Plugin::save_preset (string name, string domain)
165 {
166         lrdf_portvalue portvalues[parameter_count()];
167         lrdf_defaults defaults;
168         uint32_t id;
169         std::string unique (unique_id());
170
171         /* XXX problem: AU plugins don't have numeric ID's.
172            Solution: they have a different method of providing/saving presets.
173            XXX sub-problem: implement it.
174         */
175
176         if (!isdigit (unique[0])) {
177                 return false;
178         }
179
180         id = atol (unique.c_str());
181
182         defaults.count = parameter_count();
183         defaults.items = portvalues;
184
185         for (uint32_t i = 0; i < parameter_count(); ++i) {
186                 if (parameter_is_input (i)) {
187                         portvalues[i].pid = i;
188                         portvalues[i].value = get_parameter(i);
189                 }
190         }
191
192         char* envvar;
193         if ((envvar = getenv ("HOME")) == 0) {
194                 warning << _("Could not locate HOME.  Preset not saved.") << endmsg;
195                 return false;
196         }
197
198         string source(string_compose("file:%1/.%2/rdf/ardour-presets.n3", envvar, domain));
199
200         char* uri = lrdf_add_preset (source.c_str(), name.c_str(), id, &defaults);
201         
202         /* XXX: why is the uri apparently kept as the key in the `presets' map and also in the PresetRecord? */
203
204         presets.insert (make_pair (uri, PresetRecord (uri, name)));
205         free (uri);
206
207         string path = string_compose("%1/.%2", envvar, domain);
208         if (g_mkdir_with_parents (path.c_str(), 0775)) {
209                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
210                 return false;
211         }
212
213         path += "/rdf";
214         if (g_mkdir_with_parents (path.c_str(), 0775)) {
215                 warning << string_compose(_("Could not create %1.  Preset not saved. (%2)"), path, strerror(errno)) << endmsg;
216                 return false;
217         }
218
219         if (lrdf_export_by_source(source.c_str(), source.substr(5).c_str())) {
220                 warning << string_compose(_("Error saving presets file %1."), source) << endmsg;
221                 return false;
222         }
223
224         return true;
225 }
226
227 PluginPtr
228 ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
229 {
230         PluginManager *mgr = PluginManager::the_manager();
231         PluginInfoList plugs;
232
233         switch (type) {
234         case ARDOUR::LADSPA:
235                 plugs = mgr->ladspa_plugin_info();
236                 break;
237
238 #ifdef HAVE_SLV2
239         case ARDOUR::LV2:
240                 plugs = mgr->lv2_plugin_info();
241                 break;
242 #endif
243
244 #ifdef VST_SUPPORT
245         case ARDOUR::VST:
246                 plugs = mgr->vst_plugin_info();
247                 break;
248 #endif
249
250 #ifdef HAVE_AUDIOUNITS
251         case ARDOUR::AudioUnit:
252                 plugs = mgr->au_plugin_info();
253                 break;
254 #endif
255
256         default:
257                 return PluginPtr ((Plugin *) 0);
258         }
259
260         PluginInfoList::iterator i;
261
262         for (i = plugs.begin(); i != plugs.end(); ++i) {
263                 if (identifier == (*i)->unique_id){
264                         return (*i)->load (session);
265                 }
266         }
267
268 #ifdef VST_SUPPORT
269         /* hmm, we didn't find it. could be because in older versions of Ardour.
270            we used to store the name of a VST plugin, not its unique ID. so try
271            again.
272         */
273
274         for (i = plugs.begin(); i != plugs.end(); ++i) {
275                 if (identifier == (*i)->name){
276                         return (*i)->load (session);
277                 }
278         }
279 #endif
280
281         return PluginPtr ((Plugin*) 0);
282 }
283
284 ChanCount
285 Plugin::output_streams () const
286 {
287         /* LADSPA & VST should not get here because they do not
288            return "infinite" i/o counts.
289         */
290         return ChanCount::ZERO;
291 }
292
293 ChanCount
294 Plugin::input_streams () const
295 {
296         /* LADSPA & VST should not get here because they do not
297            return "infinite" i/o counts.
298         */
299         return ChanCount::ZERO;
300 }
301
302