13
0

variable plugin port config.

* extend plugin API (query IO ports)
* collect possible variable plugin configurations (AU, Lua)
* prepare semi-automatic configuration (presets: mono, stereo, N)
This commit is contained in:
Robin Gareus 2016-04-15 17:57:40 +02:00
parent 6f4ccfcd3b
commit 424cacfbc8
12 changed files with 211 additions and 67 deletions

View File

@ -74,6 +74,8 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
void set_parameter (uint32_t which, float val);
float get_parameter (uint32_t which) const;
PluginOutputConfiguration possible_output () const { return _output_configs; }
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
uint32_t nth_parameter (uint32_t which, bool& ok) const;
void activate ();
@ -172,6 +174,7 @@ class LIBARDOUR_API AUPlugin : public ARDOUR::Plugin
AudioBufferList* buffers;
bool _has_midi_input;
bool _has_midi_output;
PluginOutputConfiguration _output_configs;
/* despite all the cool work that apple did on their AU preset
system, they left factory presets and user presets as two

View File

@ -63,6 +63,8 @@ public:
std::string get_docs () const { return _docs; }
std::string get_parameter_docs (uint32_t) const;
PluginOutputConfiguration possible_output () const { return _output_configs; }
std::set<Evoral::Parameter> automatable() const;
void activate () { }
@ -140,6 +142,7 @@ private:
ChanCount _configured_in;
ChanCount _configured_out;
PluginOutputConfiguration _output_configs;
bool _has_midi_input;
bool _has_midi_output;

View File

@ -80,7 +80,7 @@ class LIBARDOUR_API LV2Plugin : public ARDOUR::Plugin, public ARDOUR::Workee
int get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const;
uint32_t nth_parameter (uint32_t port, bool& ok) const;
IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id);
IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const;
const void* extension_data (const char* uri) const;

View File

@ -22,6 +22,7 @@
#include <boost/shared_ptr.hpp>
#include <string>
#include <set>
#include "pbd/statefuldestructible.h"
#include "pbd/controllable.h"
@ -54,6 +55,7 @@ class AutomationControl;
typedef boost::shared_ptr<Plugin> PluginPtr;
typedef boost::shared_ptr<PluginInfo> PluginInfoPtr;
typedef std::list<PluginInfoPtr> PluginInfoList;
typedef std::set<uint32_t> PluginOutputConfiguration;
/** A plugin is an external module (usually 3rd party provided) loaded into Ardour
* for the purpose of digital signal processing.
@ -124,7 +126,8 @@ class LIBARDOUR_API Plugin : public PBD::StatefulDestructible, public Latent
bool is_sidechain;
};
virtual IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id);
virtual IOPortDescription describe_io_port (DataType dt, bool input, uint32_t id) const;
virtual PluginOutputConfiguration possible_output () const;
virtual void set_automation_control (uint32_t /*port_index*/, boost::shared_ptr<ARDOUR::AutomationControl>) { }

View File

@ -134,7 +134,8 @@ class LIBARDOUR_API PluginInsert : public Processor
}
}
ChanCount required_buffers () const { return _required_buffers; }
const ChanCount& required_buffers () const { return _required_buffers; }
const ChanCount& preset_out () const { return _preset_out; }
// allow to override output_streams(), implies "Custom Mode"
@ -144,6 +145,7 @@ class LIBARDOUR_API PluginInsert : public Processor
void set_outputs (const ChanCount&);
void set_strict_io (bool b);
void set_custom_cfg (bool b);
bool set_preset_out (const ChanCount&);
bool add_sidechain (uint32_t n_audio = 1);
bool del_sidechain ();
boost::shared_ptr<SideChain> sidechain () const { return _sidechain; }
@ -306,6 +308,7 @@ class LIBARDOUR_API PluginInsert : public Processor
ChanCount _configured_internal; // with side-chain
ChanCount _configured_out;
ChanCount _custom_out;
ChanCount _preset_out;
ChanCount _cached_sidechain_pins;
ChanCount _required_buffers;
@ -317,6 +320,7 @@ class LIBARDOUR_API PluginInsert : public Processor
bool _mapping_changed;
Match private_can_support_io_configuration (ChanCount const &, ChanCount &) const;
Match internal_can_support_io_configuration (ChanCount const &, ChanCount &) const;
Match automatic_can_support_io_configuration (ChanCount const &, ChanCount &) const;
/** details of the match currently being used */

View File

@ -313,6 +313,7 @@ class LIBARDOUR_API Route : public SessionObject, public Automatable, public Rou
*/
bool customize_plugin_insert (boost::shared_ptr<Processor> proc, uint32_t count, ChanCount outs);
bool add_remove_sidechain (boost::shared_ptr<Processor> proc, bool);
bool plugin_preset_output (boost::shared_ptr<Processor> proc, ChanCount outs);
/* enable sidechain input for a given processor
*

View File

@ -1133,8 +1133,7 @@ AUPlugin::output_streams() const
bool
AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
{
// Note: We never attempt to multiply-instantiate plugins to meet io configurations.
_output_configs.clear ();
const int32_t audio_in = in.n_audio();
int32_t audio_out;
AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info());
@ -1151,7 +1150,10 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
name(), io_configs.size(), in, out));
// preferred setting (provided by plugin_insert)
const int preferred_out = out.n_audio ();
audio_out = out.n_audio ();
bool found = false;
bool exact_match = false;
/* kAudioUnitProperty_SupportedNumChannels
* https://developer.apple.com/library/mac/documentation/MusicAudio/Conceptual/AudioUnitProgrammingGuide/TheAudioUnit/TheAudioUnit.html#//apple_ref/doc/uid/TP40003278-CH12-SW20
@ -1184,35 +1186,43 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
int32_t possible_in = i->first;
int32_t possible_out = i->second;
if ((possible_in == audio_in) && (possible_out == audio_out)) {
if ((possible_in == audio_in) && (possible_out == preferred_out)) {
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: %1 in %2 out to match in %3 out %4\n",
possible_in, possible_out,
in, out));
possible_in, possible_out,
in, out));
out.set (DataType::MIDI, 0);
out.set (DataType::AUDIO, audio_out);
return true;
// exact match
_output_configs.insert (preferred_out);
exact_match = true;
found = true;
break;
}
}
/* now allow potentially "imprecise" matches */
audio_out = -1;
bool found = false;
int32_t audio_out = -1;
float penalty = 9999;
const int preferred_out = out.n_audio ();
int used_possible_in = 0;
#define FOUNDCFG(nch) { \
float p = fabsf ((float)(nch) - preferred_out); \
if ((nch) > preferred_out) { p *= 1.1; } \
if (p < penalty) { \
used_possible_in = possible_in; \
audio_out = (nch); \
penalty = p; \
found = true; \
} \
#define FOUNDCFG(nch) { \
float p = fabsf ((float)(nch) - preferred_out); \
_output_configs.insert (nch); \
if ((nch) > preferred_out) { p *= 1.1; } \
if (p < penalty) { \
used_possible_in = possible_in; \
audio_out = (nch); \
penalty = p; \
found = true; \
} \
}
#define ANYTHINGGOES \
_output_configs.insert (0);
#define UPTO(nch) { \
for (int n = 1; n < nch; ++n) { \
_output_configs.insert (n); \
} \
}
for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
@ -1233,12 +1243,15 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
if (possible_out == -1) {
/* any configuration possible, provide stereo output */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid, should be (0, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* variable number of outputs up to -N, */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out);
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -1253,11 +1266,13 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
} else if (possible_out == -2) {
/* any configuration possible, pick matching */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* explicitly variable number of outputs, pick maximum */
FOUNDCFG (max (-possible_out, preferred_out));
/* and try min, too, in case the penalty is lower */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -1268,13 +1283,16 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
if (possible_out == -1) {
/* any configuration possible, pick matching */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid. interpret as (-1, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* invalid, interpret as (<-2, <-2)
* variable number of outputs up to -N, */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -1291,14 +1309,17 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
if (audio_in > -possible_in && imprecise == NULL) {
/* request is too large */
} else if (possible_out == -1) {
/* any output configuration possible, provide stereo out */
/* any output configuration possible */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid. interpret as (<-2, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* variable number of outputs up to -N, */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -1310,15 +1331,16 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
if (possible_out == -1) {
/* any output configuration possible */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* plugins shouldn't really use (>0,-2) but might.
* interpret as (>0,-1):
*/
/* plugins shouldn't really use (>0,-2), interpret as (>0,-1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* > 0, < -2 is not specified
* interpret as up to -N */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -1350,20 +1372,24 @@ AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out, Cha
}
}
if (found) {
if (!found) {
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tFAIL: no io configs match %1\n", in));
return false;
}
if (exact_match) {
out.set (DataType::MIDI, 0); // currently always zero
out.set (DataType::AUDIO, preferred_out);
} else {
if (used_possible_in < -2 && audio_in == 0) {
// input-port count cannot be zero, use as many ports
// as outputs, but at most abs(possible_in)
audio_input_cnt = max (1, min (audio_out, -used_possible_in));
}
out.set (DataType::MIDI, 0); /// XXX
out.set (DataType::AUDIO, audio_out);
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: in %1 out %2\n", in, out));
} else {
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tFAIL: no io configs match %1\n", in));
return false;
}
DEBUG_TRACE (DEBUG::AudioUnits, string_compose ("\tCHOSEN: in %1 out %2\n", in, out));
return true;
}

View File

@ -311,6 +311,7 @@ bool
LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, ChanCount* imprecise)
{
// caller must hold process lock (no concurrent calls to interpreter
_output_configs.clear ();
if (in.n_midi() > 0 && !_has_midi_input && !imprecise) {
return false;
@ -322,14 +323,9 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
return false;
}
luabridge::LuaRef table = luabridge::getGlobal (L, "table"); //lua std lib
luabridge::LuaRef tablesort = table["sort"];
assert (tablesort.isFunction ());
luabridge::LuaRef *_iotable = NULL; // can't use reference :(
try {
luabridge::LuaRef iotable = ioconfig ();
tablesort (iotable);
if (iotable.isTable ()) {
_iotable = new luabridge::LuaRef (iotable);
}
@ -349,13 +345,14 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
return false;
}
bool found = false;
bool exact_match = false;
const int32_t audio_in = in.n_audio ();
int32_t audio_out;
int32_t midi_out = 0; // TODO handle _has_midi_output
// preferred setting (provided by plugin_insert)
assert (out.n_audio () > 0);
audio_out = out.n_audio ();
const int preferred_out = out.n_audio ();
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
assert (i.value ().type () == LUA_TTABLE);
@ -365,28 +362,36 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
int possible_out = io["audio_out"];
// exact match
if ((possible_in == audio_in) && (possible_out == audio_out)) {
out.set (DataType::MIDI, 0);
out.set (DataType::AUDIO, audio_out);
return true;
if ((possible_in == audio_in) && (possible_out == preferred_out)) {
_output_configs.insert (preferred_out);
exact_match = true;
found = true;
break;
}
}
/* now allow potentially "imprecise" matches */
audio_out = -1;
bool found = false;
int32_t audio_out = -1;
float penalty = 9999;
const int preferred_out = out.n_audio ();
#define FOUNDCFG(nch) { \
float p = fabsf ((float)(nch) - preferred_out); \
if ((nch) > preferred_out) { p *= 1.1; } \
if (p < penalty) { \
audio_out = (nch); \
penalty = p; \
found = true; \
} \
#define FOUNDCFG(nch) { \
float p = fabsf ((float)(nch) - preferred_out); \
_output_configs.insert (nch); \
if ((nch) > preferred_out) { p *= 1.1; } \
if (p < penalty) { \
audio_out = (nch); \
penalty = p; \
found = true; \
} \
}
#define ANYTHINGGOES \
_output_configs.insert (0);
#define UPTO(nch) { \
for (int n = 1; n < nch; ++n) { \
_output_configs.insert (n); \
} \
}
for (luabridge::Iterator i (iotable); !i.isNil (); ++i) {
@ -404,12 +409,15 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
if (possible_out == -1) {
/* any configuration possible, stereo output */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid, should be (0, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* variable number of outputs up to -N, */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out);
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -424,11 +432,13 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
} else if (possible_out == -2) {
/* any configuration possible, pick matching */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* explicitly variable number of outputs, pick maximum */
FOUNDCFG (max (-possible_out, preferred_out));
/* and try min, too, in case the penalty is lower */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -436,17 +446,19 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
}
if (possible_in == -2) {
if (possible_out == -1) {
/* any configuration possible, pick matching */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid. interpret as (-1, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* invalid, interpret as (<-2, <-2)
* variable number of outputs up to -N, */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -465,12 +477,15 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
} else if (possible_out == -1) {
/* any output configuration possible */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid. interpret as (<-2, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* variable number of outputs up to -N, */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -482,13 +497,16 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
if (possible_out == -1) {
/* any output configuration possible */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out == -2) {
/* invalid. interpret as (>0, -1) */
FOUNDCFG (preferred_out);
ANYTHINGGOES;
} else if (possible_out < -2) {
/* > 0, < -2 is not specified
* interpret as up to -N */
FOUNDCFG (min (-possible_out, preferred_out));
UPTO (-possible_out)
} else {
/* exact number of outputs */
FOUNDCFG (possible_out);
@ -523,13 +541,17 @@ LuaProc::can_support_io_configuration (const ChanCount& in, ChanCount& out, Chan
}
}
if (!found) {
return false;
}
out.set (DataType::MIDI, midi_out); // currently always zero
out.set (DataType::AUDIO, audio_out);
if (exact_match) {
out.set (DataType::MIDI, midi_out); // currently always zero
out.set (DataType::AUDIO, preferred_out);
} else {
out.set (DataType::MIDI, midi_out); // currently always zero
out.set (DataType::AUDIO, audio_out);
}
return true;
}

View File

@ -1934,7 +1934,7 @@ LV2Plugin::get_parameter_descriptor(uint32_t which, ParameterDescriptor& desc) c
}
Plugin::IOPortDescription
LV2Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id)
LV2Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
{
PortFlags match = 0;
switch (dt) {

View File

@ -258,7 +258,7 @@ Plugin::input_streams () const
}
Plugin::IOPortDescription
Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id)
Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id) const
{
std::stringstream ss;
switch (dt) {
@ -278,12 +278,22 @@ Plugin::describe_io_port (ARDOUR::DataType dt, bool input, uint32_t id)
ss << _("Out") << " ";
}
ss << id;
ss << (id + 1);
Plugin::IOPortDescription iod (ss.str());
return iod;
}
PluginOutputConfiguration
Plugin::possible_output () const
{
PluginOutputConfiguration oc;
if (_info) {
oc.insert (_info->n_outputs.n_audio ());
}
return oc;
}
const Plugin::PresetRecord *
Plugin::preset_by_label (const string& label)
{

View File

@ -159,6 +159,17 @@ PluginInsert::set_custom_cfg (bool b)
}
}
bool
PluginInsert::set_preset_out (const ChanCount& c)
{
bool changed = _preset_out != c;
_preset_out = c;
if (changed && !_custom_cfg) {
PluginConfigChanged (); /* EMIT SIGNAL */
}
return changed;
}
bool
PluginInsert::add_sidechain (uint32_t n_audio)
{
@ -1383,6 +1394,8 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
ChanCount dout (in); // hint
if (_custom_cfg) {
dout = _custom_out;
} else if (_preset_out.n_audio () > 0) {
dout.set (DataType::AUDIO, _preset_out.n_audio ());
} else if (dout.n_midi () > 0 && dout.n_audio () == 0) {
dout.set (DataType::AUDIO, 2);
}
@ -1390,7 +1403,6 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
ChanCount useins;
bool const r = _plugins.front()->can_support_io_configuration (in, dout, &useins);
assert (r);
assert (dout.n_audio() <= out.n_audio()); // sans midi bypass
if (useins.n_audio() == 0) {
useins = in;
}
@ -1529,12 +1541,29 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
return private_can_support_io_configuration (in, out).method != Impossible;
}
PluginInsert::Match
PluginInsert::private_can_support_io_configuration (ChanCount const& in, ChanCount& out) const
{
if (!_custom_cfg && _preset_out.n_audio () > 0) {
// preseed hint (for variable i/o)
out.set (DataType::AUDIO, _preset_out.n_audio ());
}
Match rv = internal_can_support_io_configuration (in, out);
if (!_custom_cfg && _preset_out.n_audio () > 0) {
DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("using output preset: %1 %2\n", name(), _preset_out));
out.set (DataType::AUDIO, _preset_out.n_audio ());
}
return rv;
}
/** A private version of can_support_io_configuration which returns the method
* by which the configuration can be matched, rather than just whether or not
* it can be.
*/
PluginInsert::Match
PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
PluginInsert::internal_can_support_io_configuration (ChanCount const & inx, ChanCount& out) const
{
if (_plugins.empty()) {
return Match();
@ -1848,6 +1877,7 @@ PluginInsert::state (bool full)
* in case the plugin goes missing) */
node.add_child_nocopy (* _configured_in.state (X_("ConfiguredInput")));
node.add_child_nocopy (* _configured_out.state (X_("ConfiguredOutput")));
node.add_child_nocopy (* _preset_out.state (X_("PresetOutput")));
/* save custom i/o config */
node.add_property("custom", _custom_cfg ? "yes" : "no");
@ -2121,6 +2151,9 @@ PluginInsert::set_state(const XMLNode& node, int version)
if ((*i)->name() == X_("ConfiguredOutput")) {
_custom_out = ChanCount(**i);
}
if ((*i)->name() == X_("PresetOutput")) {
_preset_out = ChanCount(**i);
}
if (strncmp ((*i)->name ().c_str(), X_("InputMap-"), 9) == 0) {
long pc = atol (&((*i)->name().c_str()[9]));
if (pc >=0 && pc <= get_count()) {

View File

@ -2505,6 +2505,45 @@ Route::add_remove_sidechain (boost::shared_ptr<Processor> proc, bool add)
return true;
}
bool
Route::plugin_preset_output (boost::shared_ptr<Processor> proc, ChanCount outs)
{
boost::shared_ptr<PluginInsert> pi;
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(proc)) == 0) {
return false;
}
{
Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
ProcessorList::iterator i = find (_processors.begin(), _processors.end(), proc);
if (i == _processors.end ()) {
return false;
}
}
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
const ChanCount& old (pi->preset_out ());
if (!pi->set_preset_out (outs)) {
return true; // no change, OK
}
list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
if (c.empty()) {
/* not possible */
pi->set_preset_out (old);
return false;
}
configure_processors_unlocked (0);
}
processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
_session.set_dirty ();
return true;
}
bool
Route::reset_plugin_insert (boost::shared_ptr<Processor> proc)
{