2008-06-02 21:41:35 +00:00
|
|
|
/*
|
2009-10-14 16:10:01 +00:00
|
|
|
Copyright (C) 2000 Paul Davis
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
2009-07-13 00:26:28 +00:00
|
|
|
#ifdef WAF_BUILD
|
|
|
|
|
#include "libardour-config.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
|
|
2009-02-25 18:26:51 +00:00
|
|
|
#include "pbd/failed_constructor.h"
|
|
|
|
|
#include "pbd/xml++.h"
|
|
|
|
|
|
|
|
|
|
#include "ardour/audio_buffer.h"
|
|
|
|
|
#include "ardour/automation_list.h"
|
|
|
|
|
#include "ardour/buffer_set.h"
|
|
|
|
|
#include "ardour/event_type_map.h"
|
|
|
|
|
#include "ardour/ladspa_plugin.h"
|
|
|
|
|
#include "ardour/plugin.h"
|
|
|
|
|
#include "ardour/plugin_insert.h"
|
|
|
|
|
#include "ardour/port.h"
|
|
|
|
|
#include "ardour/route.h"
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
#ifdef HAVE_SLV2
|
2009-02-25 18:26:51 +00:00
|
|
|
#include "ardour/lv2_plugin.h"
|
2008-06-02 21:41:35 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef VST_SUPPORT
|
2009-02-25 18:26:51 +00:00
|
|
|
#include "ardour/vst_plugin.h"
|
2008-06-02 21:41:35 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_AUDIOUNITS
|
2009-02-25 18:26:51 +00:00
|
|
|
#include "ardour/audio_unit.h"
|
2008-06-02 21:41:35 +00:00
|
|
|
#endif
|
|
|
|
|
|
2009-02-25 18:26:51 +00:00
|
|
|
#include "ardour/audioengine.h"
|
|
|
|
|
#include "ardour/session.h"
|
|
|
|
|
#include "ardour/types.h"
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
#include "i18n.h"
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
using namespace ARDOUR;
|
|
|
|
|
using namespace PBD;
|
|
|
|
|
|
|
|
|
|
const string PluginInsert::port_automation_node_name = "PortAutomation";
|
|
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug)
|
2010-04-01 01:24:13 +00:00
|
|
|
: Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
, _signal_analysis_collected_nframes(0)
|
|
|
|
|
, _signal_analysis_collect_nframes_max(0)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
/* the first is the master */
|
|
|
|
|
|
2010-04-01 01:24:13 +00:00
|
|
|
if (plug) {
|
|
|
|
|
_plugins.push_back (plug);
|
|
|
|
|
set_automatable ();
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
Glib::Mutex::Lock em (_session.engine().process_lock());
|
|
|
|
|
IO::PortCountChanged (max(input_streams(), output_streams()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
PluginInsert::set_count (uint32_t num)
|
|
|
|
|
{
|
|
|
|
|
bool require_state = !_plugins.empty();
|
|
|
|
|
|
|
|
|
|
/* this is a bad idea.... we shouldn't do this while active.
|
2009-10-14 16:10:01 +00:00
|
|
|
only a route holding their redirect_lock should be calling this
|
2008-06-02 21:41:35 +00:00
|
|
|
*/
|
|
|
|
|
|
2009-10-14 16:10:01 +00:00
|
|
|
if (num == 0) {
|
2008-06-02 21:41:35 +00:00
|
|
|
return false;
|
|
|
|
|
} else if (num > _plugins.size()) {
|
|
|
|
|
uint32_t diff = num - _plugins.size();
|
|
|
|
|
|
|
|
|
|
for (uint32_t n = 0; n < diff; ++n) {
|
|
|
|
|
_plugins.push_back (plugin_factory (_plugins[0]));
|
|
|
|
|
|
|
|
|
|
if (require_state) {
|
|
|
|
|
/* XXX do something */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} else if (num < _plugins.size()) {
|
|
|
|
|
uint32_t diff = _plugins.size() - num;
|
|
|
|
|
for (uint32_t n= 0; n < diff; ++n) {
|
|
|
|
|
_plugins.pop_back();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PluginInsert::~PluginInsert ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2010-08-09 22:23:23 +00:00
|
|
|
PluginInsert::control_list_automation_state_changed (Evoral::Parameter which, AutoState s)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
if (which.type() != PluginAutomation)
|
|
|
|
|
return;
|
|
|
|
|
|
2008-09-19 00:47:49 +00:00
|
|
|
boost::shared_ptr<AutomationControl> c
|
2010-02-05 20:03:57 +00:00
|
|
|
= boost::dynamic_pointer_cast<AutomationControl>(control (which));
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2010-08-09 22:23:23 +00:00
|
|
|
if (c && s != Off) {
|
2008-06-02 21:41:35 +00:00
|
|
|
_plugins[0]->set_parameter (which.id(), c->list()->eval (_session.transport_frame()));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ChanCount
|
|
|
|
|
PluginInsert::output_streams() const
|
|
|
|
|
{
|
2008-09-10 15:03:30 +00:00
|
|
|
ChanCount out = _plugins.front()->get_info()->n_outputs;
|
|
|
|
|
|
|
|
|
|
if (out == ChanCount::INFINITE) {
|
|
|
|
|
return _plugins.front()->output_streams ();
|
|
|
|
|
} else {
|
|
|
|
|
out.set_audio (out.n_audio() * _plugins.size());
|
|
|
|
|
out.set_midi (out.n_midi() * _plugins.size());
|
|
|
|
|
return out;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ChanCount
|
|
|
|
|
PluginInsert::input_streams() const
|
|
|
|
|
{
|
2008-09-10 15:03:30 +00:00
|
|
|
ChanCount in = _plugins[0]->get_info()->n_inputs;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-09-10 15:03:30 +00:00
|
|
|
if (in == ChanCount::INFINITE) {
|
|
|
|
|
return _plugins[0]->input_streams ();
|
|
|
|
|
} else {
|
|
|
|
|
in.set_audio (in.n_audio() * _plugins.size());
|
|
|
|
|
in.set_midi (in.n_midi() * _plugins.size());
|
|
|
|
|
return in;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ChanCount
|
|
|
|
|
PluginInsert::natural_output_streams() const
|
|
|
|
|
{
|
|
|
|
|
return _plugins[0]->get_info()->n_outputs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ChanCount
|
|
|
|
|
PluginInsert::natural_input_streams() const
|
|
|
|
|
{
|
|
|
|
|
return _plugins[0]->get_info()->n_inputs;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
PluginInsert::is_generator() const
|
|
|
|
|
{
|
|
|
|
|
/* XXX more finesse is possible here. VST plugins have a
|
|
|
|
|
a specific "instrument" flag, for example.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
return _plugins[0]->get_info()->n_inputs.n_audio() == 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PluginInsert::set_automatable ()
|
|
|
|
|
{
|
2008-09-29 22:47:40 +00:00
|
|
|
set<Evoral::Parameter> a = _plugins.front()->automatable ();
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
Plugin::ParameterDescriptor desc;
|
|
|
|
|
|
2008-09-29 22:47:40 +00:00
|
|
|
for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
|
2008-06-02 21:41:35 +00:00
|
|
|
if (i->type() == PluginAutomation) {
|
2009-12-30 19:33:29 +00:00
|
|
|
|
2008-09-29 22:47:40 +00:00
|
|
|
Evoral::Parameter param(*i);
|
2009-12-30 19:33:29 +00:00
|
|
|
|
|
|
|
|
_plugins.front()->get_parameter_descriptor(i->id(), desc);
|
|
|
|
|
|
|
|
|
|
/* the Parameter belonging to the actual plugin doesn't have its range set
|
|
|
|
|
but we want the Controllable related to this Parameter to have those limits.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
param.set_range (desc.lower, desc.upper, _plugins.front()->default_value(i->id()));
|
|
|
|
|
can_automate (param);
|
2008-09-19 00:47:49 +00:00
|
|
|
boost::shared_ptr<AutomationList> list(new AutomationList(param));
|
2009-12-30 19:33:29 +00:00
|
|
|
add_control (boost::shared_ptr<AutomationControl>(new PluginControl(this, param, list)));
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2008-09-29 22:47:40 +00:00
|
|
|
PluginInsert::parameter_changed (Evoral::Parameter which, float val)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
if (which.type() != PluginAutomation)
|
|
|
|
|
return;
|
|
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
Plugins::iterator i = _plugins.begin();
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
/* don't set the first plugin, just all the slaves */
|
|
|
|
|
|
|
|
|
|
if (i != _plugins.end()) {
|
|
|
|
|
++i;
|
|
|
|
|
for (; i != _plugins.end(); ++i) {
|
|
|
|
|
(*i)->set_parameter (which, val);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-16 19:58:34 +00:00
|
|
|
int
|
2008-06-02 21:41:35 +00:00
|
|
|
PluginInsert::set_block_size (nframes_t nframes)
|
|
|
|
|
{
|
2010-08-16 19:58:34 +00:00
|
|
|
int ret = 0;
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
2010-08-16 19:58:34 +00:00
|
|
|
if ((*i)->set_block_size (nframes) != 0) {
|
|
|
|
|
ret = -1;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
2010-08-16 19:58:34 +00:00
|
|
|
return ret;
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PluginInsert::activate ()
|
|
|
|
|
{
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
2008-06-02 21:41:35 +00:00
|
|
|
(*i)->activate ();
|
|
|
|
|
}
|
2010-08-07 23:31:33 +00:00
|
|
|
|
|
|
|
|
Processor::activate ();
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
PluginInsert::deactivate ()
|
|
|
|
|
{
|
2009-08-02 00:34:49 +00:00
|
|
|
Processor::deactivate ();
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
2008-06-02 21:41:35 +00:00
|
|
|
(*i)->deactivate ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-16 19:58:34 +00:00
|
|
|
void
|
|
|
|
|
PluginInsert::flush ()
|
|
|
|
|
{
|
|
|
|
|
for (vector<boost::shared_ptr<Plugin> >::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
|
|
|
|
(*i)->flush ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
void
|
|
|
|
|
PluginInsert::connect_and_run (BufferSet& bufs, nframes_t nframes, nframes_t offset, bool with_auto, nframes_t now)
|
|
|
|
|
{
|
2008-10-20 18:57:34 +00:00
|
|
|
// Calculate if, and how many frames we need to collect for analysis
|
|
|
|
|
nframes_t collect_signal_nframes = (_signal_analysis_collect_nframes_max -
|
|
|
|
|
_signal_analysis_collected_nframes);
|
|
|
|
|
if (nframes < collect_signal_nframes) { // we might not get all frames now
|
|
|
|
|
collect_signal_nframes = nframes;
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
ChanMapping in_map(input_streams());
|
|
|
|
|
ChanMapping out_map(output_streams());
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
/* Note that we've already required that plugins
|
|
|
|
|
be able to handle in-place processing.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (with_auto) {
|
|
|
|
|
|
|
|
|
|
uint32_t n = 0;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2010-02-05 20:03:57 +00:00
|
|
|
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li, ++n) {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-09-19 00:47:49 +00:00
|
|
|
boost::shared_ptr<AutomationControl> c
|
|
|
|
|
= boost::dynamic_pointer_cast<AutomationControl>(li->second);
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2008-09-19 00:47:49 +00:00
|
|
|
if (c->parameter().type() == PluginAutomation && c->automation_playback()) {
|
2008-06-02 21:41:35 +00:00
|
|
|
bool valid;
|
|
|
|
|
|
2009-10-14 16:10:01 +00:00
|
|
|
const float val = c->list()->rt_safe_eval (now, valid);
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
if (valid) {
|
|
|
|
|
c->set_value(val);
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-14 16:10:01 +00:00
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-20 18:57:34 +00:00
|
|
|
if (collect_signal_nframes > 0) {
|
|
|
|
|
// collect input
|
|
|
|
|
//std::cerr << "collect input, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
|
|
|
|
|
//std::cerr << " streams " << input_streams().n_audio() << std::endl;
|
|
|
|
|
//std::cerr << "filling buffer with " << collect_signal_nframes << " frames at " << _signal_analysis_collected_nframes << std::endl;
|
2009-05-08 05:20:23 +00:00
|
|
|
|
|
|
|
|
_signal_analysis_inputs.set_count(input_streams());
|
|
|
|
|
|
2008-10-20 18:57:34 +00:00
|
|
|
for (uint32_t i = 0; i < input_streams().n_audio(); ++i) {
|
2009-05-04 15:50:51 +00:00
|
|
|
_signal_analysis_inputs.get_audio(i).read_from(
|
2008-10-20 18:57:34 +00:00
|
|
|
bufs.get_audio(i),
|
|
|
|
|
collect_signal_nframes,
|
|
|
|
|
_signal_analysis_collected_nframes); // offset is for target buffer
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-10-20 18:57:34 +00:00
|
|
|
}
|
|
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
(*i)->connect_and_run(bufs, in_map, out_map, nframes, offset);
|
2009-05-04 15:50:51 +00:00
|
|
|
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
in_map.offset_to(*t, natural_input_streams().get(*t));
|
|
|
|
|
out_map.offset_to(*t, natural_output_streams().get(*t));
|
2009-05-04 15:50:51 +00:00
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
2008-10-20 18:57:34 +00:00
|
|
|
if (collect_signal_nframes > 0) {
|
|
|
|
|
// collect output
|
|
|
|
|
//std::cerr << " output, bufs " << bufs.count().n_audio() << " count, " << bufs.available().n_audio() << " available" << std::endl;
|
|
|
|
|
//std::cerr << " streams " << output_streams().n_audio() << std::endl;
|
2009-05-08 05:20:23 +00:00
|
|
|
|
|
|
|
|
_signal_analysis_outputs.set_count(output_streams());
|
|
|
|
|
|
2008-10-20 18:57:34 +00:00
|
|
|
for (uint32_t i = 0; i < output_streams().n_audio(); ++i) {
|
2009-05-04 15:50:51 +00:00
|
|
|
_signal_analysis_outputs.get_audio(i).read_from(
|
2009-10-14 16:10:01 +00:00
|
|
|
bufs.get_audio(i),
|
|
|
|
|
collect_signal_nframes,
|
2008-10-20 18:57:34 +00:00
|
|
|
_signal_analysis_collected_nframes); // offset is for target buffer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_signal_analysis_collected_nframes += collect_signal_nframes;
|
|
|
|
|
assert(_signal_analysis_collected_nframes <= _signal_analysis_collect_nframes_max);
|
|
|
|
|
|
|
|
|
|
if (_signal_analysis_collected_nframes == _signal_analysis_collect_nframes_max) {
|
|
|
|
|
_signal_analysis_collect_nframes_max = 0;
|
|
|
|
|
_signal_analysis_collected_nframes = 0;
|
|
|
|
|
|
2009-10-14 16:10:01 +00:00
|
|
|
AnalysisDataGathered(&_signal_analysis_inputs,
|
2009-05-04 15:50:51 +00:00
|
|
|
&_signal_analysis_outputs);
|
2008-10-20 18:57:34 +00:00
|
|
|
}
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
/* leave remaining channel buffers alone */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2009-04-30 17:26:13 +00:00
|
|
|
PluginInsert::silence (nframes_t nframes)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
2009-05-04 15:50:51 +00:00
|
|
|
ChanMapping in_map(input_streams());
|
|
|
|
|
ChanMapping out_map(output_streams());
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
if (active()) {
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
|
|
|
|
(*i)->connect_and_run (_session.get_silent_buffers ((*i)->get_info()->n_inputs), in_map, out_map, nframes, 0);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
void
|
2009-11-25 23:29:52 +00:00
|
|
|
PluginInsert::run (BufferSet& bufs, sframes_t /*start_frame*/, sframes_t /*end_frame*/, nframes_t nframes, bool)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
2009-07-21 14:39:21 +00:00
|
|
|
if (_active || _pending_active) {
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
if (_session.transport_rolling()) {
|
2009-04-23 17:48:37 +00:00
|
|
|
automation_run (bufs, nframes);
|
2008-06-02 21:41:35 +00:00
|
|
|
} else {
|
2009-04-30 17:26:13 +00:00
|
|
|
connect_and_run (bufs, nframes, 0, false);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
2009-07-21 14:39:21 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
/* FIXME: type, audio only */
|
|
|
|
|
|
|
|
|
|
uint32_t in = _plugins[0]->get_info()->n_inputs.n_audio();
|
|
|
|
|
uint32_t out = _plugins[0]->get_info()->n_outputs.n_audio();
|
|
|
|
|
|
|
|
|
|
if (out > in) {
|
|
|
|
|
|
|
|
|
|
/* not active, but something has make up for any channel count increase */
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
for (uint32_t n = out - in; n < out; ++n) {
|
2009-04-23 17:48:37 +00:00
|
|
|
memcpy (bufs.get_audio(n).data(), bufs.get_audio(in - 1).data(), sizeof (Sample) * nframes);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bufs.count().set_audio(out);
|
|
|
|
|
}
|
2009-07-21 14:39:21 +00:00
|
|
|
|
|
|
|
|
_active = _pending_active;
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2008-09-29 22:47:40 +00:00
|
|
|
PluginInsert::set_parameter (Evoral::Parameter param, float val)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
if (param.type() != PluginAutomation)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* the others will be set from the event triggered by this */
|
|
|
|
|
|
|
|
|
|
_plugins[0]->set_parameter (param.id(), val);
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-09-28 21:20:43 +00:00
|
|
|
boost::shared_ptr<AutomationControl> ac
|
2010-02-05 20:03:57 +00:00
|
|
|
= boost::dynamic_pointer_cast<AutomationControl>(control(param));
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-09-28 21:20:43 +00:00
|
|
|
if (ac) {
|
|
|
|
|
ac->set_value(val);
|
|
|
|
|
} else {
|
|
|
|
|
warning << "set_parameter called for nonexistant parameter "
|
2008-09-29 22:47:40 +00:00
|
|
|
<< EventTypeMap::instance().to_symbol(param) << endmsg;
|
2008-09-28 21:20:43 +00:00
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
_session.set_dirty();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
float
|
2008-09-29 22:47:40 +00:00
|
|
|
PluginInsert::get_parameter (Evoral::Parameter param)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
2010-02-03 00:52:45 +00:00
|
|
|
if (param.type() != PluginAutomation) {
|
2008-06-02 21:41:35 +00:00
|
|
|
return 0.0;
|
2010-02-03 00:52:45 +00:00
|
|
|
} else {
|
|
|
|
|
assert (!_plugins.empty ());
|
|
|
|
|
return _plugins[0]->get_parameter (param.id());
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2009-04-23 17:48:37 +00:00
|
|
|
PluginInsert::automation_run (BufferSet& bufs, nframes_t nframes)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
2008-09-29 22:47:40 +00:00
|
|
|
Evoral::ControlEvent next_event (0, 0.0f);
|
2008-06-02 21:41:35 +00:00
|
|
|
nframes_t now = _session.transport_frame ();
|
|
|
|
|
nframes_t end = now + nframes;
|
2009-04-23 17:48:37 +00:00
|
|
|
nframes_t offset = 0;
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2010-02-05 20:03:57 +00:00
|
|
|
Glib::Mutex::Lock lm (control_lock(), Glib::TRY_LOCK);
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
if (!lm.locked()) {
|
|
|
|
|
connect_and_run (bufs, nframes, offset, false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2010-08-16 19:58:34 +00:00
|
|
|
if (!find_next_event (now, end, next_event) || requires_fixed_sized_buffers()) {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
|
|
|
|
/* no events have a time within the relevant range */
|
|
|
|
|
|
|
|
|
|
connect_and_run (bufs, nframes, offset, true, now);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (nframes) {
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
nframes_t cnt = min (((nframes_t) ceil (next_event.when) - now), nframes);
|
2009-10-14 16:10:01 +00:00
|
|
|
|
|
|
|
|
connect_and_run (bufs, cnt, offset, true, now);
|
|
|
|
|
|
|
|
|
|
nframes -= cnt;
|
|
|
|
|
offset += cnt;
|
2008-06-02 21:41:35 +00:00
|
|
|
now += cnt;
|
|
|
|
|
|
2010-02-05 20:03:57 +00:00
|
|
|
if (!find_next_event (now, end, next_event)) {
|
2008-06-02 21:41:35 +00:00
|
|
|
break;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* cleanup anything that is left to do */
|
|
|
|
|
|
|
|
|
|
if (nframes) {
|
|
|
|
|
connect_and_run (bufs, nframes, offset, true, now);
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
float
|
2008-09-19 06:30:49 +00:00
|
|
|
PluginInsert::default_parameter_value (const Evoral::Parameter& param)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
if (param.type() != PluginAutomation)
|
|
|
|
|
return 1.0;
|
|
|
|
|
|
|
|
|
|
if (_plugins.empty()) {
|
|
|
|
|
fatal << _("programming error: ") << X_("PluginInsert::default_parameter_value() called with no plugin")
|
|
|
|
|
<< endmsg;
|
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _plugins[0]->default_value (param.id());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boost::shared_ptr<Plugin>
|
|
|
|
|
PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
|
|
|
|
|
{
|
|
|
|
|
boost::shared_ptr<LadspaPlugin> lp;
|
|
|
|
|
#ifdef HAVE_SLV2
|
|
|
|
|
boost::shared_ptr<LV2Plugin> lv2p;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef VST_SUPPORT
|
|
|
|
|
boost::shared_ptr<VSTPlugin> vp;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_AUDIOUNITS
|
|
|
|
|
boost::shared_ptr<AUPlugin> ap;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if ((lp = boost::dynamic_pointer_cast<LadspaPlugin> (other)) != 0) {
|
|
|
|
|
return boost::shared_ptr<Plugin> (new LadspaPlugin (*lp));
|
|
|
|
|
#ifdef HAVE_SLV2
|
|
|
|
|
} else if ((lv2p = boost::dynamic_pointer_cast<LV2Plugin> (other)) != 0) {
|
|
|
|
|
return boost::shared_ptr<Plugin> (new LV2Plugin (*lv2p));
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef VST_SUPPORT
|
|
|
|
|
} else if ((vp = boost::dynamic_pointer_cast<VSTPlugin> (other)) != 0) {
|
|
|
|
|
return boost::shared_ptr<Plugin> (new VSTPlugin (*vp));
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef HAVE_AUDIOUNITS
|
|
|
|
|
} else if ((ap = boost::dynamic_pointer_cast<AUPlugin> (other)) != 0) {
|
|
|
|
|
return boost::shared_ptr<Plugin> (new AUPlugin (*ap));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fatal << string_compose (_("programming error: %1"),
|
|
|
|
|
X_("unknown plugin type in PluginInsert::plugin_factory"))
|
|
|
|
|
<< endmsg;
|
|
|
|
|
/*NOTREACHED*/
|
|
|
|
|
return boost::shared_ptr<Plugin> ((Plugin*) 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
PluginInsert::configure_io (ChanCount in, ChanCount out)
|
|
|
|
|
{
|
2008-09-10 15:03:30 +00:00
|
|
|
if (set_count (count_for_configuration (in, out)) < 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if we're running replicated plugins, each plugin has
|
|
|
|
|
the same i/o configuration and we may need to announce how many
|
|
|
|
|
output streams there are.
|
|
|
|
|
|
|
|
|
|
if we running a single plugin, we need to configure it.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (_plugins.front()->configure_io (in, out) < 0) {
|
2008-06-02 21:41:35 +00:00
|
|
|
return false;
|
|
|
|
|
}
|
2008-09-10 15:03:30 +00:00
|
|
|
|
2008-10-20 18:57:34 +00:00
|
|
|
// we don't know the analysis window size, so we must work with the
|
|
|
|
|
// current buffer size here. each request for data fills in these
|
2009-10-14 16:10:01 +00:00
|
|
|
// buffers and the analyser makes sure it gets enough data for the
|
2008-10-20 18:57:34 +00:00
|
|
|
// analysis window
|
2009-05-04 15:50:51 +00:00
|
|
|
session().ensure_buffer_set (_signal_analysis_inputs, in);
|
2009-05-08 05:20:23 +00:00
|
|
|
//_signal_analysis_inputs.set_count (in);
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
session().ensure_buffer_set (_signal_analysis_outputs, out);
|
2009-05-08 05:20:23 +00:00
|
|
|
//_signal_analysis_outputs.set_count (out);
|
|
|
|
|
|
2009-05-16 13:37:48 +00:00
|
|
|
// std::cerr << "set counts to i" << in.n_audio() << "/o" << out.n_audio() << std::endl;
|
2008-10-20 18:57:34 +00:00
|
|
|
|
2008-09-10 15:03:30 +00:00
|
|
|
return Processor::configure_io (in, out);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2008-09-10 15:03:30 +00:00
|
|
|
PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// Plugin has flexible I/O, so delegate to it
|
2008-09-10 15:03:30 +00:00
|
|
|
if (_plugins.front()->reconfigurable_io()) {
|
|
|
|
|
return _plugins.front()->can_support_io_configuration (in, out);
|
|
|
|
|
}
|
|
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
ChanCount inputs = _plugins[0]->get_info()->n_inputs;
|
2008-06-02 21:41:35 +00:00
|
|
|
ChanCount outputs = _plugins[0]->get_info()->n_outputs;
|
|
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// Plugin inputs match requested inputs exactly
|
|
|
|
|
if (inputs == in) {
|
2008-09-10 15:03:30 +00:00
|
|
|
out = outputs;
|
2008-06-02 21:41:35 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// See if replication is possible
|
|
|
|
|
// We can replicate if there exists a single factor f such that, for every type,
|
|
|
|
|
// the number of plugin inputs * f = the requested number of inputs
|
|
|
|
|
uint32_t f = 0;
|
|
|
|
|
bool can_replicate = true;
|
2008-06-02 21:41:35 +00:00
|
|
|
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// No inputs of this type
|
|
|
|
|
if (inputs.get(*t) == 0 && in.get(*t) == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Plugin has more inputs than requested, can not replicate
|
|
|
|
|
} else if (inputs.get(*t) >= in.get(*t)) {
|
2008-06-02 21:41:35 +00:00
|
|
|
can_replicate = false;
|
|
|
|
|
break;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// Plugin inputs is not a factor of requested inputs, can not replicate
|
|
|
|
|
} else if (inputs.get(*t) == 0 || in.get(*t) % inputs.get(*t) != 0) {
|
|
|
|
|
can_replicate = false;
|
|
|
|
|
break;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// Potential factor not set yet
|
|
|
|
|
} else if (f == 0) {
|
|
|
|
|
f = in.get(*t) / inputs.get(*t);;
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
// Factor for this type does not match another type, can not replicate
|
|
|
|
|
if (f != (in.get(*t) / inputs.get(*t))) {
|
|
|
|
|
can_replicate = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
if (can_replicate) {
|
2008-06-02 21:41:35 +00:00
|
|
|
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
out.set (*t, outputs.get(*t) * f);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return false;
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Number of plugin instances required to support a given channel configuration.
|
|
|
|
|
* (private helper)
|
|
|
|
|
*/
|
|
|
|
|
int32_t
|
2009-07-21 15:55:17 +00:00
|
|
|
PluginInsert::count_for_configuration (ChanCount in, ChanCount /*out*/) const
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
2008-09-10 15:03:30 +00:00
|
|
|
if (_plugins.front()->reconfigurable_io()) {
|
|
|
|
|
/* plugin has flexible I/O, so the answer is always 1 */
|
|
|
|
|
/* this could change if we ever decide to replicate AU's */
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
// FIXME: take 'out' into consideration
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
ChanCount outputs = _plugins[0]->get_info()->n_outputs;
|
|
|
|
|
ChanCount inputs = _plugins[0]->get_info()->n_inputs;
|
|
|
|
|
|
|
|
|
|
if (inputs.n_total() == 0) {
|
|
|
|
|
/* instrument plugin, always legal, but throws away any existing streams */
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inputs.n_total() == 1 && outputs == inputs
|
|
|
|
|
&& ((inputs.n_audio() == 0 && in.n_audio() == 0)
|
|
|
|
|
|| (inputs.n_midi() == 0 && in.n_midi() == 0))) {
|
|
|
|
|
/* mono plugin, replicate as needed to match in */
|
|
|
|
|
return in.n_total();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (inputs == in) {
|
|
|
|
|
/* exact match */
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// assumes in is valid, so we must be replicating
|
|
|
|
|
if (inputs.n_total() < in.n_total()
|
|
|
|
|
&& (in.n_total() % inputs.n_total() == 0)) {
|
|
|
|
|
|
|
|
|
|
return in.n_total() / inputs.n_total();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* err... */
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XMLNode&
|
|
|
|
|
PluginInsert::get_state(void)
|
|
|
|
|
{
|
|
|
|
|
return state (true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
XMLNode&
|
|
|
|
|
PluginInsert::state (bool full)
|
|
|
|
|
{
|
|
|
|
|
XMLNode& node = Processor::state (full);
|
|
|
|
|
|
2009-02-15 03:21:30 +00:00
|
|
|
node.add_property("type", _plugins[0]->state_node_name());
|
2008-06-02 21:41:35 +00:00
|
|
|
node.add_property("unique-id", _plugins[0]->unique_id());
|
|
|
|
|
node.add_property("count", string_compose("%1", _plugins.size()));
|
|
|
|
|
node.add_child_nocopy (_plugins[0]->get_state());
|
|
|
|
|
|
|
|
|
|
/* add port automation state */
|
2009-10-16 16:44:16 +00:00
|
|
|
XMLNode *autonode = new XMLNode(port_automation_node_name);
|
2008-09-29 22:47:40 +00:00
|
|
|
set<Evoral::Parameter> automatable = _plugins[0]->automatable();
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-09-29 22:47:40 +00:00
|
|
|
for (set<Evoral::Parameter>::iterator x = automatable.begin(); x != automatable.end(); ++x) {
|
2009-10-16 16:44:16 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
/*XMLNode* child = new XMLNode("port");
|
|
|
|
|
snprintf(buf, sizeof(buf), "%" PRIu32, *x);
|
|
|
|
|
child->add_property("number", string(buf));
|
2009-10-16 16:44:16 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
child->add_child_nocopy (automation_list (*x).state (full));
|
|
|
|
|
autonode->add_child_nocopy (*child);
|
|
|
|
|
*/
|
2010-02-05 20:03:57 +00:00
|
|
|
AutomationList* list = dynamic_cast<AutomationList*>(control(*x)->list().get());
|
|
|
|
|
autonode->add_child_nocopy (list->state (full));
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
node.add_child_nocopy (*autonode);
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
return node;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
2009-10-15 00:57:55 +00:00
|
|
|
PluginInsert::set_state(const XMLNode& node, int version)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
XMLNodeList nlist = node.children();
|
|
|
|
|
XMLNodeIterator niter;
|
|
|
|
|
XMLPropertyList plist;
|
|
|
|
|
const XMLProperty *prop;
|
|
|
|
|
ARDOUR::PluginType type;
|
|
|
|
|
|
|
|
|
|
if ((prop = node.property ("type")) == 0) {
|
2009-10-16 16:44:16 +00:00
|
|
|
error << _("XML node describing plugin is missing the `type' field") << endmsg;
|
2008-06-02 21:41:35 +00:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (prop->value() == X_("ladspa") || prop->value() == X_("Ladspa")) { /* handle old school sessions */
|
|
|
|
|
type = ARDOUR::LADSPA;
|
|
|
|
|
} else if (prop->value() == X_("lv2")) {
|
|
|
|
|
type = ARDOUR::LV2;
|
|
|
|
|
} else if (prop->value() == X_("vst")) {
|
|
|
|
|
type = ARDOUR::VST;
|
2009-10-16 16:44:16 +00:00
|
|
|
} else if (prop->value() == X_("audiounit")) {
|
|
|
|
|
type = ARDOUR::AudioUnit;
|
2008-06-02 21:41:35 +00:00
|
|
|
} else {
|
|
|
|
|
error << string_compose (_("unknown plugin type %1 in plugin insert state"),
|
|
|
|
|
prop->value())
|
|
|
|
|
<< endmsg;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
prop = node.property ("unique-id");
|
2009-10-16 16:44:16 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
if (prop == 0) {
|
2009-10-16 16:44:16 +00:00
|
|
|
#ifdef VST_SUPPORT
|
|
|
|
|
/* older sessions contain VST plugins with only an "id" field.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (type == ARDOUR::VST) {
|
|
|
|
|
prop = node.property ("id");
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
/* recheck */
|
|
|
|
|
|
|
|
|
|
if (prop == 0) {
|
|
|
|
|
error << _("Plugin has no unique ID field") << endmsg;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
boost::shared_ptr<Plugin> plugin;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
|
|
|
|
plugin = find_plugin (_session, prop->value(), type);
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
if (plugin == 0) {
|
|
|
|
|
error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
|
2009-10-14 16:10:01 +00:00
|
|
|
"Perhaps it was removed or moved since it was last used."), prop->value())
|
2008-06-02 21:41:35 +00:00
|
|
|
<< endmsg;
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t count = 1;
|
2009-10-16 16:44:16 +00:00
|
|
|
bool need_automatables = true;
|
|
|
|
|
|
|
|
|
|
if (_plugins.empty()) {
|
|
|
|
|
/* if we are adding the first plugin, we will need to set
|
|
|
|
|
up automatable controls.
|
|
|
|
|
*/
|
|
|
|
|
need_automatables = true;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
if ((prop = node.property ("count")) != 0) {
|
|
|
|
|
sscanf (prop->value().c_str(), "%u", &count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_plugins.size() != count) {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
_plugins.push_back (plugin);
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
for (uint32_t n = 1; n < count; ++n) {
|
2008-06-02 21:41:35 +00:00
|
|
|
_plugins.push_back (plugin_factory (plugin));
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
if (need_automatables) {
|
|
|
|
|
set_automatable ();
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-28 19:07:23 +00:00
|
|
|
/* Handle the node list for this Processor (or Insert if an A2 session) */
|
2008-06-02 21:41:35 +00:00
|
|
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
2010-03-28 19:07:23 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
if ((*niter)->name() == plugin->state_node_name()) {
|
2010-03-28 19:07:23 +00:00
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) {
|
2009-10-15 00:57:55 +00:00
|
|
|
(*i)->set_state (**niter, version);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2010-04-01 01:24:13 +00:00
|
|
|
Processor::set_state (node, version);
|
|
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
if (version < 3000) {
|
2010-03-28 19:07:23 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
|
|
|
|
if ((*niter)->name() == "Redirect") {
|
|
|
|
|
/* XXX do we need to tackle placement? i think not (pd; oct 16 2009) */
|
|
|
|
|
Processor::set_state (**niter, version);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
2010-03-28 19:07:23 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
set_parameter_state_2X (node, version);
|
2010-03-28 19:07:23 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
} else {
|
2010-04-01 01:24:13 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
set_parameter_state (node, version);
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
// The name of the PluginInsert comes from the plugin, nothing else
|
|
|
|
|
_name = plugin->get_info()->name;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2010-04-01 01:24:13 +00:00
|
|
|
/* catch up on I/O */
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
Glib::Mutex::Lock em (_session.engine().process_lock());
|
|
|
|
|
IO::PortCountChanged (max(input_streams(), output_streams()));
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
void
|
|
|
|
|
PluginInsert::set_parameter_state (const XMLNode& node, int version)
|
|
|
|
|
{
|
|
|
|
|
XMLNodeList nlist = node.children();
|
|
|
|
|
XMLNodeIterator niter;
|
|
|
|
|
|
|
|
|
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
|
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
if ((*niter)->name() != port_automation_node_name) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-10-16 16:44:16 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
XMLNodeList cnodes;
|
|
|
|
|
XMLProperty *cprop;
|
|
|
|
|
XMLNodeConstIterator iter;
|
|
|
|
|
XMLNode *child;
|
|
|
|
|
const char *port;
|
|
|
|
|
uint32_t port_id;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
cnodes = (*niter)->children ("AutomationList");
|
2009-10-14 16:10:01 +00:00
|
|
|
|
The great audio processing overhaul.
The vast majority of Route signal processing is now simply in the list of
processors. There are definitely regressions here, but there's also
a lot of things fixed. It's far too much work to let diverge anymore
regardless, so here it is.
The basic model is: A route has a fixed set of input channels (matching
its JACK input ports and diskstream). The first processor takes this
as input. The next processor is configured using the first processor's
output as input, and is allowed to choose whatever output it wants
given that input... and so on, and so on. Finally, the last processor's
requested output is used to set up the panner and create whatever Jack
ports are needed to output the data.
All 'special' internal processors (meter, fader, amp, insert, send) are
currently transparent: they read any input, and return the same set
of channels back (unmodified, except for amp).
User visible changes:
* LV2 Instrument support (tracks with both MIDI and audio channels)
* MIDI in/out plugin support
* Generic plugin replication (for MIDI plugins, MIDI/audio plugins)
* Movable meter point
Known Bugs:
* Things seem to get weird on loaded sessions
* Output delivery is sketchy
* 2.0 session loading was probably already broken...
but it's definitely broken now :)
Please test this and file bugs if you have any time...
git-svn-id: svn://localhost/ardour2/branches/3.0@5055 d708f5d6-7413-0410-9779-e7cbd77b26cf
2009-05-07 06:30:50 +00:00
|
|
|
for (iter = cnodes.begin(); iter != cnodes.end(); ++iter) {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
child = *iter;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
/* XXX this code knows way too much about the internal details of an AutomationList state node */
|
|
|
|
|
|
|
|
|
|
if ((cprop = child->property("automation-id")) != 0) {
|
2008-06-02 21:41:35 +00:00
|
|
|
port = cprop->value().c_str();
|
|
|
|
|
} else {
|
2009-10-16 16:44:16 +00:00
|
|
|
warning << _("PluginInsert: Auto: no plugin parameter number seen") << endmsg;
|
2008-06-02 21:41:35 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
if (sscanf (port, "parameter-%" PRIu32, &port_id) != 1) {
|
|
|
|
|
warning << _("PluginInsert: Auto: no parameter number found") << endmsg;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
if (port_id >= _plugins[0]->parameter_count()) {
|
2009-10-16 16:44:16 +00:00
|
|
|
warning << _("PluginInsert: Auto: plugin parameter out of range") << endmsg;
|
2008-06-02 21:41:35 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-19 00:47:49 +00:00
|
|
|
boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
|
2010-02-05 20:03:57 +00:00
|
|
|
control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
|
2008-09-19 00:47:49 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
if (c) {
|
|
|
|
|
c->alist()->set_state (*child, version);
|
2008-06-02 21:41:35 +00:00
|
|
|
} else {
|
2009-10-16 16:44:16 +00:00
|
|
|
error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
|
|
|
|
|
}
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
/* done */
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
void
|
|
|
|
|
PluginInsert::set_parameter_state_2X (const XMLNode& node, int version)
|
|
|
|
|
{
|
|
|
|
|
XMLNodeList nlist = node.children();
|
|
|
|
|
XMLNodeIterator niter;
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
/* look for port automation node */
|
|
|
|
|
|
|
|
|
|
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
if ((*niter)->name() != port_automation_node_name) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
XMLNodeList cnodes;
|
|
|
|
|
XMLProperty *cprop;
|
|
|
|
|
XMLNodeConstIterator iter;
|
|
|
|
|
XMLNode *child;
|
|
|
|
|
const char *port;
|
|
|
|
|
uint32_t port_id;
|
|
|
|
|
|
|
|
|
|
cnodes = (*niter)->children ("port");
|
|
|
|
|
|
2010-03-28 19:07:23 +00:00
|
|
|
for (iter = cnodes.begin(); iter != cnodes.end(); ++iter){
|
2009-10-16 16:44:16 +00:00
|
|
|
|
|
|
|
|
child = *iter;
|
|
|
|
|
|
|
|
|
|
if ((cprop = child->property("number")) != 0) {
|
|
|
|
|
port = cprop->value().c_str();
|
|
|
|
|
} else {
|
|
|
|
|
warning << _("PluginInsert: Auto: no ladspa port number") << endmsg;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sscanf (port, "%" PRIu32, &port_id);
|
|
|
|
|
|
|
|
|
|
if (port_id >= _plugins[0]->parameter_count()) {
|
|
|
|
|
warning << _("PluginInsert: Auto: port id out of range") << endmsg;
|
|
|
|
|
continue;
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
boost::shared_ptr<AutomationControl> c = boost::dynamic_pointer_cast<AutomationControl>(
|
2010-02-05 20:03:57 +00:00
|
|
|
control(Evoral::Parameter(PluginAutomation, 0, port_id), true));
|
2008-06-02 21:41:35 +00:00
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
if (c) {
|
|
|
|
|
if (!child->children().empty()) {
|
|
|
|
|
c->alist()->set_state (*child->children().front(), version);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
error << string_compose (_("PluginInsert: automatable control %1 not found - ignored"), port_id) << endmsg;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
/* done */
|
2009-10-16 16:44:16 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
break;
|
2009-10-16 16:44:16 +00:00
|
|
|
}
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
2009-10-16 16:44:16 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
string
|
2008-09-29 22:47:40 +00:00
|
|
|
PluginInsert::describe_parameter (Evoral::Parameter param)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
if (param.type() != PluginAutomation)
|
|
|
|
|
return Automatable::describe_parameter(param);
|
|
|
|
|
|
|
|
|
|
return _plugins[0]->describe_parameter (param);
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-14 16:10:01 +00:00
|
|
|
ARDOUR::nframes_t
|
2008-06-02 21:41:35 +00:00
|
|
|
PluginInsert::signal_latency() const
|
|
|
|
|
{
|
|
|
|
|
if (_user_latency) {
|
|
|
|
|
return _user_latency;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _plugins[0]->signal_latency ();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ARDOUR::PluginType
|
|
|
|
|
PluginInsert::type ()
|
|
|
|
|
{
|
2010-04-15 20:42:05 +00:00
|
|
|
return plugin()->get_info()->type;
|
2008-06-02 21:41:35 +00:00
|
|
|
}
|
|
|
|
|
|
2008-09-29 22:47:40 +00:00
|
|
|
PluginInsert::PluginControl::PluginControl (PluginInsert* p, const Evoral::Parameter ¶m, boost::shared_ptr<AutomationList> list)
|
2008-09-29 01:22:21 +00:00
|
|
|
: AutomationControl (p->session(), param, list, p->describe_parameter(param))
|
2008-06-02 21:41:35 +00:00
|
|
|
, _plugin (p)
|
|
|
|
|
{
|
|
|
|
|
Plugin::ParameterDescriptor desc;
|
2008-09-29 01:22:21 +00:00
|
|
|
p->plugin(0)->get_parameter_descriptor (param.id(), desc);
|
2008-06-02 21:41:35 +00:00
|
|
|
_logarithmic = desc.logarithmic;
|
|
|
|
|
_toggled = desc.toggled;
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
void
|
2010-07-27 14:09:16 +00:00
|
|
|
PluginInsert::PluginControl::set_value (double val)
|
2008-06-02 21:41:35 +00:00
|
|
|
{
|
|
|
|
|
/* FIXME: probably should be taking out some lock here.. */
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
if (_toggled) {
|
|
|
|
|
if (val > 0.5) {
|
|
|
|
|
val = 1.0;
|
|
|
|
|
} else {
|
|
|
|
|
val = 0.0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
/*const float range = _list->get_max_y() - _list->get_min_y();
|
|
|
|
|
const float lower = _list->get_min_y();
|
|
|
|
|
|
|
|
|
|
if (!_logarithmic) {
|
|
|
|
|
val = lower + (range * val);
|
|
|
|
|
} else {
|
|
|
|
|
float log_lower = 0.0f;
|
|
|
|
|
if (lower > 0.0f) {
|
|
|
|
|
log_lower = log(lower);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
val = exp(log_lower + log(range) * val);
|
|
|
|
|
}*/
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
for (Plugins::iterator i = _plugin->_plugins.begin();
|
2008-09-29 01:22:21 +00:00
|
|
|
i != _plugin->_plugins.end(); ++i) {
|
2008-06-02 21:41:35 +00:00
|
|
|
(*i)->set_parameter (_list->parameter().id(), val);
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-13 19:45:20 +00:00
|
|
|
boost::shared_ptr<Plugin> iasp = _plugin->_impulseAnalysisPlugin.lock();
|
|
|
|
|
if (iasp) {
|
|
|
|
|
iasp->set_parameter (_list->parameter().id(), val);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
AutomationControl::set_value(val);
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-27 14:09:16 +00:00
|
|
|
double
|
2008-06-02 21:41:35 +00:00
|
|
|
PluginInsert::PluginControl::get_value (void) const
|
|
|
|
|
{
|
|
|
|
|
/* FIXME: probably should be taking out some lock here.. */
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2010-07-27 14:09:16 +00:00
|
|
|
double val = _plugin->get_parameter (_list->parameter());
|
2008-06-02 21:41:35 +00:00
|
|
|
|
|
|
|
|
return val;
|
|
|
|
|
|
|
|
|
|
/*if (_toggled) {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
return val;
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
} else {
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
if (_logarithmic) {
|
|
|
|
|
val = log(val);
|
|
|
|
|
}
|
2009-10-14 16:10:01 +00:00
|
|
|
|
2008-06-02 21:41:35 +00:00
|
|
|
return ((val - lower) / range);
|
|
|
|
|
}*/
|
|
|
|
|
}
|
|
|
|
|
|
2008-10-13 19:45:20 +00:00
|
|
|
boost::shared_ptr<Plugin>
|
|
|
|
|
PluginInsert::get_impulse_analysis_plugin()
|
|
|
|
|
{
|
|
|
|
|
boost::shared_ptr<Plugin> ret;
|
|
|
|
|
if (_impulseAnalysisPlugin.expired()) {
|
|
|
|
|
ret = plugin_factory(_plugins[0]);
|
|
|
|
|
_impulseAnalysisPlugin = ret;
|
|
|
|
|
} else {
|
|
|
|
|
ret = _impulseAnalysisPlugin.lock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-04 15:50:51 +00:00
|
|
|
void
|
|
|
|
|
PluginInsert::collect_signal_for_analysis(nframes_t nframes)
|
|
|
|
|
{
|
|
|
|
|
// called from outside the audio thread, so this should be safe
|
2009-05-08 05:20:23 +00:00
|
|
|
// only do audio as analysis is (currently) only for audio plugins
|
2009-10-14 16:10:01 +00:00
|
|
|
_signal_analysis_inputs.ensure_buffers( DataType::AUDIO, input_streams().n_audio(), nframes);
|
|
|
|
|
_signal_analysis_outputs.ensure_buffers( DataType::AUDIO, output_streams().n_audio(), nframes);
|
2009-05-04 15:50:51 +00:00
|
|
|
|
|
|
|
|
_signal_analysis_collected_nframes = 0;
|
2009-10-14 16:10:01 +00:00
|
|
|
_signal_analysis_collect_nframes_max = nframes;
|
2009-05-04 15:50:51 +00:00
|
|
|
}
|
|
|
|
|
|