From 35a9facdaeed3285c0c81ba0b7b67d1607b56438 Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Fri, 5 May 2017 19:25:35 +0100 Subject: add missing files from selection development branch(es) --- gtk2_ardour/axis_provider.h | 38 +++++ libs/ardour/ardour/selection.h | 111 ++++++++++++++ libs/ardour/selection.cc | 324 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 473 insertions(+) create mode 100644 gtk2_ardour/axis_provider.h create mode 100644 libs/ardour/ardour/selection.h create mode 100644 libs/ardour/selection.cc diff --git a/gtk2_ardour/axis_provider.h b/gtk2_ardour/axis_provider.h new file mode 100644 index 0000000000..6aeb77ab09 --- /dev/null +++ b/gtk2_ardour/axis_provider.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2017 Paul Davis (paul@linuxaudiosystems.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __gtk2_ardour_axis_provider_h__ +#define __gtk2_ardour_axis_provider_h__ + +#include + +namespace ARDOUR { + class Stripable; + class AutomationControl; +} + +class AxisView; + +class AxisViewProvider +{ + public: + virtual AxisView* axis_view_by_stripable (boost::shared_ptr) const = 0; + virtual AxisView* axis_view_by_control (boost::shared_ptr) const = 0; +}; + +#endif /* __gtk2_ardour_axis_provider_h__ */ diff --git a/libs/ardour/ardour/selection.h b/libs/ardour/ardour/selection.h new file mode 100644 index 0000000000..26e2c31ce1 --- /dev/null +++ b/libs/ardour/ardour/selection.h @@ -0,0 +1,111 @@ +/* + Copyright (C) 2017 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __ardour_selection_h__ +#define __ardour_selection_h__ + +#include +#include + +#include +#include + +#include "pbd/stateful.h" +#include "pbd/i18n.h" + +#include "ardour/presentation_info.h" + +namespace ARDOUR { + +class AutomationControl; +class Session; +class Stripable; +class PresentationInfo; + +class CoreSelection : public PBD::Stateful { + public: + CoreSelection (Session& s); + ~CoreSelection (); + + void toggle (boost::shared_ptr, boost::shared_ptr); + void add (boost::shared_ptr, boost::shared_ptr); + void remove (boost::shared_ptr, boost::shared_ptr); + void set (boost::shared_ptr, boost::shared_ptr); + void clear_stripables(); + + bool selected (boost::shared_ptr) const; + bool selected (boost::shared_ptr) const; + uint32_t selected() const; + + struct StripableAutomationControl { + boost::shared_ptr stripable; + boost::shared_ptr controllable; + int order; + + StripableAutomationControl (boost::shared_ptr s, boost::shared_ptr c, int o) + : stripable (s), controllable (c), order (o) {} + }; + + typedef std::vector StripableAutomationControls; + + void get_stripables (StripableAutomationControls&) const; + + XMLNode& get_state (void); + int set_state (const XMLNode&, int version); + + protected: + friend class AutomationControl; + void remove_control_by_id (PBD::ID const &); + + protected: + friend class Stripable; + void remove_stripable_by_id (PBD::ID const &); + + private: + mutable Glib::Threads::RWLock _lock; + Session& session; + int selection_order; + + struct SelectedStripable { + SelectedStripable (boost::shared_ptr, boost::shared_ptr, int); + SelectedStripable (PBD::ID const & s, PBD::ID const & c, int o) + : stripable (s), controllable (c), order (o) {} + + PBD::ID stripable; + PBD::ID controllable; + int order; + + bool operator< (SelectedStripable const & other) const { + if (stripable == other.stripable) { + return controllable < other.controllable; + } + return stripable < other.stripable; + } + }; + + typedef std::set SelectedStripables; + + SelectedStripables _stripables; + + void send_selection_change (); +}; + +} // namespace ARDOUR + +#endif /* __ardour_selection_h__ */ diff --git a/libs/ardour/selection.cc b/libs/ardour/selection.cc new file mode 100644 index 0000000000..2e887afcd5 --- /dev/null +++ b/libs/ardour/selection.cc @@ -0,0 +1,324 @@ +/* + Copyright (C) 2017 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "pbd/compose.h" +#include "pbd/signals.h" + +#include "ardour/automation_control.h" +#include "ardour/debug.h" +#include "ardour/selection.h" +#include "ardour/session.h" +#include "ardour/stripable.h" + +using namespace ARDOUR; +using namespace PBD; + +void +CoreSelection::send_selection_change () +{ + PropertyChange pc; + pc.add (Properties::selected); + PresentationInfo::send_static_change (pc); +} + +CoreSelection::CoreSelection (Session& s) + : session (s) + , selection_order (0) +{ +} + +CoreSelection::~CoreSelection () +{ +} + +void +CoreSelection::toggle (boost::shared_ptr s, boost::shared_ptr c) +{ + DEBUG_TRACE (DEBUG::Selection, string_compose ("toggle: s %1 selected %2 c %3 selected %4\n", + s, selected (s), c, selected (c))); + if ((c && selected (c)) || selected (s)) { + remove (s, c); + } else { + add (s, c); + } +} + +void +CoreSelection::add (boost::shared_ptr s, boost::shared_ptr c) +{ + bool send = false; + + { + Glib::Threads::RWLock::WriterLock lm (_lock); + + SelectedStripable ss (s, c, g_atomic_int_add (&selection_order, 1)); + + if (_stripables.insert (ss).second) { + DEBUG_TRACE (DEBUG::Selection, string_compose ("added %1/%2 to s/c selection\n", s->name(), c)); + send = true; + } else { + DEBUG_TRACE (DEBUG::Selection, string_compose ("%1/%2 already in s/c selection\n", s->name(), c)); + } + } + + if (send) { + send_selection_change (); + } +} + +void +CoreSelection::remove (boost::shared_ptr s, boost::shared_ptr c) +{ + bool send = false; + { + Glib::Threads::RWLock::WriterLock lm (_lock); + + SelectedStripable ss (s, c, 0); + + SelectedStripables::iterator i = _stripables.find (ss); + + if (i != _stripables.end()) { + _stripables.erase (i); + DEBUG_TRACE (DEBUG::Selection, string_compose ("removed %1/%2 from s/c selection\n", s, c)); + send = true; + } + } + + if (send) { + send_selection_change (); + } +} + +void +CoreSelection::set (boost::shared_ptr s, boost::shared_ptr c) +{ + { + Glib::Threads::RWLock::WriterLock lm (_lock); + + SelectedStripable ss (s, c, g_atomic_int_add (&selection_order, 1)); + + if (_stripables.size() == 1 && _stripables.find (ss) != _stripables.end()) { + return; + } + + _stripables.clear (); + _stripables.insert (ss); + DEBUG_TRACE (DEBUG::Selection, string_compose ("set s/c selection to %1/%2\n", s->name(), c)); + } + + send_selection_change (); +} + +void +CoreSelection::clear_stripables () +{ + bool send = false; + + DEBUG_TRACE (DEBUG::Selection, "clearing s/c selection\n"); + + { + Glib::Threads::RWLock::WriterLock lm (_lock); + + if (!_stripables.empty()) { + _stripables.clear (); + send = true; + DEBUG_TRACE (DEBUG::Selection, "cleared s/c selection\n"); + } + } + + if (send) { + send_selection_change (); + } +} + +bool +CoreSelection::selected (boost::shared_ptr s) const +{ + if (!s) { + return false; + } + + Glib::Threads::RWLock::ReaderLock lm (_lock); + + for (SelectedStripables::const_iterator x = _stripables.begin(); x != _stripables.end(); ++x) { + + if (!((*x).controllable == 0)) { + /* selected automation control */ + continue; + } + + /* stripable itself selected, not just a control belonging to + * it + */ + + if ((*x).stripable == s->id()) { + return true; + } + } + + return false; +} + +bool +CoreSelection::selected (boost::shared_ptr c) const +{ + if (!c) { + return false; + } + + Glib::Threads::RWLock::ReaderLock lm (_lock); + + for (SelectedStripables::const_iterator x = _stripables.begin(); x != _stripables.end(); ++x) { + if ((*x).controllable == c->id()) { + return true; + } + } + + return false; +} + +CoreSelection::SelectedStripable::SelectedStripable (boost::shared_ptr s, boost::shared_ptr c, int o) + : stripable (s ? s->id() : PBD::ID (0)) + , controllable (c ? c->id() : PBD::ID (0)) + , order (o) +{ +} + +struct StripableControllerSort { + bool operator() (CoreSelection::StripableAutomationControl const &a, CoreSelection::StripableAutomationControl const & b) const { + return a.order < b.order; + } +}; + +void +CoreSelection::get_stripables (StripableAutomationControls& sc) const +{ + Glib::Threads::RWLock::ReaderLock lm (_lock); + + for (SelectedStripables::const_iterator x = _stripables.begin(); x != _stripables.end(); ++x) { + + boost::shared_ptr s = session.stripable_by_id ((*x).stripable); + boost::shared_ptr c; + + if (!s) { + c = session.automation_control_by_id ((*x).controllable); + } else { + c = s->automation_control ((*x).controllable); + } + + if (s || c) { + sc.push_back (StripableAutomationControl (s, c, (*x).order)); + } + } + + StripableControllerSort cmp; + sort (sc.begin(), sc.end(), cmp); +} + +void +CoreSelection::remove_control_by_id (PBD::ID const & id) +{ + Glib::Threads::RWLock::WriterLock lm (_lock); + + for (SelectedStripables::const_iterator x = _stripables.begin(); x != _stripables.end(); ++x) { + if ((*x).controllable == id) { + _stripables.erase (x); + return; + } + } +} + +void +CoreSelection::remove_stripable_by_id (PBD::ID const & id) +{ + Glib::Threads::RWLock::WriterLock lm (_lock); + + for (SelectedStripables::const_iterator x = _stripables.begin(); x != _stripables.end(); ++x) { + if ((*x).stripable == id) { + _stripables.erase (x); + return; + } + } +} + +XMLNode& +CoreSelection::get_state (void) +{ + XMLNode* node = new XMLNode (X_("Selection")); + + Glib::Threads::RWLock::WriterLock lm (_lock); + + for (SelectedStripables::const_iterator x = _stripables.begin(); x != _stripables.end(); ++x) { + XMLNode* child = new XMLNode (X_("StripableAutomationControl")); + child->set_property (X_("stripable"), (*x).stripable.to_s()); + child->set_property (X_("control"), (*x).controllable.to_s()); + child->set_property (X_("order"), (*x).order); + + node->add_child_nocopy (*child); + } + + return *node; +} +int +CoreSelection::set_state (const XMLNode& node, int /* version */) +{ + XMLNodeList children (node.children()); + Glib::Threads::RWLock::WriterLock lm (_lock); + + _stripables.clear (); + + for (XMLNodeConstIterator i = children.begin(); i != children.end(); ++i) { + if ((*i)->name() != X_("StripableAutomationControl")) { + continue; + } + + std::string s; + + if (!(*i)->get_property (X_("stripable"), s)) { + continue; + } + + std::string c; + + if (!(*i)->get_property (X_("control"), c)) { + continue; + } + + int order; + + if (!(*i)->get_property (X_("order"), order)) { + continue; + } + + SelectedStripable ss (PBD::ID (s), PBD::ID (c), order); + _stripables.insert (ss); + } + + std::cerr << "set state: " << _stripables.size() << std::endl; + + return 0; +} + +uint32_t +CoreSelection::selected () const +{ + Glib::Threads::RWLock::ReaderLock lm (_lock); + return _stripables.size(); +} + -- cgit v1.2.3