From eb3f50e15c9f9ed1880c59fecd6f8b3edcc05820 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 12 May 2017 14:51:31 +0100 Subject: [PATCH] change the way ControlProtocols (control surfaces) are notified and handle Stripable selection changes The Editor continues to notify them, but via a direct call to ControlProtocolManager, not a signal. The CP Manager calls the ControlProtocol static method to set up static data structures holding selection info for all surfaces and then notifies each surface/protocol that selection has changed. --- cfgtool/wscript | 2 +- gtk2_ardour/editor_selection.cc | 5 ++-- libs/ardour/ardour/control_protocol_manager.h | 5 ++++ libs/ardour/control_protocol_manager.cc | 23 +++++++++++++++++++ libs/surfaces/cc121/cc121.cc | 12 ++-------- libs/surfaces/cc121/cc121.h | 2 +- .../control_protocol/control_protocol.cc | 12 +--------- .../control_protocol/control_protocol.h | 14 +++-------- libs/surfaces/faderport/faderport.cc | 5 +--- libs/surfaces/faderport/faderport.h | 2 +- libs/surfaces/faderport8/faderport8.cc | 8 +++---- libs/surfaces/faderport8/faderport8.h | 2 +- .../generic_midi_control_protocol.h | 2 ++ .../mackie/mackie_control_protocol.cc | 7 +++--- .../surfaces/mackie/mackie_control_protocol.h | 4 +--- libs/surfaces/mackie/strip.cc | 1 - libs/surfaces/osc/osc.cc | 3 --- libs/surfaces/osc/osc.h | 2 ++ libs/surfaces/push2/push2.cc | 17 +++++++------- libs/surfaces/push2/push2.h | 3 +-- libs/surfaces/push2/track_mix.cc | 12 ---------- libs/surfaces/push2/track_mix.h | 2 -- libs/surfaces/wiimote/wiimote.h | 2 ++ 23 files changed, 64 insertions(+), 83 deletions(-) diff --git a/cfgtool/wscript b/cfgtool/wscript index 6f594ca792..7fa076114a 100644 --- a/cfgtool/wscript +++ b/cfgtool/wscript @@ -19,6 +19,6 @@ def build(bld): obj = bld (features = 'cxx c cxxprogram') obj.source = 'cfgtool.cc' obj.target = 'cfgtool' - obj.use = [ 'libpbd', 'libardour' ] + obj.use = [ 'libpbd', 'libardour', 'libardour_cp' ] obj.uselib = [ 'GLIBMM', 'XML' ] obj.install_path = None diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc index c9e2ba49fd..82c9020e9a 100644 --- a/gtk2_ardour/editor_selection.cc +++ b/gtk2_ardour/editor_selection.cc @@ -23,6 +23,7 @@ #include "pbd/stacktrace.h" #include "pbd/unwind.h" +#include "ardour/control_protocol_manager.h" #include "ardour/midi_region.h" #include "ardour/playlist.h" #include "ardour/profile.h" @@ -30,8 +31,6 @@ #include "ardour/selection.h" #include "ardour/session.h" -#include "control_protocol/control_protocol.h" - #include "editor.h" #include "editor_drag.h" #include "editor_routes.h" @@ -1090,7 +1089,7 @@ Editor::presentation_info_changed (PropertyChange const & what_changed) /* STEP 4: notify control protocols */ - ControlProtocol::StripableSelectionChanged (stripables); + ControlProtocolManager::instance().stripable_selection_changed (stripables); if (sfbrowser && _session && !_session->deletion_in_progress()) { uint32_t audio_track_cnt = 0; diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h index 2dddc30aca..c8370e03a6 100644 --- a/libs/ardour/ardour/control_protocol_manager.h +++ b/libs/ardour/ardour/control_protocol_manager.h @@ -27,6 +27,9 @@ #include #include "pbd/stateful.h" + +#include "control_protocol/types.h" + #include "ardour/session_handle.h" namespace ARDOUR { @@ -80,6 +83,8 @@ class LIBARDOUR_API ControlProtocolManager : public PBD::Stateful, public ARDOUR PBD::Signal1 ProtocolStatusChange; + void stripable_selection_changed (ARDOUR::StripableNotificationListPtr); + private: ControlProtocolManager (); static ControlProtocolManager* _instance; diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc index ba32ab8b70..338ea816f2 100644 --- a/libs/ardour/control_protocol_manager.cc +++ b/libs/ardour/control_protocol_manager.cc @@ -557,3 +557,26 @@ ControlProtocolManager::register_request_buffer_factories () } } } + +void +ControlProtocolManager::stripable_selection_changed (StripableNotificationListPtr sp) +{ + /* this sets up the (static) data structures owned by ControlProtocol + that are "shared" across all control protocols. + */ + + DEBUG_TRACE (DEBUG::Selection, string_compose ("Surface manager: selection changed, now %1 stripables\n", sp ? sp->size() : -1)); + ControlProtocol::notify_stripable_selection_changed (sp); + + /* now give each protocol the chance to respond to the selection change + */ + + { + Glib::Threads::Mutex::Lock lm (protocols_lock); + + for (list::iterator p = control_protocols.begin(); p != control_protocols.end(); ++p) { + DEBUG_TRACE (DEBUG::Selection, string_compose ("selection change notification for surface \"%1\"\n", (*p)->name())); + (*p)->stripable_selection_changed (); + } + } +} diff --git a/libs/surfaces/cc121/cc121.cc b/libs/surfaces/cc121/cc121.cc index 3f563db251..19301b86b8 100644 --- a/libs/surfaces/cc121/cc121.cc +++ b/libs/surfaces/cc121/cc121.cc @@ -115,8 +115,6 @@ CC121::CC121 (Session& s) ); - StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&CC121::gui_track_selection_changed, this, _1), this); - /* Catch port connections and disconnections */ ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&CC121::connection_handler, this, _1, _2, _3, _4, _5), this); buttons.insert (std::make_pair (EButton, Button (*this, _("EButton"), EButton))); @@ -1040,15 +1038,9 @@ CC121::Button::get_state () const } void -CC121::gui_track_selection_changed (StripableNotificationListPtr stripables) +CC121::stripable_selection_changed () { - boost::shared_ptr r; - - if (!stripables->empty()) { - r = stripables->front().lock(); - } - - set_current_stripable (r); + set_current_stripable (first_selected_stripable()); } void diff --git a/libs/surfaces/cc121/cc121.h b/libs/surfaces/cc121/cc121.h index a5f0363a22..bef1000ee6 100644 --- a/libs/surfaces/cc121/cc121.h +++ b/libs/surfaces/cc121/cc121.h @@ -298,7 +298,7 @@ class CC121 : public ARDOUR::ControlProtocol, public AbstractUI { void drop_current_stripable (); void use_master (); void use_monitor (); - void gui_track_selection_changed (ARDOUR::StripableNotificationListPtr); + void stripable_selection_changed (); PBD::ScopedConnection selection_connection; PBD::ScopedConnectionList stripable_connections; diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc index edcc06b23a..c2589d24e3 100644 --- a/libs/surfaces/control_protocol/control_protocol.cc +++ b/libs/surfaces/control_protocol/control_protocol.cc @@ -56,14 +56,10 @@ PBD::Signal1 > ControlProtocol::Toggle PBD::Signal1 > ControlProtocol::RemoveStripableFromSelection; PBD::Signal0 ControlProtocol::ClearStripableSelection; -PBD::Signal1 ControlProtocol::StripableSelectionChanged; - Glib::Threads::Mutex ControlProtocol::special_stripable_mutex; boost::weak_ptr ControlProtocol::_first_selected_stripable; boost::weak_ptr ControlProtocol::_leftmost_mixer_stripable; StripableNotificationList ControlProtocol::_last_selected; -bool ControlProtocol::selection_connected = false; -PBD::ScopedConnection ControlProtocol::selection_connection; const std::string ControlProtocol::state_node_name ("Protocol"); @@ -72,12 +68,6 @@ 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 () @@ -374,7 +364,7 @@ ControlProtocol::set_first_selected_stripable (boost::shared_ptr s) } void -ControlProtocol::stripable_selection_changed (StripableNotificationListPtr sp) +ControlProtocol::notify_stripable_selection_changed (StripableNotificationListPtr sp) { bool had_selection = !_last_selected.empty(); diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h index 987a8bcac4..ff5cd314fa 100644 --- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h +++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h @@ -57,6 +57,8 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope virtual void midi_connectivity_established () {} + virtual void stripable_selection_changed () = 0; + PBD::Signal0 ActiveChanged; /* signals that a control protocol can emit and other (presumably graphical) @@ -85,13 +87,6 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope 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. - */ - - static PBD::Signal1 StripableSelectionChanged; - static boost::shared_ptr first_selected_stripable (); static void set_first_selected_stripable (boost::shared_ptr); @@ -146,6 +141,7 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope static const std::string state_node_name; static StripableNotificationList const & last_selected() { return _last_selected; } + static void notify_stripable_selection_changed (StripableNotificationListPtr); protected: std::vector > route_table; @@ -158,14 +154,10 @@ class LIBCONTROLCP_API ControlProtocol : public PBD::Stateful, public PBD::Scope LIBCONTROLCP_LOCAL ControlProtocol (const ControlProtocol&); /* noncopyable */ bool _active; - static Glib::Threads::Mutex special_stripable_mutex; static boost::weak_ptr _leftmost_mixer_stripable; 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/faderport/faderport.cc b/libs/surfaces/faderport/faderport.cc index 8fd8250c21..9debc72f6f 100644 --- a/libs/surfaces/faderport/faderport.cc +++ b/libs/surfaces/faderport/faderport.cc @@ -108,9 +108,6 @@ FaderPort::FaderPort (Session& s) session->engine().make_port_name_non_relative (outp->name()) ); - - StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort::gui_track_selection_changed, this, _1), this); - /* Catch port connections and disconnections */ ARDOUR::AudioEngine::instance()->PortConnectedOrDisconnected.connect (port_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort::connection_handler, this, _1, _2, _3, _4, _5), this); @@ -1105,7 +1102,7 @@ FaderPort::Button::get_state () const } void -FaderPort::gui_track_selection_changed (StripableNotificationListPtr stripables) +FaderPort::stripable_selection_changed () { set_current_stripable (ControlProtocol::first_selected_stripable()); } diff --git a/libs/surfaces/faderport/faderport.h b/libs/surfaces/faderport/faderport.h index dc9327da2c..56b8ebfbfd 100644 --- a/libs/surfaces/faderport/faderport.h +++ b/libs/surfaces/faderport/faderport.h @@ -298,7 +298,7 @@ class FaderPort : public ARDOUR::ControlProtocol, public AbstractUIStopped.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::engine_reset, this), this); ARDOUR::Port::PortDrop.connect (port_connections, MISSING_INVALIDATOR, boost::bind (&FaderPort8::engine_reset, this), this); - StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&FaderPort8::notify_gui_track_selection_changed, this), this); - /* bind button events to call libardour actions */ setup_actions (); @@ -1363,7 +1361,7 @@ FaderPort8::assign_strips (bool reset_bank) case ModeTrack: case ModePan: assign_stripables (); - notify_gui_track_selection_changed (); // update selection, automation-state + stripable_selection_changed (); // update selection, automation-state break; case ModePlugins: if (_proc_params.size() > 0) { @@ -1427,7 +1425,7 @@ FaderPort8::select_strip (boost::weak_ptr ws) } if (s->is_selected () && s != first_selected_stripable ()) { set_first_selected_stripable (s); - notify_gui_track_selection_changed (); + stripable_selection_changed (); } else { ToggleStripableSelection (s); } @@ -1538,7 +1536,7 @@ FaderPort8::notify_stripable_property_changed (boost::weak_ptr ws, co } void -FaderPort8::notify_gui_track_selection_changed (/*ARDOUR::StripableNotificationListPtr*/) +FaderPort8::stripable_selection_changed () { if (!_device_active) { /* this can be called anytime from the static diff --git a/libs/surfaces/faderport8/faderport8.h b/libs/surfaces/faderport8/faderport8.h index aa1fb8a1fc..06556b4ccd 100644 --- a/libs/surfaces/faderport8/faderport8.h +++ b/libs/surfaces/faderport8/faderport8.h @@ -181,7 +181,7 @@ private: void notify_pi_property_changed (const PBD::PropertyChange&); void notify_stripable_property_changed (boost::weak_ptr, const PBD::PropertyChange&); - void notify_gui_track_selection_changed (); + void stripable_selection_changed (); PBD::ScopedConnection selection_connection; PBD::ScopedConnectionList automation_state_connections; diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h index 291262c820..6585c7ea24 100644 --- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h +++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h @@ -55,6 +55,8 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol { int set_active (bool yn); static bool probe() { return true; } + void stripable_selection_changed () {} + std::list > bundles (); boost::shared_ptr input_port () const; diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc index e50d098882..0cee0e523b 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.cc +++ b/libs/surfaces/mackie/mackie_control_protocol.cc @@ -2369,10 +2369,11 @@ MackieControlProtocol::is_mapped (boost::shared_ptr r) const } void -MackieControlProtocol::update_selected (boost::shared_ptr s, bool became_selected) +MackieControlProtocol::stripable_selection_changed () { - if (became_selected) { + boost::shared_ptr s = first_selected_stripable (); + if (s) { check_fader_automation_state (); /* It is possible that first_selected_route() may return null if we @@ -2382,7 +2383,7 @@ MackieControlProtocol::update_selected (boost::shared_ptr s, bool bec * set_subview_mode() will fail, and we will reset to None. */ - if (set_subview_mode (_subview_mode, first_selected_stripable())) { + if (set_subview_mode (_subview_mode, s)) { set_subview_mode (None, boost::shared_ptr()); } diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h index 2c649a179a..9172716fe2 100644 --- a/libs/surfaces/mackie/mackie_control_protocol.h +++ b/libs/surfaces/mackie/mackie_control_protocol.h @@ -140,7 +140,6 @@ class MackieControlProtocol bool is_midi_track (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); void check_fader_automation_state (); void update_fader_automation_state (); @@ -360,8 +359,7 @@ class MackieControlProtocol void clear_surfaces (); void force_special_stripable_to_strip (boost::shared_ptr r, uint32_t surface, uint32_t strip_number); void build_button_map (); - void gui_track_selection_changed (ARDOUR::StripableNotificationListPtr, bool save_list); - void _gui_track_selection_changed (ARDOUR::StripableNotificationList*, bool save_list, bool gui_did_change); + void stripable_selection_changed (); int ipmidi_restart (); void initialize (); int set_device_info (const std::string& device_name); diff --git a/libs/surfaces/mackie/strip.cc b/libs/surfaces/mackie/strip.cc index 61cb64ce9b..1ec72d501c 100644 --- a/libs/surfaces/mackie/strip.cc +++ b/libs/surfaces/mackie/strip.cc @@ -381,7 +381,6 @@ Strip::notify_property_changed (const PropertyChange& what_changed) if (what_changed.contains (ARDOUR::Properties::selected)) { if (_stripable) { _surface->write (_select->set_state (_stripable->is_selected())); - _surface->mcp().update_selected (_stripable, _stripable->is_selected()); } } } diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc index 58ed86104c..9d422eea6f 100644 --- a/libs/surfaces/osc/osc.cc +++ b/libs/surfaces/osc/osc.cc @@ -245,9 +245,6 @@ OSC::start () periodic_connection = periodic_timeout->connect (sigc::mem_fun (*this, &OSC::periodic)); periodic_timeout->attach (main_loop()->get_context()); - // catch changes to selection for GUI_select mode - StripableSelectionChanged.connect (session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::gui_selection_changed, this), this); - // catch track reordering // receive routes added session->RouteAdded.connect(session_connections, MISSING_INVALIDATOR, boost::bind (&OSC::notify_routes_added, this, _1), this); diff --git a/libs/surfaces/osc/osc.h b/libs/surfaces/osc/osc.h index da4dca3fbe..eeadcf2c6c 100644 --- a/libs/surfaces/osc/osc.h +++ b/libs/surfaces/osc/osc.h @@ -77,6 +77,8 @@ class OSC : public ARDOUR::ControlProtocol, public AbstractUI XMLNode& get_state (); int set_state (const XMLNode&, int version); + void stripable_selection_changed () {} + bool has_editor () const { return true; } void* get_gui () const; void tear_down_gui (); diff --git a/libs/surfaces/push2/push2.cc b/libs/surfaces/push2/push2.cc index 30b521686c..00c7ef43d2 100644 --- a/libs/surfaces/push2/push2.cc +++ b/libs/surfaces/push2/push2.cc @@ -107,8 +107,6 @@ Push2::Push2 (ARDOUR::Session& s) /* master cannot be removed, so no need to connect to going-away signal */ master = session->master_out (); - ControlProtocol::StripableSelectionChanged.connect (selection_connection, MISSING_INVALIDATOR, boost::bind (&Push2::stripable_selection_change, this, _1), this); - /* allocate graphics layouts, even though we're not using them yet */ _canvas = new Push2Canvas (*this, 960, 160); @@ -138,7 +136,6 @@ Push2::~Push2 () DEBUG_TRACE (DEBUG::Push2, "push2 control surface object being destroyed\n"); /* do this before stopping the event loop, so that we don't get any notifications */ - selection_connection.disconnect (); port_reg_connection.disconnect (); port_connection.disconnect (); @@ -200,10 +197,7 @@ Push2::begin_using_device () splash (); /* catch current selection, if any so that we can wire up the pads if appropriate */ - { - StripableNotificationListPtr sp (new StripableNotificationList (ControlProtocol::last_selected())); - stripable_selection_change (sp); - } + stripable_selection_changed (); request_pressure_mode (); @@ -1525,15 +1519,16 @@ Push2::current_layout () const } void -Push2::stripable_selection_change (StripableNotificationListPtr selected) +Push2::stripable_selection_changed () { boost::shared_ptr pad_port = boost::dynamic_pointer_cast(_async_in)->shadow_port(); boost::shared_ptr current_midi_track = current_pad_target.lock(); boost::shared_ptr new_pad_target; + StripableNotificationList const & selected (last_selected()); /* See if there's a MIDI track selected */ - for (StripableNotificationList::iterator si = selected->begin(); si != selected->end(); ++si) { + for (StripableNotificationList::const_iterator si = selected.begin(); si != selected.end(); ++si) { new_pad_target = boost::dynamic_pointer_cast ((*si).lock()); @@ -1582,6 +1577,10 @@ Push2::stripable_selection_change (StripableNotificationListPtr selected) } reset_pad_colors (); + + TrackMixLayout* tml = dynamic_cast (mix_layout); + assert (tml); + tml->set_stripable (first_selected_stripable()); } Push2::Button* diff --git a/libs/surfaces/push2/push2.h b/libs/surfaces/push2/push2.h index bb34f7c016..361801529a 100644 --- a/libs/surfaces/push2/push2.h +++ b/libs/surfaces/push2/push2.h @@ -569,8 +569,7 @@ class Push2 : public ARDOUR::ControlProtocol /* pad mapping */ - PBD::ScopedConnection selection_connection; - void stripable_selection_change (ARDOUR::StripableNotificationListPtr); + void stripable_selection_changed (); MusicalMode::Type _mode; int _scale_root; diff --git a/libs/surfaces/push2/track_mix.cc b/libs/surfaces/push2/track_mix.cc index aad94ec9da..a04ac0af24 100644 --- a/libs/surfaces/push2/track_mix.cc +++ b/libs/surfaces/push2/track_mix.cc @@ -160,8 +160,6 @@ TrackMixLayout::TrackMixLayout (Push2& p, Session & s, std::string const & name) minsec_text->set_font_description (fd2); minsec_text->set_color (p2.get_color (Push2::LightBackground)); minsec_text->set_position (Duple (10 + (4 * Push2Canvas::inter_button_spacing()), 90)); - - ControlProtocol::StripableSelectionChanged.connect (selection_connection, invalidator (*this), boost::bind (&TrackMixLayout::selection_changed, this), &p2); } TrackMixLayout::~TrackMixLayout () @@ -171,16 +169,6 @@ TrackMixLayout::~TrackMixLayout () } } -void -TrackMixLayout::selection_changed () -{ - boost::shared_ptr s = ControlProtocol::first_selected_stripable(); - - if (s) { - set_stripable (s); - } -} - void TrackMixLayout::show () { diff --git a/libs/surfaces/push2/track_mix.h b/libs/surfaces/push2/track_mix.h index 53c08ea219..ba6aa49a0a 100644 --- a/libs/surfaces/push2/track_mix.h +++ b/libs/surfaces/push2/track_mix.h @@ -85,8 +85,6 @@ class TrackMixLayout : public Push2Layout void stripable_property_change (PBD::PropertyChange const& what_changed); void simple_control_change (boost::shared_ptr ac, Push2::ButtonID bid); - PBD::ScopedConnection selection_connection; - void selection_changed (); void show_state (); void drop_stripable (); diff --git a/libs/surfaces/wiimote/wiimote.h b/libs/surfaces/wiimote/wiimote.h index c1fbcfd03f..23e9eedaa2 100644 --- a/libs/surfaces/wiimote/wiimote.h +++ b/libs/surfaces/wiimote/wiimote.h @@ -55,6 +55,8 @@ public: void wiimote_callback (int mesg_count, union cwiid_mesg mesg[]); + void stripable_selection_changed () {} + protected: void do_request (WiimoteControlUIRequest*); int start (); -- 2.30.2