don't actually use a method from libardourcp inside libardour; use a PBD::Signal...
[ardour.git] / libs / surfaces / control_protocol / control_protocol.cc
index 707965ba1b3e7ebf17b40b78c0d58f474cad7aef..e094e9b6cc4a723c3410d4586962cb54bd812771 100644 (file)
 
 */
 
+#include "pbd/convert.h"
 #include "pbd/error.h"
 
+#include "ardour/control_protocol_manager.h"
 #include "ardour/gain_control.h"
 #include "ardour/session.h"
+#include "ardour/record_enable_control.h"
 #include "ardour/route.h"
 #include "ardour/audio_track.h"
 #include "ardour/meter.h"
@@ -48,19 +51,18 @@ PBD::Signal0<void> ControlProtocol::VerticalZoomOutSelected;
 PBD::Signal0<void>          ControlProtocol::StepTracksDown;
 PBD::Signal0<void>          ControlProtocol::StepTracksUp;
 
-PBD::Signal1<void,uint64_t> ControlProtocol::AddRouteToSelection;
-PBD::Signal1<void,uint64_t> ControlProtocol::SetRouteSelection;
-PBD::Signal1<void,uint64_t> ControlProtocol::ToggleRouteSelection;
-PBD::Signal1<void,uint64_t> ControlProtocol::RemoveRouteFromSelection;
-PBD::Signal0<void>          ControlProtocol::ClearRouteSelection;
-
-PBD::Signal1<void,StripableNotificationListPtr> ControlProtocol::StripableSelectionChanged;
-PBD::Signal1<void,uint64_t> ControlProtocol::AddStripableToSelection;
-PBD::Signal1<void,uint64_t> ControlProtocol::SetStripableSelection;
-PBD::Signal1<void,uint64_t> ControlProtocol::ToggleStripableSelection;
-PBD::Signal1<void,uint64_t> ControlProtocol::RemoveStripableFromSelection;
+PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::AddStripableToSelection;
+PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::SetStripableSelection;
+PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::ToggleStripableSelection;
+PBD::Signal1<void,boost::shared_ptr<ARDOUR::Stripable> > ControlProtocol::RemoveStripableFromSelection;
 PBD::Signal0<void>          ControlProtocol::ClearStripableSelection;
 
+Glib::Threads::Mutex ControlProtocol::special_stripable_mutex;
+boost::weak_ptr<Stripable> ControlProtocol::_first_selected_stripable;
+boost::weak_ptr<Stripable> ControlProtocol::_leftmost_mixer_stripable;
+StripableNotificationList ControlProtocol::_last_selected;
+PBD::ScopedConnection ControlProtocol::selection_connection;
+bool ControlProtocol::selection_connected = false;
 
 const std::string ControlProtocol::state_node_name ("Protocol");
 
@@ -69,6 +71,11 @@ 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 */
+               ControlProtocolManager::StripableSelectionChanged.connect_same_thread (selection_connection, boost::bind (&ControlProtocol::notify_stripable_selection_changed, _1));
+               selection_connected = true;
+       }
 }
 
 ControlProtocol::~ControlProtocol ()
@@ -287,7 +294,8 @@ ControlProtocol::route_set_soloed (uint32_t table_index, bool yn)
        boost::shared_ptr<Route> r = route_table[table_index];
 
        if (r != 0) {
-               r->solo_control()->set_value (yn ? 1.0 : 0.0, Controllable::UseGroup);
+               r->solo_control()->set_value (yn ? 1.0 : 0.0, Controllable::UseGroup); // XXX does not propagate
+               //_session->set_control (r->solo_control(), yn ? 1.0 : 0.0, Controllable::UseGroup); // << correct way, needs a session ptr
        }
 }
 
@@ -318,8 +326,8 @@ ControlProtocol::get_state ()
 {
        XMLNode* node = new XMLNode (state_node_name);
 
-       node->add_property ("name", _name);
-       node->add_property ("feedback", get_feedback() ? "yes" : "no");
+       node->set_property ("name", _name);
+       node->set_property ("feedback", get_feedback());
 
        return *node;
 }
@@ -327,11 +335,58 @@ ControlProtocol::get_state ()
 int
 ControlProtocol::set_state (XMLNode const & node, int /* version */)
 {
-       const XMLProperty* prop;
-
-       if ((prop = node.property ("feedback")) != 0) {
-               set_feedback (string_is_affirmative (prop->value()));
+       bool feedback;
+       if (node.get_property ("feedback", feedback)) {
+               set_feedback (feedback);
        }
 
        return 0;
 }
+
+boost::shared_ptr<Stripable>
+ControlProtocol::first_selected_stripable ()
+{
+       Glib::Threads::Mutex::Lock lm (special_stripable_mutex);
+       return _first_selected_stripable.lock();
+}
+
+boost::shared_ptr<Stripable>
+ControlProtocol::leftmost_mixer_stripable ()
+{
+       Glib::Threads::Mutex::Lock lm (special_stripable_mutex);
+       return _leftmost_mixer_stripable.lock();
+}
+
+void
+ControlProtocol::set_leftmost_mixer_stripable (boost::shared_ptr<Stripable> s)
+{
+       Glib::Threads::Mutex::Lock lm (special_stripable_mutex);
+       _leftmost_mixer_stripable = s;
+}
+
+void
+ControlProtocol::set_first_selected_stripable (boost::shared_ptr<Stripable> s)
+{
+       Glib::Threads::Mutex::Lock lm (special_stripable_mutex);
+       _first_selected_stripable = s;
+}
+
+void
+ControlProtocol::notify_stripable_selection_changed (StripableNotificationListPtr sp)
+{
+       bool had_selection = !_last_selected.empty();
+
+       _last_selected = *sp;
+
+       {
+               Glib::Threads::Mutex::Lock lm (special_stripable_mutex);
+
+               if (!_last_selected.empty()) {
+                       if (!had_selection) {
+                               _first_selected_stripable = _last_selected.front().lock();
+                       }
+               } else {
+                       _first_selected_stripable = boost::weak_ptr<Stripable>();
+               }
+       }
+}