From: Paul Davis Date: Wed, 6 Jul 2016 17:36:55 +0000 (-0400) Subject: restore/extend/simplify ControlProtocol API to allow tracking of selection X-Git-Tag: 5.0-pre1~304 X-Git-Url: https://main.carlh.net/gitweb/?p=ardour.git;a=commitdiff_plain;h=2047ee527c688ed2c2bedea79a7e01088da58d72;hp=eed3ea5047ae50484542cacece0df1fd9db2e4d0 restore/extend/simplify ControlProtocol API to allow tracking of selection --- diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc index f1b2f9f112..4d578409c3 100644 --- a/libs/surfaces/control_protocol/control_protocol.cc +++ b/libs/surfaces/control_protocol/control_protocol.cc @@ -49,8 +49,20 @@ PBD::Signal0 ControlProtocol::VerticalZoomOutSelected; PBD::Signal0 ControlProtocol::StepTracksDown; PBD::Signal0 ControlProtocol::StepTracksUp; +PBD::Signal1 > ControlProtocol::AddStripableToSelection; +PBD::Signal1 > ControlProtocol::SetStripableSelection; +PBD::Signal1 > ControlProtocol::ToggleStripableSelection; +PBD::Signal1 > ControlProtocol::RemoveStripableFromSelection; +PBD::Signal0 ControlProtocol::ClearStripableSelection; + PBD::Signal1 ControlProtocol::StripableSelectionChanged; +Glib::Threads::Mutex ControlProtocol::first_selected_mutex; +boost::weak_ptr ControlProtocol::_first_selected_stripable; +StripableNotificationList ControlProtocol::_last_selected; +bool ControlProtocol::selection_connected = false; +PBD::ScopedConnection ControlProtocol::selection_connection; + const std::string ControlProtocol::state_node_name ("Protocol"); ControlProtocol::ControlProtocol (Session& s, string str) @@ -58,6 +70,12 @@ ControlProtocol::ControlProtocol (Session& s, string str) , _name (str) , _active (false) { + if (!selection_connected) { + /* this is all static, connect it only once (and early), for all ControlProtocols */ + + StripableSelectionChanged.connect_same_thread (selection_connection, boost::bind (&ControlProtocol::stripable_selection_changed, _1)); + selection_connected = true; + } } ControlProtocol::~ControlProtocol () @@ -324,3 +342,35 @@ ControlProtocol::set_state (XMLNode const & node, int /* version */) return 0; } + +boost::shared_ptr +ControlProtocol::first_selected_stripable () +{ + Glib::Threads::Mutex::Lock lm (first_selected_mutex); + return _first_selected_stripable.lock(); +} + +void +ControlProtocol::set_first_selected_stripable (boost::shared_ptr s) +{ + Glib::Threads::Mutex::Lock lm (first_selected_mutex); + _first_selected_stripable = s; +} + +void +ControlProtocol::stripable_selection_changed (StripableNotificationListPtr sp) +{ + _last_selected = *sp; + + { + Glib::Threads::Mutex::Lock lm (first_selected_mutex); + + if (!_last_selected.empty()) { + _first_selected_stripable = _last_selected.front().lock(); + } else { + _first_selected_stripable = boost::weak_ptr(); + } + } + + cerr << "CP: selection now " << _last_selected.size() << endl; +} diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 496ba99083..2485ca84ac 100644 --- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -39,6 +39,7 @@ namespace ARDOUR { class Route; class Session; class Bundle; +class Stripable; class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList, public BasicUI { @@ -78,6 +79,12 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope static PBD::Signal0 StepTracksDown; static PBD::Signal0 StepTracksUp; + static PBD::Signal1 > AddStripableToSelection; + static PBD::Signal1 > SetStripableSelection; + static PBD::Signal1 > ToggleStripableSelection; + static PBD::Signal1 > RemoveStripableFromSelection; + static PBD::Signal0 ClearStripableSelection; + /* signals that one UI (e.g. the GUI) can emit to get all other UI's to respond. Typically this will always be GUI->"others" - the GUI pays no attention to these signals. @@ -85,6 +92,9 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope static PBD::Signal1 StripableSelectionChanged; + static boost::shared_ptr first_selected_stripable (); + static void set_first_selected_stripable (boost::shared_ptr); + /* the model here is as follows: we imagine most control surfaces being able to control @@ -132,6 +142,7 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope int set_state (XMLNode const &, int version); static const std::string state_node_name; + static StripableNotificationList const & last_selected() { return _last_selected; } protected: std::vector > route_table; @@ -143,6 +154,14 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope private: LIBCONTROLCP_LOCAL ControlProtocol (const ControlProtocol&); /* noncopyable */ bool _active; + + + static Glib::Threads::Mutex first_selected_mutex; + static boost::weak_ptr _first_selected_stripable; + static StripableNotificationList _last_selected; + static void stripable_selection_changed (StripableNotificationListPtr); + static bool selection_connected; + static PBD::ScopedConnection selection_connection; }; extern "C" { diff --git a/libs/surfaces/generic_midi/midifunction.cc b/libs/surfaces/generic_midi/midifunction.cc index 4d2b19fdfd..3a60f53961 100644 --- a/libs/surfaces/generic_midi/midifunction.cc +++ b/libs/surfaces/generic_midi/midifunction.cc @@ -167,7 +167,8 @@ MIDIFunction::execute () if (!_argument.empty()) { uint32_t rid; sscanf (_argument.c_str(), "%d", &rid); - _ui->toggle_selection (rid, ARDOUR::PresentationInfo::Flag (ARDOUR::PresentationInfo::Route|ARDOUR::PresentationInfo::VCA)); + // XX fix me ... need to get stripable, not RID + //_ui->toggle_selection (rid, ARDOUR::PresentationInfo::Flag (ARDOUR::PresentationInfo::Route|ARDOUR::PresentationInfo::VCA)); DEBUG_TRACE (DEBUG::GenericMidi, string_compose ("Function: SetRouteSelection = %1\n", rid)); } break; diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index 222b1177a8..c1786756a4 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -289,12 +289,12 @@ MackieControlProtocol::get_sorted_stripables() switch (_view_mode) { case Mixer: - if (!is_hidden (s)) { + if (!s->presentation_info().hidden()) { sorted.push_back (s); } break; case AudioTracks: - if (is_audio_track(s) && !is_hidden(s)) { + if (is_audio_track(s) && !s->presentation_info().hidden()) { sorted.push_back (s); } break; @@ -306,13 +306,13 @@ MackieControlProtocol::get_sorted_stripables() } #endif } else { - if (!is_track(s) && !is_hidden(s)) { + if (!is_track(s) && !s->presentation_info().hidden()) { sorted.push_back (s); } } break; case MidiTracks: - if (is_midi_track(s) && !is_hidden(s)) { + if (is_midi_track(s) && !s->presentation_info().hidden()) { sorted.push_back (s); } break; @@ -320,22 +320,22 @@ MackieControlProtocol::get_sorted_stripables() break; case Auxes: // in ardour, for now aux and buss are same. for mixbus, "Busses" are mixbuses, "Auxes" are ardour buses #ifdef MIXBUS - if (!s->mixbus() && !is_track() && !is_hidden(s)) + if (!s->mixbus() && !is_track() && !s->presentation_info().hidden()) #else - if (!is_track(s) && !is_hidden(s)) + if (!is_track(s) && !s->presentation_info().hidden()) #endif { sorted.push_back (s); } break; case Hidden: // Show all the tracks we have hidden - if (is_hidden(s)) { + if (s->presentation_info().hidden()) { // maybe separate groups sorted.push_back (s); } break; case Selected: // For example: a group (this is USER) - if (selected(s) && !is_hidden(s)) { + if (s->presentation_info().selected() && !s->presentation_info().hidden()) { sorted.push_back (s); } break; @@ -2039,23 +2039,19 @@ MackieControlProtocol::select_range () return; } - if (stripables.size() == 1 && _last_selected_stripables.size() == 1 && stripables.front()->presentation_info().selected()) { + if (stripables.size() == 1 && ControlProtocol::last_selected().size() == 1 && stripables.front()->presentation_info().selected()) { /* cancel selection for one and only selected stripable */ - session->toggle_stripable_selection (stripables.front()); + ToggleStripableSelection (stripables.front()); } else { - for (StripableList::iterator s = stripables.begin(); s != stripables.end(); ++s) { - if (main_modifier_state() == MODIFIER_CONTROL) { - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("toggle selection of %1 (%2)\n", (*s)->name(), (*s)->presentation_info().order())); - session->toggle_stripable_selection (*s); + if (main_modifier_state() == MODIFIER_SHIFT) { + ToggleStripableSelection (*s); } else { if (s == stripables.begin()) { - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("set selection of %1 (%2)\n", (*s)->name(), (*s)->presentation_info().order())); - session->set_stripable_selection (*s); - } else { - DEBUG_TRACE (DEBUG::MackieControl, string_compose ("add to selection %1 (%2)\n", (*s)->name(), (*s)->presentation_info().order())); - session->add_stripable_selection (*s); + SetStripableSelection (*s); + } else { + AddStripableToSelection (*s); } } } @@ -2351,27 +2347,6 @@ MackieControlProtocol::is_midi_track (boost::shared_ptr r) const return boost::dynamic_pointer_cast(r) != 0; } -bool -MackieControlProtocol::selected (boost::shared_ptr r) const -{ - for (Selection::const_iterator i = _last_selected_stripables.begin(); i != _last_selected_stripables.end(); ++i) { - boost::shared_ptr rt = (*i).lock(); - if (rt == r) { - return true; - } - } - return false; -} - -bool -MackieControlProtocol::is_hidden (boost::shared_ptr r) const -{ - if (!r) { - return false; - } - return (r->presentation_info().flags() & PresentationInfo::Hidden); -} - bool MackieControlProtocol::is_mapped (boost::shared_ptr r) const { @@ -2391,14 +2366,6 @@ MackieControlProtocol::update_selected (boost::shared_ptr s, bool bec { if (became_selected) { - if (selected (s)) { - /* already selected .. mmmm */ - cerr << "stripable " << s->name() << " already marked as selected\n"; - return; - } - - _last_selected_stripables.push_back (boost::weak_ptr (s)); - check_fader_automation_state (); /* It is possible that first_selected_route() may return null if we @@ -2412,33 +2379,19 @@ MackieControlProtocol::update_selected (boost::shared_ptr s, bool bec set_subview_mode (None, boost::shared_ptr()); } - } else { - - for (Selection::iterator i = _last_selected_stripables.begin(); i != _last_selected_stripables.end(); ++i) { - boost::shared_ptr ss = (*i).lock(); - - if (ss == s) { - _last_selected_stripables.erase (i); - break; - } - } } } boost::shared_ptr MackieControlProtocol::first_selected_stripable () const { - if (_last_selected_stripables.empty()) { - return boost::shared_ptr(); - } - - boost::shared_ptr r = (*(_last_selected_stripables.begin())).lock(); + boost::shared_ptr s = ControlProtocol::first_selected_stripable(); - if (r) { + if (s) { /* check it is on one of our surfaces */ - if (is_mapped (r)) { - return r; + if (is_mapped (s)) { + return s; } /* stripable is not mapped. thus, the currently selected stripable is @@ -2446,10 +2399,10 @@ MackieControlProtocol::first_selected_stripable () const * no currently selected stripable. */ - r.reset (); + s.reset (); } - return r; /* may be null */ + return s; /* may be null */ } boost::shared_ptr diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index 76da4fe5e8..56ead71b50 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -138,8 +138,6 @@ class MackieControlProtocol bool is_track (boost::shared_ptr) const; bool is_audio_track (boost::shared_ptr) const; bool is_midi_track (boost::shared_ptr) const; - bool selected (boost::shared_ptr) const; - bool is_hidden (boost::shared_ptr) const; bool is_mapped (boost::shared_ptr) const; boost::shared_ptr first_selected_stripable () const; void update_selected (boost::shared_ptr, bool selected); @@ -335,8 +333,6 @@ class MackieControlProtocol bool needs_ipmidi_restart; bool _metering_active; bool _initialized; - typedef std::vector > Selection; - Selection _last_selected_stripables; XMLNode* configuration_state; int state_version; int _last_bank[9]; diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index f2fd8af867..b199b64f84 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -2600,9 +2600,8 @@ OSC::route_plugin_parameter_print (int ssid, int piid, int par, lo_message msg) void OSC::gui_selection_changed () { - boost::shared_ptr strip; + boost::shared_ptr strip = ControlProtocol::first_selected_stripable(); - strip = boost::dynamic_pointer_cast(session->get_editor_mixer().lock()); if (strip) { _select = strip; for (uint32_t it = 0; it < _surface.size(); ++it) {