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:
parent
6f4ccfcd3b
commit
424cacfbc8
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>) { }
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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()) {
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user