~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/ardour/plugin.cc

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/buffer_set.h"
 
42
#include "ardour/chan_count.h"
 
43
#include "ardour/chan_mapping.h"
 
44
#include "ardour/data_type.h"
 
45
#include "ardour/midi_buffer.h"
 
46
#include "ardour/midi_state_tracker.h"
 
47
#include "ardour/plugin.h"
 
48
#include "ardour/plugin_manager.h"
 
49
#include "ardour/session.h"
 
50
#include "ardour/types.h"
 
51
 
 
52
#ifdef AUDIOUNIT_SUPPORT
 
53
#include "ardour/audio_unit.h"
 
54
#endif
 
55
 
 
56
#ifdef LV2_SUPPORT
 
57
#include "ardour/lv2_plugin.h"
 
58
#endif
 
59
 
 
60
#include "pbd/stl_delete.h"
 
61
 
 
62
#include "i18n.h"
 
63
#include <locale.h>
 
64
 
 
65
using namespace std;
 
66
using namespace ARDOUR;
 
67
using namespace PBD;
 
68
 
 
69
namespace ARDOUR { class AudioEngine; }
 
70
 
 
71
#ifdef NO_PLUGIN_STATE
 
72
static bool seen_get_state_message = false;
 
73
static bool seen_set_state_message = false;
 
74
#endif
 
75
 
 
76
bool
 
77
PluginInfo::is_instrument () const
 
78
{
 
79
        return (n_inputs.n_midi() != 0) && (n_outputs.n_audio() > 0);
 
80
}
 
81
 
 
82
Plugin::Plugin (AudioEngine& e, Session& s)
 
83
        : _engine (e)
 
84
        , _session (s)
 
85
        , _cycles (0)
 
86
        , _have_presets (false)
 
87
        , _have_pending_stop_events (false)
 
88
        , _parameter_changed_since_last_preset (false)
 
89
{
 
90
        _pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096);
 
91
}
 
92
 
 
93
Plugin::Plugin (const Plugin& other)
 
94
        : StatefulDestructible()
 
95
        , Latent()
 
96
        , _engine (other._engine)
 
97
        , _session (other._session)
 
98
        , _info (other._info)
 
99
        , _cycles (0)
 
100
        , _have_presets (false)
 
101
        , _have_pending_stop_events (false)
 
102
        , _parameter_changed_since_last_preset (false)
 
103
{
 
104
        _pending_stop_events.ensure_buffers (DataType::MIDI, 1, 4096);
 
105
}
 
106
 
 
107
Plugin::~Plugin ()
 
108
{
 
109
}
 
110
 
 
111
void
 
112
Plugin::remove_preset (string name)
 
113
{
 
114
        do_remove_preset (name);
 
115
        _presets.erase (preset_by_label (name)->uri);
 
116
 
 
117
        _last_preset.uri = "";
 
118
        _parameter_changed_since_last_preset = false;
 
119
        PresetRemoved (); /* EMIT SIGNAL */
 
120
}
 
121
 
 
122
/** @return PresetRecord with empty URI on failure */
 
123
Plugin::PresetRecord
 
124
Plugin::save_preset (string name)
 
125
{
 
126
        string const uri = do_save_preset (name);
 
127
 
 
128
        if (!uri.empty()) {
 
129
                _presets.insert (make_pair (uri, PresetRecord (uri, name)));
 
130
                PresetAdded (); /* EMIT SIGNAL */
 
131
        }
 
132
 
 
133
        return PresetRecord (uri, name);
 
134
}
 
135
 
 
136
PluginPtr
 
137
ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
 
138
{
 
139
        PluginManager& mgr (PluginManager::instance());
 
140
        PluginInfoList plugs;
 
141
 
 
142
        switch (type) {
 
143
        case ARDOUR::LADSPA:
 
144
                plugs = mgr.ladspa_plugin_info();
 
145
                break;
 
146
 
 
147
#ifdef LV2_SUPPORT
 
148
        case ARDOUR::LV2:
 
149
                plugs = mgr.lv2_plugin_info();
 
150
                break;
 
151
#endif
 
152
 
 
153
#ifdef WINDOWS_VST_SUPPORT
 
154
        case ARDOUR::Windows_VST:
 
155
                plugs = mgr.windows_vst_plugin_info();
 
156
                break;
 
157
#endif
 
158
 
 
159
#ifdef LXVST_SUPPORT
 
160
        case ARDOUR::LXVST:
 
161
                plugs = mgr.lxvst_plugin_info();
 
162
                break;
 
163
#endif
 
164
 
 
165
#ifdef AUDIOUNIT_SUPPORT
 
166
        case ARDOUR::AudioUnit:
 
167
                plugs = mgr.au_plugin_info();
 
168
                break;
 
169
#endif
 
170
 
 
171
        default:
 
172
                return PluginPtr ((Plugin *) 0);
 
173
        }
 
174
 
 
175
        PluginInfoList::iterator i;
 
176
 
 
177
        for (i = plugs.begin(); i != plugs.end(); ++i) {
 
178
                if (identifier == (*i)->unique_id){
 
179
                        return (*i)->load (session);
 
180
                }
 
181
        }
 
182
 
 
183
#ifdef WINDOWS_VST_SUPPORT
 
184
        /* hmm, we didn't find it. could be because in older versions of Ardour.
 
185
           we used to store the name of a VST plugin, not its unique ID. so try
 
186
           again.
 
187
        */
 
188
 
 
189
        for (i = plugs.begin(); i != plugs.end(); ++i) {
 
190
                if (identifier == (*i)->name){
 
191
                        return (*i)->load (session);
 
192
                }
 
193
        }
 
194
#endif
 
195
 
 
196
#ifdef LXVST_SUPPORT
 
197
        /* hmm, we didn't find it. could be because in older versions of Ardour.
 
198
           we used to store the name of a VST plugin, not its unique ID. so try
 
199
           again.
 
200
        */
 
201
 
 
202
        for (i = plugs.begin(); i != plugs.end(); ++i) {
 
203
                if (identifier == (*i)->name){
 
204
                        return (*i)->load (session);
 
205
                }
 
206
        }
 
207
#endif
 
208
 
 
209
        return PluginPtr ((Plugin*) 0);
 
210
}
 
211
 
 
212
ChanCount
 
213
Plugin::output_streams () const
 
214
{
 
215
        /* LADSPA & VST should not get here because they do not
 
216
           return "infinite" i/o counts.
 
217
        */
 
218
        return ChanCount::ZERO;
 
219
}
 
220
 
 
221
ChanCount
 
222
Plugin::input_streams () const
 
223
{
 
224
        /* LADSPA & VST should not get here because they do not
 
225
           return "infinite" i/o counts.
 
226
        */
 
227
        return ChanCount::ZERO;
 
228
}
 
229
 
 
230
const Plugin::PresetRecord *
 
231
Plugin::preset_by_label (const string& label)
 
232
{
 
233
        // FIXME: O(n)
 
234
        for (map<string, PresetRecord>::const_iterator i = _presets.begin(); i != _presets.end(); ++i) {
 
235
                if (i->second.label == label) {
 
236
                        return &i->second;
 
237
                }
 
238
        }
 
239
 
 
240
        return 0;
 
241
}
 
242
 
 
243
const Plugin::PresetRecord *
 
244
Plugin::preset_by_uri (const string& uri)
 
245
{
 
246
        map<string, PresetRecord>::const_iterator pr = _presets.find (uri);
 
247
        if (pr != _presets.end()) {
 
248
                return &pr->second;
 
249
        } else {
 
250
                return 0;
 
251
        }
 
252
}
 
253
 
 
254
int
 
255
Plugin::connect_and_run (BufferSet& bufs,
 
256
                         ChanMapping /*in_map*/, ChanMapping /*out_map*/,
 
257
                         pframes_t /* nframes */, framecnt_t /*offset*/)
 
258
{
 
259
        if (bufs.count().n_midi() > 0) {
 
260
 
 
261
                /* Track notes that we are sending to the plugin */
 
262
 
 
263
                MidiBuffer& b = bufs.get_midi (0);
 
264
 
 
265
                _tracker.track (b.begin(), b.end());
 
266
 
 
267
                if (_have_pending_stop_events) {
 
268
                        /* Transmit note-offs that are pending from the last transport stop */
 
269
                        bufs.merge_from (_pending_stop_events, 0);
 
270
                        _have_pending_stop_events = false;
 
271
                }
 
272
        }
 
273
 
 
274
        return 0;
 
275
}
 
276
 
 
277
void
 
278
Plugin::realtime_handle_transport_stopped ()
 
279
{
 
280
        resolve_midi ();
 
281
}
 
282
 
 
283
void
 
284
Plugin::realtime_locate ()
 
285
{
 
286
        resolve_midi ();
 
287
}
 
288
 
 
289
void
 
290
Plugin::monitoring_changed ()
 
291
{
 
292
        resolve_midi ();
 
293
}
 
294
 
 
295
void
 
296
Plugin::resolve_midi ()
 
297
{
 
298
        /* Create note-offs for any active notes and put them in _pending_stop_events, to be picked
 
299
           up on the next call to connect_and_run ().
 
300
        */
 
301
 
 
302
        _pending_stop_events.get_midi(0).clear ();
 
303
        _tracker.resolve_notes (_pending_stop_events.get_midi (0), 0);
 
304
        _have_pending_stop_events = true;
 
305
}
 
306
 
 
307
 
 
308
vector<Plugin::PresetRecord>
 
309
Plugin::get_presets ()
 
310
{
 
311
        vector<PresetRecord> p;
 
312
 
 
313
#ifndef NO_PLUGIN_STATE
 
314
        if (!_have_presets) {
 
315
                find_presets ();
 
316
                _have_presets = true;
 
317
        }
 
318
 
 
319
        for (map<string, PresetRecord>::const_iterator i = _presets.begin(); i != _presets.end(); ++i) {
 
320
                p.push_back (i->second);
 
321
        }
 
322
#else
 
323
        if (!seen_set_state_message) {
 
324
                info << string_compose (_("Plugin presets are not supported in this build of %1. Consider paying for a full version"),
 
325
                                        PROGRAM_NAME)
 
326
                     << endmsg;
 
327
        }
 
328
#endif
 
329
 
 
330
        return p;
 
331
}
 
332
 
 
333
/** Set parameters using a preset */
 
334
bool
 
335
Plugin::load_preset (PresetRecord r)
 
336
{
 
337
        _last_preset = r;
 
338
        _parameter_changed_since_last_preset = false;
 
339
 
 
340
        PresetLoaded (); /* EMIT SIGNAL */
 
341
        return true;
 
342
}
 
343
 
 
344
void
 
345
Plugin::clear_preset ()
 
346
{
 
347
        _last_preset.uri = "";
 
348
        _last_preset.label = "";
 
349
        _parameter_changed_since_last_preset = false;
 
350
 
 
351
        PresetLoaded (); /* EMIT SIGNAL */
 
352
}
 
353
 
 
354
/** @param val `plugin' value */
 
355
void
 
356
Plugin::set_parameter (uint32_t which, float)
 
357
{
 
358
        _parameter_changed_since_last_preset = true;
 
359
        _session.set_dirty ();
 
360
        ParameterChanged (which, get_parameter (which)); /* EMIT SIGNAL */
 
361
}
 
362
 
 
363
int
 
364
Plugin::set_state (const XMLNode& node, int /*version*/)
 
365
{
 
366
        XMLProperty const * p = node.property (X_("last-preset-uri"));
 
367
        if (p) {
 
368
                _last_preset.uri = p->value ();
 
369
        }
 
370
 
 
371
        p = node.property (X_("last-preset-label"));
 
372
        if (p) {
 
373
                _last_preset.label = p->value ();
 
374
        }
 
375
 
 
376
        p = node.property (X_("parameter-changed-since-last-preset"));
 
377
        if (p) {
 
378
                _parameter_changed_since_last_preset = string_is_affirmative (p->value ());
 
379
        }
 
380
 
 
381
        return 0;
 
382
}
 
383
 
 
384
XMLNode &
 
385
Plugin::get_state ()
 
386
{
 
387
        XMLNode* root = new XMLNode (state_node_name ());
 
388
        LocaleGuard lg (X_("POSIX"));
 
389
 
 
390
        root->add_property (X_("last-preset-uri"), _last_preset.uri);
 
391
        root->add_property (X_("last-preset-label"), _last_preset.label);
 
392
        root->add_property (X_("parameter-changed-since-last-preset"), _parameter_changed_since_last_preset ? X_("yes") : X_("no"));
 
393
 
 
394
#ifndef NO_PLUGIN_STATE 
 
395
        add_state (root);
 
396
#else
 
397
        if (!seen_get_state_message) {
 
398
                info << string_compose (_("Saving plugin settings is not supported in this build of %1. Consider paying for the full version"),
 
399
                                        PROGRAM_NAME)
 
400
                     << endmsg;
 
401
                seen_get_state_message = true;
 
402
        }
 
403
#endif
 
404
 
 
405
        return *root;
 
406
}
 
407
 
 
408
void
 
409
Plugin::set_info (PluginInfoPtr info)
 
410
{
 
411
        _info = info;
 
412
}
 
413
 
 
414