Use macro from pbd/enum_convert.h to define to_string/_to for Track enum
[ardour.git] / libs / ardour / presentation_info.cc
index b335f549042fd808e41ddf0dd3e45ede9517d509..e3e7700d403409c7ff436e63114b949681505f0c 100644 (file)
@@ -26,6 +26,7 @@
 #include "pbd/enumwriter.h"
 #include "pbd/error.h"
 #include "pbd/failed_constructor.h"
+#include "pbd/stacktrace.h"
 #include "pbd/xml++.h"
 
 #include "ardour/presentation_info.h"
@@ -37,7 +38,12 @@ using namespace PBD;
 using std::string;
 
 string PresentationInfo::state_node_name = X_("PresentationInfo");
-PBD::Signal0<void> PresentationInfo::Change;
+
+PBD::Signal1<void,PropertyChange const &> PresentationInfo::Change;
+Glib::Threads::Mutex PresentationInfo::static_signal_lock;
+int PresentationInfo::_change_signal_suspended = 0;
+PBD::PropertyChange PresentationInfo::_pending_static_changes;
+int PresentationInfo::selection_counter = 0;
 
 namespace ARDOUR {
        namespace Properties {
@@ -47,6 +53,59 @@ namespace ARDOUR {
        }
 }
 
+void
+PresentationInfo::suspend_change_signal ()
+{
+       g_atomic_int_add (&_change_signal_suspended, 1);
+}
+
+void
+PresentationInfo::unsuspend_change_signal ()
+{
+       Glib::Threads::Mutex::Lock lm (static_signal_lock);
+
+       if (g_atomic_int_get (const_cast<gint*> (&_change_signal_suspended)) == 1) {
+
+               /* atomically grab currently pending flags */
+
+               PropertyChange pc = _pending_static_changes;
+               _pending_static_changes.clear ();
+
+               if (!pc.empty()) {
+
+                       /* emit the signal with further emissions still blocked
+                        * by _change_signal_suspended, but not by the lock.
+                        *
+                        * This means that if the handlers modify other PI
+                        * states, the signal for that won't be sent while they
+                        * are handling the current signal.
+                        */
+                       lm.release ();
+                       Change (pc); /* EMIT SIGNAL */
+                       lm.acquire ();
+               }
+       }
+
+       g_atomic_int_add (const_cast<gint*>(&_change_signal_suspended), -1);
+}
+
+void
+PresentationInfo::send_static_change (const PropertyChange& what_changed)
+{
+       if (what_changed.empty()) {
+               return;
+       }
+
+
+       if (g_atomic_int_get (&_change_signal_suspended)) {
+               Glib::Threads::Mutex::Lock lm (static_signal_lock);
+               _pending_static_changes.add (what_changed);
+               return;
+       }
+
+       Change (what_changed);
+}
+
 const PresentationInfo::order_t PresentationInfo::max_order = UINT32_MAX;
 const PresentationInfo::Flag PresentationInfo::Bus = PresentationInfo::Flag (PresentationInfo::AudioBus|PresentationInfo::MidiBus);
 const PresentationInfo::Flag PresentationInfo::Track = PresentationInfo::Flag (PresentationInfo::AudioTrack|PresentationInfo::MidiTrack);
@@ -164,6 +223,7 @@ PresentationInfo::set_color (PresentationInfo::color_t c)
        if (c != _color) {
                _color = c;
                send_change (PropertyChange (Properties::color));
+               send_static_change (PropertyChange (Properties::color));
        }
 }
 
@@ -184,10 +244,13 @@ PresentationInfo::set_selected (bool yn)
        if (yn != selected()) {
                if (yn) {
                        _flags = Flag (_flags | Selected);
+                       _selection_cnt = g_atomic_int_add (&selection_counter, 1);
                } else {
                        _flags = Flag (_flags & ~Selected);
+                       _selection_cnt = 0;
                }
                send_change (PropertyChange (Properties::selected));
+               send_static_change (PropertyChange (Properties::selected));
        }
 }
 
@@ -203,6 +266,7 @@ PresentationInfo::set_hidden (bool yn)
                }
 
                send_change (PropertyChange (Properties::hidden));
+               send_static_change (PropertyChange (Properties::hidden));
        }
 }
 
@@ -214,6 +278,7 @@ PresentationInfo::set_order (order_t order)
        if (order != _order) {
                _order = order;
                send_change (PropertyChange (Properties::order));
+               send_static_change (PropertyChange (Properties::order));
        }
 }