X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fpresentation_info.cc;h=23d82f6409ed6c5731284baf3be8ef76bbd055ca;hb=7613c9cb34a6f9a27225c6251f7755723272136f;hp=b992f6d5c9b8c752f4cf45d90173a2efe135bdd0;hpb=109be3b4f333c15c557c2343c05a68264225d65d;p=ardour.git diff --git a/libs/ardour/presentation_info.cc b/libs/ardour/presentation_info.cc index b992f6d5c9..23d82f6409 100644 --- a/libs/ardour/presentation_info.cc +++ b/libs/ardour/presentation_info.cc @@ -21,103 +21,269 @@ #include +#include "pbd/debug.h" +#include "pbd/enum_convert.h" #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" +#include "ardour/selection.h" -#include "i18n.h" +#include "pbd/i18n.h" + +namespace PBD { + DEFINE_ENUM_CONVERT(ARDOUR::PresentationInfo::Flag); +} using namespace ARDOUR; using namespace PBD; using std::string; +string PresentationInfo::state_node_name = X_("PresentationInfo"); + +PBD::Signal1 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 { + PBD::PropertyDescriptor selected; + PBD::PropertyDescriptor order; + PBD::PropertyDescriptor color; + } +} + +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 (&_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(&_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); const PresentationInfo::Flag PresentationInfo::Route = PresentationInfo::Flag (PresentationInfo::Bus|PresentationInfo::Track); +const PresentationInfo::Flag PresentationInfo::AllRoutes = PresentationInfo::Flag (PresentationInfo::Route|PresentationInfo::MasterOut|PresentationInfo::MonitorOut); +const PresentationInfo::Flag PresentationInfo::AllStripables = PresentationInfo::Flag (PresentationInfo::AllRoutes|PresentationInfo::VCA); -PresentationInfo::PresentationInfo (std::string const & str) +void +PresentationInfo::make_property_quarks () { - if (parse (str)) { - throw failed_constructor (); - } + Properties::selected.property_id = g_quark_from_static_string (X_("selected")); + DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for selected = %1\n", Properties::selected.property_id)); + Properties::color.property_id = g_quark_from_static_string (X_("color")); + DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for color = %1\n", Properties::color.property_id)); + Properties::order.property_id = g_quark_from_static_string (X_("order")); + DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for order = %1\n", Properties::order.property_id)); } -int -PresentationInfo::parse (string const& str) +PresentationInfo::PresentationInfo (Flag f) + : _order (0) + , _flags (Flag (f & ~OrderSet)) + , _color (0) { - std::stringstream s (str); - - /* new school, segmented string "NNN:TYPE" */ - string f; - char c; + /* OrderSet is not set */ +} - s >> _order; - /* skip colon */ - s >> c; - /* grab flags */ - s >> f; +PresentationInfo::PresentationInfo (order_t o, Flag f) + : _order (o) + , _flags (Flag (f | OrderSet)) + , _color (0) +{ + /* OrderSet is set */ +} +PresentationInfo::PresentationInfo (PresentationInfo const& other) + : PBD::Stateful () + , _order (other.order()) + , _flags (other.flags()) + , _color (other.color()) +{ +} - _flags = Flag (string_2_enum (f, _flags)|GroupOrderSet); +XMLNode& +PresentationInfo::get_state () +{ + XMLNode* node = new XMLNode (state_node_name); + node->set_property ("order", _order); + node->set_property ("flags", _flags); + node->set_property ("color", _color); - return 0; + return *node; } int -PresentationInfo::parse (uint32_t n, Flag f) -{ - if (n < UINT32_MAX) { - assert (f != Flag (0)); - _order = n; - _flags = Flag (f|GroupOrderSet); - } else { - _order = (n & 0xffff); - _flags = Flag ((n >> 16)|GroupOrderSet); +PresentationInfo::set_state (XMLNode const& node, int /* version */) +{ + if (node.name() != state_node_name) { + return -1; } - return 0; -} + PropertyChange pc; -std::string -PresentationInfo::to_string() const -{ - std::stringstream ss; + order_t o; + if (node.get_property (X_("order"), o)) { + if (o != _order) { + pc.add (Properties::order); + _order = o; + } + _order = o; // huh? + } - /* Do not save or selected hidden status, or group-order set bit */ + Flag f; + if (node.get_property (X_("flags"), f)) { + if ((f&Hidden) != (_flags&Hidden)) { + pc.add (Properties::hidden); + } + _flags = f; + } - Flag f = Flag (_flags & ~(Hidden|Selected|GroupOrderSet)); + color_t c; + if (node.get_property (X_("color"), c)) { + if (c != _color) { + pc.add (Properties::color); + _color = c; + } + } + + send_change (PropertyChange (pc)); - ss << _order << ':' << enum_2_string (f); + return 0; - return ss.str(); } PresentationInfo::Flag PresentationInfo::get_flags (XMLNode const& node) { - const XMLProperty *prop; XMLNodeList nlist = node.children (); - XMLNodeConstIterator niter; - XMLNode *child; - for (niter = nlist.begin(); niter != nlist.end(); ++niter){ - child = *niter; + for (XMLNodeConstIterator niter = nlist.begin(); niter != nlist.end(); ++niter){ + XMLNode* child = *niter; - if (child->name() == X_("PresentationInfo")) { - if ((prop = child->property (X_("value"))) != 0) { - PresentationInfo pi (prop->value()); - return pi.flags (); + if (child->name() == PresentationInfo::state_node_name) { + Flag f; + if (child->get_property (X_("flags"), f)) { + return f; } } } return Flag (0); } +void +PresentationInfo::set_color (PresentationInfo::color_t c) +{ + if (c != _color) { + _color = c; + send_change (PropertyChange (Properties::color)); + send_static_change (PropertyChange (Properties::color)); + } +} + +bool +PresentationInfo::color_set () const +{ + /* all RGBA values zero? not set. + * + * this is heuristic, but it is fairly realistic. who will ever set + * a color to completely transparent black? only the constructor .. + */ + return _color != 0; +} + +void +PresentationInfo::set_hidden (bool yn) +{ + if (yn != hidden()) { + + if (yn) { + _flags = Flag (_flags | Hidden); + } else { + _flags = Flag (_flags & ~Hidden); + } + + send_change (PropertyChange (Properties::hidden)); + send_static_change (PropertyChange (Properties::hidden)); + } +} + +void +PresentationInfo::set_order (order_t order) +{ + _flags = Flag (_flags|OrderSet); + + if (order != _order) { + _order = order; + send_change (PropertyChange (Properties::order)); + send_static_change (PropertyChange (Properties::order)); + } +} + +PresentationInfo& +PresentationInfo::operator= (PresentationInfo const& other) +{ + if (this != &other) { + _order = other.order(); + _flags = other.flags(); + _color = other.color(); + } + + return *this; +} + std::ostream& -operator<<(std::ostream& o, ARDOUR::PresentationInfo const& rid) +operator<<(std::ostream& o, ARDOUR::PresentationInfo const& pi) { - return o << rid.to_string (); + return o << pi.order() << '/' << enum_2_string (pi.flags()) << '/' << pi.color(); }