diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc index 2b260bcb5a..78d69ba6bf 100644 --- a/gtk2_ardour/mixer_strip.cc +++ b/gtk2_ardour/mixer_strip.cc @@ -407,7 +407,8 @@ MixerStrip::set_route (boost::shared_ptr rt) midi_input_enable_button = manage (new StatefulToggleButton); midi_input_enable_button->set_name ("MixerMidiInputEnableButton"); midi_input_enable_button->set_image (*img); - midi_input_enable_button->signal_toggled().connect (sigc::mem_fun (*this, &MixerStrip::midi_input_toggled)); + midi_input_enable_button->signal_button_press_event().connect (sigc::mem_fun (*this, &MixerStrip::input_active_button_press), false); + midi_input_enable_button->signal_button_release_event().connect (sigc::mem_fun (*this, &MixerStrip::input_active_button_release), false); ARDOUR_UI::instance()->set_tip (midi_input_enable_button, _("Enable/Disable MIDI input")); } else { input_button_box.remove (*midi_input_enable_button); @@ -1915,16 +1916,40 @@ MixerStrip::hide_things () processor_box.hide_things (); } -void -MixerStrip::midi_input_toggled () +bool +MixerStrip::input_active_button_press (GdkEventButton* ev) +{ + /* nothing happens on press */ + return true; +} + +bool +MixerStrip::input_active_button_release (GdkEventButton* ev) { boost::shared_ptr mt = midi_track (); if (!mt) { - return; + return true; } - mt->set_input_active (midi_input_enable_button->get_active()); + if (mt->input_active()) { + if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) { + /* turn all other tracks using this input off */ + _session->set_exclusive_input_active (mt, false); + } else { + mt->set_input_active (false); + } + + } else { + if (Keyboard::modifier_state_contains (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::SecondaryModifier))) { + /* turn all other tracks using this input on */ + _session->set_exclusive_input_active (mt, true); + } else { + mt->set_input_active (true); + } + } + + return true; } void diff --git a/gtk2_ardour/mixer_strip.h b/gtk2_ardour/mixer_strip.h index de907a3607..863aab2ee6 100644 --- a/gtk2_ardour/mixer_strip.h +++ b/gtk2_ardour/mixer_strip.h @@ -188,7 +188,8 @@ class MixerStrip : public RouteUI, public Gtk::EventBox std::string longest_label; void midi_input_status_changed (); - void midi_input_toggled (); + bool input_active_button_press (GdkEventButton*); + bool input_active_button_release (GdkEventButton*); gint mark_update_safe (); guint32 mode_switch_in_progress; diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 865971b377..062abac4f4 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -107,6 +107,7 @@ class IO : public SessionObject, public Latent int disconnect (Port *our_port, std::string other_port, void *src); int disconnect (void *src); bool connected_to (boost::shared_ptr) const; + bool connected_to (const std::string&) const; bool connected () const; bool physically_connected () const; diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 004ff41f83..6b9010642c 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -238,6 +238,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi boost::shared_ptr route_by_name (std::string); boost::shared_ptr route_by_id (PBD::ID); boost::shared_ptr route_by_remote_id (uint32_t id); + void routes_using_input_from (const std::string& str, RouteList& rl); bool route_name_unique (std::string) const; bool route_name_internal (std::string) const; @@ -608,6 +609,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi void set_listen (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_record_enabled (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); void set_solo_isolated (boost::shared_ptr, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false); + void set_exclusive_input_active (boost::shared_ptr rt, bool others_on); PBD::Signal1 SoloActive; PBD::Signal0 SoloChanged; diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 5c2cdcf53e..13d22e6592 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -1519,6 +1519,18 @@ IO::connected_to (boost::shared_ptr other) const return false; } +bool +IO::connected_to (const string& str) const +{ + for (PortSet::const_iterator i = _ports.begin(); i != _ports.end(); ++i) { + if (i->connected_to (str)) { + return true; + } + } + + return false; +} + void IO::process_input (boost::shared_ptr proc, framepos_t start_frame, framepos_t end_frame, pframes_t nframes) { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index ecdd9bca8d..d4af9b6766 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -2466,6 +2466,62 @@ Session::io_name_is_legal (const std::string& name) return true; } +void +Session::set_exclusive_input_active (boost::shared_ptr rt, bool others_on) +{ + RouteList rl; + vector connections; + + PortSet& ps (rt->input()->ports()); + + for (PortSet::iterator p = ps.begin(); p != ps.end(); ++p) { + p->get_connections (connections); + } + + for (vector::iterator s = connections.begin(); s != connections.end(); ++s) { + routes_using_input_from (*s, rl); + } + + /* scan all relevant routes to see if others are on or off */ + + bool others_are_already_on = false; + + for (RouteList::iterator r = rl.begin(); r != rl.end(); ++r) { + if ((*r) != rt) { + boost::shared_ptr mt = boost::dynamic_pointer_cast (*r); + if (mt) { + if (mt->input_active()) { + others_are_already_on = true; + break; + } + } + } + } + + /* globally reverse other routes */ + + for (RouteList::iterator r = rl.begin(); r != rl.end(); ++r) { + if ((*r) != rt) { + boost::shared_ptr mt = boost::dynamic_pointer_cast (*r); + if (mt) { + mt->set_input_active (!others_are_already_on); + } + } + } +} + +void +Session::routes_using_input_from (const string& str, RouteList& rl) +{ + boost::shared_ptr r = routes.reader (); + + for (RouteList::iterator i = r->begin(); i != r->end(); ++i) { + if ((*i)->input()->connected_to (str)) { + rl.push_back (*i); + } + } +} + boost::shared_ptr Session::route_by_name (string name) {