void collect_signal_for_analysis (framecnt_t nframes);
+ void set_strict_io (bool b) {
+ _strict_io = b;
+ }
+
+ bool strict_io_configured () const {
+ return _strict_io_configured;
+ }
+
bool splitting () const {
return _match.method == Split;
}
ChanCount _configured_in;
ChanCount _configured_out;
+ bool _strict_io;
+ bool _strict_io_configured;
+
/** Description of how we can match our plugin's IO to our own insert IO */
struct Match {
Match () : method (Impossible), plugins (0) {}
void clear_processors (Placement);
void all_visible_processors_active (bool);
+ bool strict_io () const { return _strict_io; }
+ bool set_strict_io (bool);
+
framecnt_t set_private_port_latencies (bool playback) const;
void set_public_port_latencies (framecnt_t, bool playback) const;
friend class ProcessorState;
+ bool _strict_io;
+
/* no copy construction */
Route (Route const &);
: Processor (s, (plug ? plug->name() : string ("toBeRenamed")))
, _signal_analysis_collected_nframes(0)
, _signal_analysis_collect_nframes_max(0)
+ , _strict_io (false)
+ , _strict_io_configured (false)
{
/* the first is the master */
PluginInfoPtr info = _plugins.front()->get_info();
- if (info->reconfigurable_io()) {
+ if (_strict_io_configured) {
+ return _configured_in; // XXX, check initial configuration
+ }
+ else if (info->reconfigurable_io()) {
ChanCount out = _plugins.front()->output_streams ();
// DEBUG_TRACE (DEBUG::Processors, string_compose ("Plugin insert, reconfigur(able) output streams = %1\n", out));
return out;
PluginInsert::Match
PluginInsert::private_can_support_io_configuration (ChanCount const & inx, ChanCount& out)
{
+ _strict_io_configured = false;
if (_plugins.empty()) {
return Match();
}
return Match (Impossible, 0);
}
+ if (_strict_io && in.n_audio() < out.n_audio()) {
+ DEBUG_TRACE (DEBUG::Processors, string_compose ("hiding output ports of reconfigurable %1\n", name()));
+ out.set (DataType::AUDIO, in.get (DataType::AUDIO));
+ }
+
return Match (Delegate, 1);
}
}
/* Plugin inputs match requested inputs exactly */
- if (inputs == in) {
+ if (inputs == in && (!_strict_io || outputs.n_audio() == inputs.n_audio())) {
out = outputs + midi_bypass;
return Match (ExactMatch, 1);
}
plugin inputs? Let me count the ways ...
*/
- bool can_split = true;
+ bool can_split = !_strict_io;
for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
bool const can_split_type = (in.get (*t) == 1 && inputs.get (*t) > 1);
}
if (could_hide && !cannot_hide) {
- out = outputs + midi_bypass;
+ if (_strict_io && inputs.get (DataType::AUDIO) == outputs.get (DataType::AUDIO)) {
+ _strict_io_configured = true;
+ outputs = inputs;
+ } else {
+ out = outputs + midi_bypass;
+ }
return Match (Hide, 1, hide_channels);
}
, _track_number (0)
, _in_configure_processors (false)
, _initial_io_setup (false)
+ , _strict_io (false)
, _custom_meter_position_noted (false)
{
processor_max_streams.reset();
return 1;
}
+ if (_strict_io) {
+ boost::shared_ptr<PluginInsert> pi;
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(processor)) != 0) {
+ pi->set_strict_io (true);
+ }
+ }
+
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) != 0) {
pi->set_count (1);
+ pi->set_strict_io (_strict_io);
}
_processors.insert (loc, *i);
return 1;
}
+ /* ensure that sub is not owned by another route */
+ if (sub->owner ()) {
+ return 1;
+ }
+
{
Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
Glib::Threads::RWLock::WriterLock lm (_processor_lock);
return 1;
}
+ if (_strict_io) {
+ boost::shared_ptr<PluginInsert> pi;
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(sub)) != 0) {
+ pi->set_strict_io (true);
+ }
+ }
+
if (configure_processors_unlocked (err)) {
pstate.restore ();
configure_processors_unlocked (0);
return 0;
}
+bool
+Route::set_strict_io (const bool enable)
+{
+ if (_strict_io != enable) {
+ _strict_io = enable;
+ Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
+ for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
+ boost::shared_ptr<PluginInsert> pi;
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
+ pi->set_strict_io (_strict_io);
+ }
+ }
+
+ list<pair<ChanCount, ChanCount> > c = try_configure_processors_unlocked (n_inputs (), 0);
+
+ if (c.empty()) {
+ // not possible
+ _strict_io = !enable; // restore old value
+ for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p) {
+ boost::shared_ptr<PluginInsert> pi;
+ if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*p)) != 0) {
+ pi->set_strict_io (_strict_io);
+ }
+ }
+ return false;
+ }
+ lm.release ();
+
+ {
+ Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
+ configure_processors (0);
+ }
+ processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
+ _session.set_dirty ();
+ }
+ return true;
+}
+
XMLNode&
Route::get_state()
{
node->add_property("id", buf);
node->add_property ("name", _name);
node->add_property("default-type", _default_type.to_string());
+ node->add_property ("strict-io", _strict_io);
if (_flags) {
node->add_property("flags", enum_2_string (_flags));
_flags = Flag (0);
}
+ if ((prop = node.property (X_("strict-io"))) != 0) {
+ _strict_io = string_is_affirmative (prop->value());
+ }
+
if (is_master() || is_monitor() || is_auditioner()) {
_mute_master->set_solo_ignore (true);
}
processor.reset (new UnknownProcessor (_session, **niter));
} else {
processor.reset (new PluginInsert (_session));
+ if (_strict_io) {
+ boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert>(processor);
+ pi->set_strict_io (true);
+ }
+
}
} else if (prop->value() == "port") {