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