13
0

rework MIDI [processor|plugin] chain

* forward midi-data around plugins that have no MIDI-out
* allow to insert plugins with no MIDI-input at a point with one MIDI-channel

This works because excess ports (both plugin and route) remain
unconnected and use scratch-buffers.

Tested with LV2, LXVST and LADSPA.
(AU plugins with variable in/out retain the old behavior, no bypass)

fixes http://tracker.ardour.org/view.php?id=5630
This commit is contained in:
Robin Gareus 2013-08-02 03:39:00 +02:00
parent 28f3d76e7c
commit bfd50cdeb0
29 changed files with 53 additions and 39 deletions

View File

@ -61,7 +61,7 @@ Amp::display_name() const
}
bool
Amp::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
Amp::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -40,7 +40,7 @@ public:
bool visible () const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);

View File

@ -104,7 +104,7 @@ class AUPlugin : public ARDOUR::Plugin
bool has_editor () const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
ChanCount output_streams() const;
ChanCount input_streams() const;
bool configure_io (ChanCount in, ChanCount out);

View File

@ -38,7 +38,7 @@ class CapturingProcessor : public Processor
int set_block_size (pframes_t nframes);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool result_required);
bool configure_io (ChanCount in, ChanCount out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
virtual XMLNode& state (bool);
private:

View File

@ -67,7 +67,7 @@ public:
std::string display_name() const;
Role role() const { return _role; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);

View File

@ -39,7 +39,7 @@ class InternalReturn : public Return
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
bool configure_io (ChanCount, ChanCount);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
void add_send (InternalSend *);
void remove_send (InternalSend *);

View File

@ -42,7 +42,7 @@ class InternalSend : public Send
void cycle_start (pframes_t);
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
bool feeds (boost::shared_ptr<Route> other) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
int set_block_size (pframes_t);

View File

@ -56,7 +56,7 @@ public:
void reset ();
void reset_max ();
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
/* special method for meter, to ensure that it can always handle the maximum

View File

@ -118,7 +118,7 @@ public:
int set_state (const XMLNode&, int /* version */);
bool configure_io (ChanCount in, ChanCount out);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
void set_cut_all (bool);
void set_dim_all (bool);

View File

@ -53,7 +53,7 @@ public:
std::string describe_parameter (Evoral::Parameter param);
bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return true; };
bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) { return true; };
void configure_io (ChanCount in, ChanCount out);
/// The fundamental Panner function

View File

@ -242,7 +242,7 @@ class Plugin : public PBD::StatefulDestructible, public Latent
/* specific types of plugins can overload this. As of September 2008, only
AUPlugin does this.
*/
virtual bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) const { return false; }
virtual bool can_support_io_configuration (const ChanCount& /*in*/, ChanCount& /*out*/) { return false; }
virtual ChanCount output_streams() const;
virtual ChanCount input_streams() const;

View File

@ -69,7 +69,7 @@ class PluginInsert : public Processor
bool set_count (uint32_t num);
uint32_t get_count () const { return _plugins.size(); }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
bool has_no_inputs() const;
@ -160,6 +160,8 @@ class PluginInsert : public Processor
BufferSet _signal_analysis_inputs;
BufferSet _signal_analysis_outputs;
ChanCount midi_bypass;
/** Description of how we can match our plugin's IO to our own insert IO */
struct Match {
Match () : method (Impossible), plugins (0) {}
@ -170,7 +172,7 @@ class PluginInsert : public Processor
ChanCount hide; ///< number of channels to hide
};
Match private_can_support_io_configuration (ChanCount const &, ChanCount &) const;
Match private_can_support_io_configuration (ChanCount const &, ChanCount &);
/** details of the match currently being used */
Match _match;

View File

@ -57,7 +57,7 @@ class PortInsert : public IOProcessor
bool set_name (const std::string& name);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
void activate ();

View File

@ -82,7 +82,7 @@ class Processor : public SessionObject, public Automatable, public Latent
/* Derived classes should override these, or processor appears as an in-place pass-through */
virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const = 0;
virtual bool can_support_io_configuration (const ChanCount& in, ChanCount& out) = 0;
virtual ChanCount input_streams () const { return _configured_input; }
virtual ChanCount output_streams() const { return _configured_output; }

View File

@ -56,7 +56,7 @@ public:
uint32_t pans_required() const { return _configured_input.n_audio(); }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
static uint32_t how_many_returns();

View File

@ -56,7 +56,7 @@ class Send : public Delivery
void run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pframes_t nframes, bool);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool can_support_io_configuration (const ChanCount& in, ChanCount& out);
bool configure_io (ChanCount in, ChanCount out);
void activate ();

View File

@ -49,7 +49,7 @@ public:
return false;
}
bool can_support_io_configuration (const ChanCount &, ChanCount &) const {
bool can_support_io_configuration (const ChanCount &, ChanCount &) {
return false;
}

View File

@ -998,7 +998,7 @@ AUPlugin::output_streams() const
}
bool
AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
AUPlugin::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
// Note: We never attempt to multiply-instantiate plugins to meet io configurations.

View File

@ -62,7 +62,7 @@ CapturingProcessor::configure_io (ChanCount in, ChanCount out)
}
bool
CapturingProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
CapturingProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -124,7 +124,7 @@ Delivery::display_name () const
}
bool
Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
Delivery::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
if (_role == Main) {

View File

@ -80,7 +80,7 @@ InternalReturn::get_state()
}
bool
InternalReturn::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
InternalReturn::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -284,7 +284,7 @@ InternalSend::connect_when_legal ()
}
bool
InternalSend::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
InternalSend::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -165,7 +165,7 @@ PeakMeter::reset_max ()
}
bool
PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
PeakMeter::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -355,7 +355,7 @@ MonitorProcessor::configure_io (ChanCount in, ChanCount out)
}
bool
MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
MonitorProcessor::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -145,7 +145,7 @@ PluginInsert::output_streams() const
ChanCount out = info->n_outputs;
// DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, static output streams = %1 for %2 plugins\n", out, _plugins.size()));
out.set_audio (out.n_audio() * _plugins.size());
out.set_midi (out.n_midi() * _plugins.size());
out.set_midi (out.n_midi() * _plugins.size() + midi_bypass.n_midi());
return out;
}
}
@ -465,7 +465,6 @@ PluginInsert::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end
}
} else {
if (has_no_audio_inputs()) {
/* silence all (audio) outputs. Should really declick
@ -704,7 +703,7 @@ PluginInsert::configure_io (ChanCount in, ChanCount out)
* @return true if the given IO configuration can be supported.
*/
bool
PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
return private_can_support_io_configuration (in, out).method != Impossible;
}
@ -714,9 +713,11 @@ PluginInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
* it can be.
*/
PluginInsert::Match
PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCount& out) const
PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out)
{
PluginInfoPtr info = _plugins.front()->get_info();
ChanCount in; in += inx;
midi_bypass.reset();
if (info->reconfigurable_io()) {
/* Plugin has flexible I/O, so delegate to it */
@ -731,6 +732,15 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
ChanCount inputs = info->n_inputs;
ChanCount outputs = info->n_outputs;
if (in.get(DataType::MIDI) == 1 && outputs.get(DataType::MIDI) == 0) {
DEBUG_TRACE ( DEBUG::Processors, string_compose ("bypassing midi-data around %1\n", name()));
midi_bypass.set(DataType::MIDI, 1);
}
if (in.get(DataType::MIDI) == 1 && inputs.get(DataType::MIDI) == 0) {
DEBUG_TRACE ( DEBUG::Processors, string_compose ("hiding midi-port from plugin %1\n", name()));
in.set(DataType::MIDI, 0);
}
bool no_inputs = true;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
if (inputs.get (*t) != 0) {
@ -741,13 +751,13 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
if (no_inputs) {
/* no inputs so we can take any input configuration since we throw it away */
out = outputs;
out = outputs + midi_bypass;
return Match (NoInputs, 1);
}
/* Plugin inputs match requested inputs exactly */
if (inputs == in) {
out = outputs;
out = outputs + midi_bypass;
return Match (ExactMatch, 1);
}
@ -789,6 +799,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
out.set (*t, outputs.get(*t) * f);
}
out += midi_bypass;
return Match (Replicate, f);
}
@ -812,7 +823,7 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
}
if (can_split) {
out = outputs;
out = outputs + midi_bypass;
return Match (Split, 1);
}
@ -836,10 +847,11 @@ PluginInsert::private_can_support_io_configuration (ChanCount const & in, ChanCo
}
if (could_hide && !cannot_hide) {
out = outputs;
out = outputs + midi_bypass;
return Match (Hide, 1, hide_channels);
}
midi_bypass.reset();
return Match (Impossible, 0);
}

View File

@ -266,7 +266,7 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
}
bool
PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in;
return true;

View File

@ -136,7 +136,7 @@ Return::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame, pfra
}
bool
Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
Return::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
out = in + _input->n_ports();
return true;

View File

@ -543,11 +543,10 @@ Route::process_output_buffers (BufferSet& bufs,
if (bufs.count() != (*i)->input_streams()) {
DEBUG_TRACE (
DEBUG::Processors, string_compose (
"%1 bufs = %2 input for %3 = %4\n",
"input port mismatch %1 bufs = %2 input for %3 = %4\n",
_name, bufs.count(), (*i)->name(), (*i)->input_streams()
)
);
continue;
}
}
#endif
@ -1654,7 +1653,8 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
if (boost::dynamic_pointer_cast<UnknownProcessor> (*p)) {
DEBUG_TRACE (DEBUG::Processors, "--- CONFIGURE ABORTED due to unknown processor.\n");
break;
DEBUG_TRACE (DEBUG::Processors, "}\n");
return list<pair<ChanCount, ChanCount> > ();
}
if ((*p)->can_support_io_configuration(in, out)) {

View File

@ -270,7 +270,7 @@ Send::set_state_2X (const XMLNode& node, int /* version */)
}
bool
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out)
{
/* sends have no impact at all on the channel configuration of the
streams passing through the route. so, out == in.