summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2017-05-05 12:31:49 +0100
committerPaul Davis <paul@linuxaudiosystems.com>2017-05-05 18:56:25 +0100
commitdc0139d4af4d246f6dcafb04425e3f1198c347c3 (patch)
tree096fa3207a951ec2d5e0338d207adac3f9872996
parent0c035778e162bd5934fc0070e43a26ffb4c8825a (diff)
use CoreSelection for track selection
-rw-r--r--gtk2_ardour/automation_time_axis.cc1
-rw-r--r--gtk2_ardour/automation_time_axis.h4
-rw-r--r--gtk2_ardour/axis_view.cc10
-rw-r--r--gtk2_ardour/axis_view.h7
-rw-r--r--gtk2_ardour/editor.cc46
-rw-r--r--gtk2_ardour/editor.h15
-rw-r--r--gtk2_ardour/editor_canvas_events.cc4
-rw-r--r--gtk2_ardour/editor_drag.cc4
-rw-r--r--gtk2_ardour/editor_mixer.cc3
-rw-r--r--gtk2_ardour/editor_mouse.cc1
-rw-r--r--gtk2_ardour/editor_routes.cc51
-rw-r--r--gtk2_ardour/editor_routes.h2
-rw-r--r--gtk2_ardour/editor_selection.cc174
-rw-r--r--gtk2_ardour/mixer_ui.cc28
-rw-r--r--gtk2_ardour/mixer_ui.h7
-rw-r--r--gtk2_ardour/monitor_section.cc1
-rw-r--r--gtk2_ardour/monitor_section.h4
-rw-r--r--gtk2_ardour/monitor_selector.h2
-rw-r--r--gtk2_ardour/port_group.cc2
-rw-r--r--gtk2_ardour/processor_box.cc20
-rw-r--r--gtk2_ardour/processor_box.h6
-rw-r--r--gtk2_ardour/processor_selection.h84
-rw-r--r--gtk2_ardour/public_editor.h16
-rw-r--r--gtk2_ardour/route_params_ui.cc8
-rw-r--r--gtk2_ardour/route_params_ui.h4
-rw-r--r--gtk2_ardour/route_processor_selection.cc94
-rw-r--r--gtk2_ardour/route_processor_selection.h22
-rw-r--r--gtk2_ardour/selection.cc526
-rw-r--r--gtk2_ardour/selection.h4
-rw-r--r--gtk2_ardour/time_axis_view.cc10
-rw-r--r--gtk2_ardour/track_selection.cc44
-rw-r--r--gtk2_ardour/track_selection.h2
-rw-r--r--gtk2_ardour/wscript1
33 files changed, 677 insertions, 530 deletions
diff --git a/gtk2_ardour/automation_time_axis.cc b/gtk2_ardour/automation_time_axis.cc
index 0b71e423cd..3028fdaefd 100644
--- a/gtk2_ardour/automation_time_axis.cc
+++ b/gtk2_ardour/automation_time_axis.cc
@@ -1062,3 +1062,4 @@ AutomationTimeAxisView::color () const
{
return gdk_color_from_rgb (_route->presentation_info().color());
}
+
diff --git a/gtk2_ardour/automation_time_axis.h b/gtk2_ardour/automation_time_axis.h
index 4be1a4c4d2..c298ac325b 100644
--- a/gtk2_ardour/automation_time_axis.h
+++ b/gtk2_ardour/automation_time_axis.h
@@ -105,8 +105,8 @@ class AutomationTimeAxisView : public TimeAxisView {
std::string state_id() const;
static bool parse_state_id (std::string const &, PBD::ID &, bool &, Evoral::Parameter &);
- boost::shared_ptr<ARDOUR::AutomationControl> control() { return _control; }
- boost::shared_ptr<AutomationController> controller() { return _controller; }
+ boost::shared_ptr<ARDOUR::AutomationControl> control() const { return _control; }
+ boost::shared_ptr<AutomationController> controller() const { return _controller; }
Evoral::Parameter parameter () const {
return _parameter;
}
diff --git a/gtk2_ardour/axis_view.cc b/gtk2_ardour/axis_view.cc
index 3d25b35e17..632289bddf 100644
--- a/gtk2_ardour/axis_view.cc
+++ b/gtk2_ardour/axis_view.cc
@@ -27,17 +27,19 @@
#include "pbd/error.h"
#include "pbd/convert.h"
+#include "pbd/i18n.h"
#include <gtkmm2ext/utils.h>
#include <gtkmm2ext/selector.h>
#include <gtkmm2ext/gtk_ui.h>
+#include "ardour/selection.h"
+
#include "public_editor.h"
#include "ardour_ui.h"
#include "gui_object.h"
#include "axis_view.h"
#include "utils.h"
-#include "pbd/i18n.h"
using namespace std;
using namespace Gtk;
@@ -131,10 +133,4 @@ AxisView::set_selected (bool yn)
}
Selectable::set_selected (yn);
-
- boost::shared_ptr<Stripable> s = stripable ();
-
- if (s) {
- s->presentation_info().set_selected (yn);
- }
}
diff --git a/gtk2_ardour/axis_view.h b/gtk2_ardour/axis_view.h
index 81fe489252..77518116a3 100644
--- a/gtk2_ardour/axis_view.h
+++ b/gtk2_ardour/axis_view.h
@@ -35,6 +35,10 @@
#include "prompter.h"
#include "selectable.h"
+namespace PBD {
+ class Controllable;
+}
+
namespace ARDOUR {
class Session;
class Stripable;
@@ -49,14 +53,13 @@ namespace ARDOUR {
class AxisView : public virtual PBD::ScopedConnectionList, public virtual ARDOUR::SessionHandlePtr, public virtual Selectable
{
public:
- ARDOUR::Session* session() const { return _session; }
-
virtual std::string name() const = 0;
virtual Gdk::Color color() const = 0;
sigc::signal<void> Hiding;
virtual boost::shared_ptr<ARDOUR::Stripable> stripable() const = 0;
+ virtual boost::shared_ptr<ARDOUR::AutomationControl> control() const { return boost::shared_ptr<ARDOUR::AutomationControl>(); }
virtual std::string state_id() const = 0;
/* for now, we always return properties in string form.
diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
index 0d6eb33416..7fe49de57b 100644
--- a/gtk2_ardour/editor.cc
+++ b/gtk2_ardour/editor.cc
@@ -642,6 +642,8 @@ Editor::Editor ()
bottom_hbox.set_border_width (2);
bottom_hbox.set_spacing (3);
+ PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&Editor::presentation_info_changed, this, _1), gui_context());
+
_route_groups = new EditorRouteGroups (this);
_routes = new EditorRoutes (this);
_regions = new EditorRegions (this);
@@ -1038,7 +1040,7 @@ Editor::control_unselect ()
void
Editor::control_select (boost::shared_ptr<Stripable> s, Selection::Operation op)
{
- TimeAxisView* tav = axis_view_from_stripable (s);
+ TimeAxisView* tav = time_axis_view_from_stripable (s);
if (tav) {
switch (op) {
@@ -1371,6 +1373,12 @@ Editor::set_session (Session *t)
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
set_state (*node, Stateful::loading_state_version);
+ /* catch up on selection state, etc. */
+
+ PropertyChange sc;
+ sc.add (Properties::selected);
+ presentation_info_changed (sc);
+
/* catch up with the playhead */
_session->request_locate (playhead_cursor->current_frame ());
@@ -1431,25 +1439,6 @@ Editor::set_session (Session *t)
break;
}
- /* catch up on selection of stripables (other selection state is lost
- * when a session is closed
- */
-
- StripableList sl;
- TrackViewList tl;
- _session->get_stripables (sl);
- for (StripableList::const_iterator s = sl.begin(); s != sl.end(); ++s) {
- if ((*s)->presentation_info().selected()) {
- RouteTimeAxisView* rtav = get_route_view_by_route_id ((*s)->id());
- if (rtav) {
- tl.push_back (rtav);
- }
- }
- }
- if (!tl.empty()) {
- selection->set (tl);
- }
-
/* register for undo history */
_session->register_with_memento_command_factory(id(), this);
_session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
@@ -5246,8 +5235,8 @@ Editor::region_view_removed ()
_summary->set_background_dirty ();
}
-TimeAxisView*
-Editor::axis_view_from_stripable (boost::shared_ptr<Stripable> s) const
+AxisView*
+Editor::axis_view_by_stripable (boost::shared_ptr<Stripable> s) const
{
for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
if ((*j)->stripable() == s) {
@@ -5258,6 +5247,17 @@ Editor::axis_view_from_stripable (boost::shared_ptr<Stripable> s) const
return 0;
}
+AxisView*
+Editor::axis_view_by_control (boost::shared_ptr<AutomationControl> c) const
+{
+ for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
+ if ((*j)->control() == c) {
+ return *j;
+ }
+ }
+
+ return 0;
+}
TrackViewList
Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
@@ -5265,7 +5265,7 @@ Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
TrackViewList t;
for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
- TimeAxisView* tv = axis_view_from_stripable (*i);
+ TimeAxisView* tv = time_axis_view_from_stripable (*i);
if (tv) {
t.push_back (tv);
}
diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
index 868817bddd..60bf93494d 100644
--- a/gtk2_ardour/editor.h
+++ b/gtk2_ardour/editor.h
@@ -140,14 +140,13 @@ class TimeSelection;
class RegionLayeringOrderEditor;
class VerboseCursor;
-class Editor : public PublicEditor, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr
+class Editor : public PublicEditor, public PBD::ScopedConnectionList
{
public:
Editor ();
~Editor ();
void set_session (ARDOUR::Session *);
- ARDOUR::Session* session() const { return _session; }
Gtk::Window* use_own_window (bool and_fill_it);
@@ -427,7 +426,7 @@ public:
void start_resize_line_ops ();
void end_resize_line_ops ();
- TrackViewList const & get_track_views () {
+ TrackViewList const & get_track_views () const {
return track_views;
}
@@ -1158,7 +1157,13 @@ private:
/* track views */
TrackViewList track_views;
std::pair<TimeAxisView*, double> trackview_by_y_position (double, bool trackview_relative_offset = true) const;
- TimeAxisView* axis_view_from_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
+
+ AxisView* axis_view_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
+ AxisView* axis_view_by_control (boost::shared_ptr<ARDOUR::AutomationControl>) const;
+
+ TimeAxisView* time_axis_view_from_stripable (boost::shared_ptr<ARDOUR::Stripable> s) const {
+ return dynamic_cast<TimeAxisView*> (axis_view_by_stripable (s));
+ }
TrackViewList get_tracks_for_range_action () const;
@@ -1857,7 +1862,7 @@ private:
void time_selection_changed ();
void update_time_selection_display ();
- void track_selection_changed ();
+ void presentation_info_changed (PBD::PropertyChange const &);
void region_selection_changed ();
sigc::connection editor_regions_selection_changed_connection;
void sensitize_all_region_actions (bool);
diff --git a/gtk2_ardour/editor_canvas_events.cc b/gtk2_ardour/editor_canvas_events.cc
index 132f6f870b..ad1cb8def8 100644
--- a/gtk2_ardour/editor_canvas_events.cc
+++ b/gtk2_ardour/editor_canvas_events.cc
@@ -1295,7 +1295,7 @@ Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
}
list<boost::shared_ptr<AudioTrack> > audio_tracks;
audio_tracks = session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
- rtav = dynamic_cast<RouteTimeAxisView*> (axis_view_from_stripable (audio_tracks.front()));
+ rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (audio_tracks.front()));
} else if (boost::dynamic_pointer_cast<MidiRegion> (region)) {
ChanCount one_midi_port (DataType::MIDI, 1);
list<boost::shared_ptr<MidiTrack> > midi_tracks;
@@ -1304,7 +1304,7 @@ Editor::drop_regions (const Glib::RefPtr<Gdk::DragContext>& /*context*/,
boost::shared_ptr<ARDOUR::PluginInfo>(),
(ARDOUR::Plugin::PresetRecord*) 0,
(ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
- rtav = dynamic_cast<RouteTimeAxisView*> (axis_view_from_stripable (midi_tracks.front()));
+ rtav = dynamic_cast<RouteTimeAxisView*> (time_axis_view_from_stripable (midi_tracks.front()));
} else {
return;
}
diff --git a/gtk2_ardour/editor_drag.cc b/gtk2_ardour/editor_drag.cc
index 35e9d395c5..90ef18f5b7 100644
--- a/gtk2_ardour/editor_drag.cc
+++ b/gtk2_ardour/editor_drag.cc
@@ -1443,7 +1443,7 @@ RegionMoveDrag::create_destination_time_axis (boost::shared_ptr<Region> region,
output_chan = _editor->session()->master_out()->n_inputs().n_audio();
}
audio_tracks = _editor->session()->new_audio_track (region->n_channels(), output_chan, 0, 1, region->name(), PresentationInfo::max_order);
- tav =_editor->axis_view_from_stripable (audio_tracks.front());
+ tav =_editor->time_axis_view_from_stripable (audio_tracks.front());
} else {
ChanCount one_midi_port (DataType::MIDI, 1);
list<boost::shared_ptr<MidiTrack> > midi_tracks;
@@ -1452,7 +1452,7 @@ RegionMoveDrag::create_destination_time_axis (boost::shared_ptr<Region> region,
boost::shared_ptr<ARDOUR::PluginInfo>(),
(ARDOUR::Plugin::PresetRecord*) 0,
(ARDOUR::RouteGroup*) 0, 1, region->name(), PresentationInfo::max_order);
- tav = _editor->axis_view_from_stripable (midi_tracks.front());
+ tav = _editor->time_axis_view_from_stripable (midi_tracks.front());
}
if (tav) {
diff --git a/gtk2_ardour/editor_mixer.cc b/gtk2_ardour/editor_mixer.cc
index 840b2293cf..0063536735 100644
--- a/gtk2_ardour/editor_mixer.cc
+++ b/gtk2_ardour/editor_mixer.cc
@@ -146,7 +146,7 @@ Editor::show_editor_mixer (bool yn)
if (current_mixer_strip && current_mixer_strip->get_parent() == 0) {
global_hpacker.pack_start (*current_mixer_strip, Gtk::PACK_SHRINK );
- global_hpacker.reorder_child (*current_mixer_strip, 0);
+ global_hpacker.reorder_child (*current_mixer_strip, 0);
current_mixer_strip->show ();
}
@@ -285,4 +285,3 @@ Editor::mixer_strip_width_changed ()
editor_mixer_strip_width = current_mixer_strip->get_width_enum ();
}
-
diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
index 008f609474..2348ef7ba5 100644
--- a/gtk2_ardour/editor_mouse.cc
+++ b/gtk2_ardour/editor_mouse.cc
@@ -337,7 +337,6 @@ Editor::update_time_selection_display ()
break;
case MouseObject:
selection->clear_time ();
- selection->clear_tracks ();
selection->clear_midi_notes ();
break;
case MouseDraw:
diff --git a/gtk2_ardour/editor_routes.cc b/gtk2_ardour/editor_routes.cc
index 0d08c6ea87..059439befe 100644
--- a/gtk2_ardour/editor_routes.cc
+++ b/gtk2_ardour/editor_routes.cc
@@ -31,6 +31,7 @@
#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
#include "ardour/route.h"
+#include "ardour/selection.h"
#include "ardour/session.h"
#include "ardour/solo_isolate_control.h"
#include "ardour/utils.h"
@@ -319,7 +320,6 @@ EditorRoutes::EditorRoutes (Editor* e)
_display.set_enable_search (false);
Route::PluginSetup.connect_same_thread (*this, boost::bind (&EditorRoutes::plugin_setup, this, _1, _2, _3));
- PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&EditorRoutes::presentation_info_changed, this, _1), gui_context());
}
bool
@@ -727,7 +727,10 @@ EditorRoutes::time_axis_views_added (list<TimeAxisView*> tavs)
}
}
- _display.set_model (Glib::RefPtr<ListStore>());
+ {
+ PBD::Unwinder<bool> uw (_ignore_selection_change, true);
+ _display.set_model (Glib::RefPtr<ListStore>());
+ }
for (list<TimeAxisView*>::iterator x = tavs.begin(); x != tavs.end(); ++x) {
@@ -754,7 +757,6 @@ EditorRoutes::time_axis_views_added (list<TimeAxisView*> tavs)
row[_columns.is_track] = (boost::dynamic_pointer_cast<Track> (stripable) != 0);
-
if (midi_trk) {
row[_columns.is_input_active] = midi_trk->input_active ();
row[_columns.is_midi] = true;
@@ -832,7 +834,11 @@ EditorRoutes::time_axis_views_added (list<TimeAxisView*> tavs)
update_input_active_display ();
update_active_display ();
- _display.set_model (_model);
+ {
+ PBD::Unwinder<bool> uw (_ignore_selection_change, true);
+ cerr << "Should ignore model/selection change\n";
+ _display.set_model (_model);
+ }
/* now update route order keys from the treeview/track display order */
@@ -1083,19 +1089,6 @@ EditorRoutes::sync_presentation_info_from_treeview ()
}
void
-EditorRoutes::presentation_info_changed (PropertyChange const & what_changed)
-{
- PropertyChange soh;
- soh.add (Properties::selected);
- soh.add (Properties::order);
- soh.add (Properties::hidden);
-
- if (what_changed.contains (soh)) {
- sync_treeview_from_presentation_info (what_changed);
- }
-}
-
-void
EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_changed)
{
/* Some route order key(s) have been changed, make sure that
@@ -1169,13 +1162,18 @@ EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_
if (what_changed.contains (Properties::selected)) {
+ /* by the time this is invoked, the GUI Selection model has
+ * already updated itself.
+ */
+
TrackViewList tvl;
PBD::Unwinder<bool> uw (_ignore_selection_change, true);
- /* step one: set the treeview model selection state */
+ /* set the treeview model selection state */
+
for (TreeModel::Children::iterator ri = rows.begin(); ri != rows.end(); ++ri) {
boost::shared_ptr<Stripable> stripable = (*ri)[_columns.stripable];
- if (stripable && stripable->presentation_info().selected()) {
+ if (stripable && stripable->is_selected()) {
TimeAxisView* tav = (*ri)[_columns.tv];
if (tav) {
tvl.push_back (tav);
@@ -1185,12 +1183,6 @@ EditorRoutes::sync_treeview_from_presentation_info (PropertyChange const & what_
_display.get_selection()->unselect (*ri);
}
}
-
- /* step two: set the Selection (for stripables/routes) */
- _editor->get_selection().set (tvl);
-
- /* step three, tell the editor */
- _editor->track_selection_changed ();
}
redisplay ();
@@ -1645,7 +1637,7 @@ EditorRoutes::move_selected_tracks (bool up)
/* build a list that includes time axis view information */
for (StripableList::const_iterator sli = sl.begin(); sli != sl.end(); ++sli) {
- TimeAxisView* tv = _editor->axis_view_from_stripable (*sli);
+ TimeAxisView* tv = _editor->time_axis_view_from_stripable (*sli);
view_stripables.push_back (ViewStripable (tv, *sli));
}
@@ -1666,7 +1658,7 @@ EditorRoutes::move_selected_tracks (bool up)
while (vsi != view_stripables.end()) {
- if (vsi->stripable->presentation_info().selected()) {
+ if (vsi->stripable->is_selected()) {
if (unselected_neighbour != view_stripables.end()) {
@@ -1701,7 +1693,7 @@ EditorRoutes::move_selected_tracks (bool up)
--vsi;
- if (vsi->stripable->presentation_info().selected()) {
+ if (vsi->stripable->is_selected()) {
if (unselected_neighbour != view_stripables.end()) {
@@ -1852,6 +1844,7 @@ EditorRoutes::views () const
void
EditorRoutes::clear ()
{
+ PBD::Unwinder<bool> uw (_ignore_selection_change, true);
_display.set_model (Glib::RefPtr<Gtk::TreeStore> (0));
_model->clear ();
_display.set_model (_model);
@@ -1902,7 +1895,7 @@ EditorRoutes::show_tracks_with_regions_at_playhead ()
set<TimeAxisView*> show;
for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
- TimeAxisView* tav = _editor->axis_view_from_stripable (*i);
+ TimeAxisView* tav = _editor->time_axis_view_from_stripable (*i);
if (tav) {
show.insert (tav);
}
diff --git a/gtk2_ardour/editor_routes.h b/gtk2_ardour/editor_routes.h
index a9d7115fdf..2ceb6682b2 100644
--- a/gtk2_ardour/editor_routes.h
+++ b/gtk2_ardour/editor_routes.h
@@ -65,6 +65,7 @@ public:
void hide_all_tracks (bool);
void clear ();
void sync_presentation_info_from_treeview ();
+ void sync_treeview_from_presentation_info (PBD::PropertyChange const &);
private:
void initial_display ();
@@ -78,7 +79,6 @@ private:
void on_tv_solo_safe_toggled (std::string const &);
void build_menu ();
void presentation_info_changed (PBD::PropertyChange const &);
- void sync_treeview_from_presentation_info (PBD::PropertyChange const &);
void row_deleted (Gtk::TreeModel::Path const &);
void visible_changed (std::string const &);
void active_changed (std::string const &);
diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
index 770bfe9c1f..c9e2ba49fd 100644
--- a/gtk2_ardour/editor_selection.cc
+++ b/gtk2_ardour/editor_selection.cc
@@ -27,12 +27,14 @@
#include "ardour/playlist.h"
#include "ardour/profile.h"
#include "ardour/route_group.h"
+#include "ardour/selection.h"
#include "ardour/session.h"
#include "control_protocol/control_protocol.h"
-#include "editor_drag.h"
#include "editor.h"
+#include "editor_drag.h"
+#include "editor_routes.h"
#include "actions.h"
#include "audio_time_axis.h"
#include "audio_region_view.h"
@@ -267,9 +269,7 @@ Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no
break;
case Selection::Add:
- if (!selection->selected (&view)) {
- selection->add (&view);
- }
+ selection->add (&view);
break;
case Selection::Set:
@@ -999,84 +999,136 @@ struct SelectionOrderSorter {
};
void
-Editor::track_selection_changed ()
+Editor::presentation_info_changed (PropertyChange const & what_changed)
{
- SelectionOrderSorter cmp;
- selection->tracks.sort (cmp);
+ /* We cannot ensure ordering of the handlers for
+ * PresentationInfo::Changed, so we have to do everything in order
+ * here, as a single handler.
+ */
- switch (selection->tracks.size()) {
- case 0:
- break;
- default:
- set_selected_mixer_strip (*(selection->tracks.back()));
- if (!_track_selection_change_without_scroll) {
- ensure_time_axis_view_is_visible (*(selection->tracks.back()), false);
- }
- break;
+ for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+ (*i)->set_selected (false);
+ (*i)->hide_selection ();
}
- RouteNotificationListPtr routes (new RouteNotificationList);
- StripableNotificationListPtr stripables (new StripableNotificationList);
+ /* STEP 1: set the GUI selection state (in which TimeAxisViews for the
+ * currently selected stripable/controllable duples are found and added
+ */
- for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+ selection->core_selection_changed (what_changed);
- bool yn = (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end());
+ /* STEP 2: update TimeAxisView's knowledge of their selected state
+ */
- (*i)->set_selected (yn);
- TimeAxisView::Children c = (*i)->get_child_list ();
- for (TimeAxisView::Children::iterator j = c.begin(); j != c.end(); ++j) {
- (*j)->set_selected (find (selection->tracks.begin(), selection->tracks.end(), j->get()) != selection->tracks.end());
- }
+ PropertyChange pc;
+ pc.add (Properties::selected);
- if (yn) {
- (*i)->reshow_selection (selection->time);
- } else {
- (*i)->hide_selection ();
- }
+ if (what_changed.contains (Properties::selected)) {
+ StripableNotificationListPtr stripables (new StripableNotificationList);
- if (yn) {
- RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*i);
- if (rtav) {
- routes->push_back (rtav->route());
- stripables->push_back (rtav->route());
+ switch (selection->tracks.size()) {
+ case 0:
+ break;
+ default:
+ set_selected_mixer_strip (*(selection->tracks.back()));
+ if (!_track_selection_change_without_scroll) {
+ ensure_time_axis_view_is_visible (*(selection->tracks.back()), false);
}
+ break;
}
- }
- ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
+ CoreSelection::StripableAutomationControls sc;
+ _session->selection().get_stripables (sc);
- sensitize_the_right_region_actions (false);
+ for (CoreSelection::StripableAutomationControls::const_iterator i = sc.begin(); i != sc.end(); ++i) {
- /* notify control protocols */
+ AxisView* av = axis_view_by_stripable ((*i).stripable);
- ControlProtocol::StripableSelectionChanged (stripables);
+ if (!av) {
+ continue;
+ }
- if (sfbrowser && _session && !_session->deletion_in_progress()) {
- uint32_t audio_track_cnt = 0;
- uint32_t midi_track_cnt = 0;
+ TimeAxisView* tav = dynamic_cast<TimeAxisView*> (av);
- for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
- AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*x);
+ if (!tav) {
+ continue; /* impossible */
+ }
- if (atv) {
- if (atv->is_audio_track()) {
- audio_track_cnt++;
- }
+ if (!(*i).controllable) {
+
+ /* "parent" track selected */
+ tav->set_selected (true);
+ tav->reshow_selection (selection->time);
} else {
- MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(*x);
- if (mtv) {
- if (mtv->is_midi_track()) {
- midi_track_cnt++;
+ /* possibly a child */
+
+ TimeAxisView::Children c = tav->get_child_list ();
+
+ for (TimeAxisView::Children::iterator j = c.begin(); j != c.end(); ++j) {
+
+ boost::shared_ptr<AutomationControl> control = (*j)->control ();
+
+ if (control != (*i).controllable) {
+ continue;
}
+
+ (*j)->set_selected (true);
+ (*j)->reshow_selection (selection->time);
}
}
+
+ stripables->push_back ((*i).stripable);
+ }
+
+ ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
+
+ sensitize_the_right_region_actions (false);
+
+ /* STEP 4: notify control protocols */
+
+ ControlProtocol::StripableSelectionChanged (stripables);
+
+ if (sfbrowser && _session && !_session->deletion_in_progress()) {
+ uint32_t audio_track_cnt = 0;
+ uint32_t midi_track_cnt = 0;
+
+ for (TrackSelection::iterator x = selection->tracks.begin(); x != selection->tracks.end(); ++x) {
+ AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*x);
+
+ if (atv) {
+ if (atv->is_audio_track()) {
+ audio_track_cnt++;
+ }
+
+ } else {
+ MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(*x);
+
+ if (mtv) {
+ if (mtv->is_midi_track()) {
+ midi_track_cnt++;
+ }
+ }
+ }
+ }
+
+ sfbrowser->reset (audio_track_cnt, midi_track_cnt);
}
+ }
- sfbrowser->reset (audio_track_cnt, midi_track_cnt);
+ /* STEP 4: update EditorRoutes treeview */
+
+ PropertyChange soh;
+
+ soh.add (Properties::selected);
+ soh.add (Properties::order);
+ soh.add (Properties::hidden);
+
+ if (what_changed.contains (soh)) {
+ _routes->sync_treeview_from_presentation_info (what_changed);
}
}
@@ -1570,28 +1622,32 @@ Editor::select_all_objects (Selection::Operation op)
{
list<Selectable *> touched;
- TrackViewList ts = track_views;
-
if (internal_editing() && select_all_internal_edit(op)) {
return; // Selected notes
}
+ TrackViewList ts;
+
+ if (selection->tracks.empty()) {
+ ts = track_views;
+ } else {
+ ts = selection->tracks;
+ }
+
for (TrackViewList::iterator iter = ts.begin(); iter != ts.end(); ++iter) {
if ((*iter)->hidden()) {
continue;
}
(*iter)->get_selectables (0, max_framepos, 0, DBL_MAX, touched);
- selection->add (*iter);
}
-
begin_reversible_selection_op (X_("select all"));
switch (op) {
case Selection::Add:
selection->add (touched);
break;
case Selection::Toggle:
- selection->add (touched);
+ selection->toggle (touched);
break;
case Selection::Set:
selection->set (touched);
diff --git a/gtk2_ardour/mixer_ui.cc b/gtk2_ardour/mixer_ui.cc
index 4c5d60d6c7..b70ceef37d 100644
--- a/gtk2_ardour/mixer_ui.cc
+++ b/gtk2_ardour/mixer_ui.cc
@@ -48,6 +48,7 @@
#include "ardour/midi_track.h"
#include "ardour/plugin_manager.h"
#include "ardour/route_group.h"
+#include "ardour/selection.h"
#include "ardour/session.h"
#include "ardour/vca.h"
#include "ardour/vca_manager.h"
@@ -110,6 +111,7 @@ Mixer_UI::Mixer_UI ()
, _maximised (false)
, _show_mixer_list (true)
, myactions (X_("mixer"))
+ , _selection (*this, *this)
{
register_actions ();
load_bindings ();
@@ -683,6 +685,8 @@ Mixer_UI::remove_strip (MixerStrip* strip)
void
Mixer_UI::presentation_info_changed (PropertyChange const & what_changed)
{
+ _selection.presentation_info_changed (what_changed);
+
PropertyChange soh;
soh.add (Properties::selected);
soh.add (Properties::order);
@@ -850,7 +854,7 @@ Mixer_UI::sync_treeview_from_presentation_info (PropertyChange const & what_chan
for (list<MixerStrip *>::const_iterator i = strips.begin(); i != strips.end(); ++i) {
boost::shared_ptr<Stripable> stripable = (*i)->stripable();
- if (stripable && stripable->presentation_info().selected()) {
+ if (stripable && stripable->is_selected()) {
_selection.add (*i);
} else {
_selection.remove (*i);
@@ -891,7 +895,7 @@ Mixer_UI::strip_by_stripable (boost::shared_ptr<Stripable> s) const
}
AxisView*
-Mixer_UI::axis_by_stripable (boost::shared_ptr<Stripable> s) const
+Mixer_UI::axis_view_by_stripable (boost::shared_ptr<Stripable> s) const
{
for (list<MixerStrip *>::const_iterator i = strips.begin(); i != strips.end(); ++i) {
if ((*i)->stripable() == s) {
@@ -902,6 +906,18 @@ Mixer_UI::axis_by_stripable (boost::shared_ptr<Stripable> s) const
return 0;
}
+AxisView*
+Mixer_UI::axis_view_by_control (boost::shared_ptr<AutomationControl> c) const
+{
+ for (list<MixerStrip *>::const_iterator i = strips.begin(); i != strips.end(); ++i) {
+ if ((*i)->control() == c) {
+ return (*i);
+ }
+ }
+
+ return 0;
+}
+
bool
Mixer_UI::strip_button_release_event (GdkEventButton *ev, MixerStrip *strip)
{
@@ -1000,6 +1016,7 @@ Mixer_UI::set_session (Session* sess)
}
if (!_session) {
+ _selection.clear ();
return;
}
@@ -1029,6 +1046,13 @@ Mixer_UI::set_session (Session* sess)
if (_visible) {
show_window();
}
+
+ /* catch up on selection state, etc. */
+
+ PropertyChange sc;
+ sc.add (Properties::selected);
+ _selection.presentation_info_changed (sc);
+
start_updating ();
}
diff --git a/gtk2_ardour/mixer_ui.h b/gtk2_ardour/mixer_ui.h
index 413c8be727..4e2bda711b 100644
--- a/gtk2_ardour/mixer_ui.h
+++ b/gtk2_ardour/mixer_ui.h
@@ -47,6 +47,7 @@
#include "gtkmm2ext/tabbable.h"
#include "gtkmm2ext/treeutils.h"
+#include "axis_provider.h"
#include "enums.h"
#include "route_processor_selection.h"
@@ -76,7 +77,7 @@ protected:
virtual bool row_drop_possible_vfunc (const Gtk::TreeModel::Path&, const Gtk::SelectionData&) const;
};
-class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr
+class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, public ARDOUR::SessionHandlePtr, public AxisViewProvider
{
public:
static Mixer_UI* instance();
@@ -188,7 +189,9 @@ class Mixer_UI : public Gtkmm2ext::Tabbable, public PBD::ScopedConnectionList, p
MixerStrip* strip_by_route (boost::shared_ptr<ARDOUR::Route>) const;
MixerStrip* strip_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
- AxisView* axis_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
+
+ AxisView* axis_view_by_stripable (boost::shared_ptr<ARDOUR::Stripable>) const;
+ AxisView* axis_view_by_control (boost::shared_ptr<ARDOUR::AutomationControl>) const;
void hide_all_strips (bool with_select);
void unselect_all_strips();
diff --git a/gtk2_ardour/monitor_section.cc b/gtk2_ardour/monitor_section.cc
index de1d9504c0..2cd46c051a 100644
--- a/gtk2_ardour/monitor_section.cc
+++ b/gtk2_ardour/monitor_section.cc
@@ -88,6 +88,7 @@ MonitorSection::MonitorSection (Session* s)
, solo_mute_override_button (ArdourButton::led_default_elements)
, toggle_processorbox_button (ArdourButton::default_elements)
, _inhibit_solo_model_update (false)
+ , _rr_selection ()
, _ui_initialized (false)
{
diff --git a/gtk2_ardour/monitor_section.h b/gtk2_ardour/monitor_section.h
index b58203f521..61f4480c2f 100644
--- a/gtk2_ardour/monitor_section.h
+++ b/gtk2_ardour/monitor_section.h
@@ -32,8 +32,8 @@
#include "monitor_selector.h"
#include "plugin_selector.h"
-#include "route_processor_selection.h"
#include "processor_box.h"
+#include "processor_selection.h"
namespace Gtkmm2ext {
class TearOff;
@@ -192,7 +192,7 @@ class MonitorSection : public RouteUI, public Gtk::EventBox
ProcessorBox* insert_box;
PluginSelector* _plugin_selector;
- RouteProcessorSelection _rr_selection;
+ ProcessorSelection _rr_selection;
void help_count_processors (boost::weak_ptr<ARDOUR::Processor> p, uint32_t* cnt) const;
uint32_t count_processors ();
diff --git a/gtk2_ardour/monitor_selector.h b/gtk2_ardour/monitor_selector.h
index 8c642b5dfe..8e572e958c 100644
--- a/gtk2_ardour/monitor_selector.h
+++ b/gtk2_ardour/monitor_selector.h
@@ -34,8 +34,6 @@ class MonitorSelector : public PortMatrix
std::string disassociation_verb () const;
std::string channel_noun () const;
- ARDOUR::Session* session() const { return _session; }
-
uint32_t n_io_ports () const;
boost::shared_ptr<ARDOUR::IO> const io () { return _io; }
void setup_ports (int);
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 7439fe1b77..5db8585a83 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -378,7 +378,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
/* Now put the bundles that belong to these sorted RouteIOs into the PortGroup. */
for (list<RouteIOs>::iterator i = route_ios.begin(); i != route_ios.end(); ++i) {
- TimeAxisView* tv = PublicEditor::instance().axis_view_from_stripable (i->route);
+ TimeAxisView* tv = PublicEditor::instance().time_axis_view_from_stripable (i->route);
/* Work out which group to put these IOs' bundles in */
boost::shared_ptr<PortGroup> g;
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index 37645f0185..34bcbf28b5 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -76,9 +76,9 @@
#include "plugin_ui.h"
#include "port_insert_ui.h"
#include "processor_box.h"
+#include "processor_selection.h"
#include "public_editor.h"
#include "return_ui.h"
-#include "route_processor_selection.h"
#include "script_selector.h"
#include "send_ui.h"
#include "timers.h"
@@ -1807,14 +1807,14 @@ static std::list<Gtk::TargetEntry> drag_targets_noplugin()
}
ProcessorBox::ProcessorBox (ARDOUR::Session* sess, boost::function<PluginSelector*()> get_plugin_selector,
- RouteProcessorSelection& rsel, MixerStrip* parent, bool owner_is_mixer)
+ ProcessorSelection& psel, MixerStrip* parent, bool owner_is_mixer)
: _parent_strip (parent)
, _owner_is_mixer (owner_is_mixer)
, ab_direction (true)
, _get_plugin_selector (get_plugin_selector)
, _placement (-1)
, _visible_prefader_processors (0)
- , _rr_selection(rsel)
+ , _p_selection(psel)
, processor_display (drop_targets())
, _redisplay_pending (false)
{
@@ -2200,7 +2200,7 @@ ProcessorBox::show_processor_menu (int arg)
const bool sensitive = !processor_display.selection().empty() && ! stub_processor_selected ();
- paste_action->set_sensitive (!_rr_selection.processors.empty());
+ paste_action->set_sensitive (!_p_selection.processors.empty());
cut_action->set_sensitive (sensitive && can_cut ());
copy_action->set_sensitive (sensitive);
delete_action->set_sensitive (sensitive || stub_processor_selected ());
@@ -3165,7 +3165,7 @@ ProcessorBox::cut_processors (const ProcSelection& to_be_removed)
return;
}
- _rr_selection.set (node);
+ _p_selection.set (node);
no_processor_redisplay = false;
redisplay_processors ();
@@ -3189,7 +3189,7 @@ ProcessorBox::copy_processors (const ProcSelection& to_be_copied)
}
}
- _rr_selection.set (node);
+ _p_selection.set (node);
}
void
@@ -3304,22 +3304,22 @@ ProcessorBox::rename_processor (boost::shared_ptr<Processor> processor)
void
ProcessorBox::paste_processors ()
{
- if (_rr_selection.processors.empty()) {
+ if (_p_selection.processors.empty()) {
return;
}
- paste_processor_state (_rr_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
+ paste_processor_state (_p_selection.processors.get_node().children(), boost::shared_ptr<Processor>());
}
void
ProcessorBox::paste_processors (boost::shared_ptr<Processor> before)
{
- if (_rr_selection.processors.empty()) {
+ if (_p_selection.processors.empty()) {
return;
}
- paste_processor_state (_rr_selection.processors.get_node().children(), before);
+ paste_processor_state (_p_selection.processors.get_node().children(), before);
}
void
diff --git a/gtk2_ardour/processor_box.h b/gtk2_ardour/processor_box.h
index 330a920e87..5e73afa45c 100644
--- a/gtk2_ardour/processor_box.h
+++ b/gtk2_ardour/processor_box.h
@@ -62,7 +62,7 @@
class MotionController;
class PluginSelector;
class PluginUIWindow;
-class RouteProcessorSelection;
+class ProcessorSelection;
class MixerStrip;
namespace ARDOUR {
@@ -414,7 +414,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
};
ProcessorBox (ARDOUR::Session*, boost::function<PluginSelector*()> get_plugin_selector,
- RouteProcessorSelection&, MixerStrip* parent, bool owner_is_mixer = false);
+ ProcessorSelection&, MixerStrip* parent, bool owner_is_mixer = false);
~ProcessorBox ();
void set_route (boost::shared_ptr<ARDOUR::Route>);
@@ -490,7 +490,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject, public ARD
int _placement;
uint32_t _visible_prefader_processors;
- RouteProcessorSelection& _rr_selection;
+ ProcessorSelection& _p_selection;
static Gtkmm2ext::ActionMap myactions;
static void load_bindings ();
diff --git a/gtk2_ardour/processor_selection.h b/gtk2_ardour/processor_selection.h
index d371493b41..fc3a133ef1 100644
--- a/gtk2_ardour/processor_selection.h
+++ b/gtk2_ardour/processor_selection.h
@@ -1,5 +1,5 @@
/*
- Copyright (C) 2000-2007 Paul Davis
+ Copyright (C) 2004 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
@@ -20,40 +20,64 @@
#ifndef __ardour_gtk_processor_selection_h__
#define __ardour_gtk_processor_selection_h__
+#include <vector>
+
+#include "pbd/signals.h"
#include "pbd/xml++.h"
-class ProcessorSelection {
+class XMLProcessorSelection {
public:
- ProcessorSelection() : node (0) {}
- ~ProcessorSelection() { if (node) { delete node; } }
-
- void set (XMLNode* n) {
- if (node) {
- delete node;
- }
- node = n;
- }
-
- void add (XMLNode* newchild) {
- if (!node) {
- node = new XMLNode ("add");
- }
- node->add_child_nocopy (*newchild);
- }
-
- void clear () {
- if (node) {
- delete node;
- node = 0;
- }
- }
-
- bool empty () const { return node == 0 || node->children().empty(); }
-
- const XMLNode& get_node() const { return *node; }
+ XMLProcessorSelection() : node (0) {}
+ ~XMLProcessorSelection() { if (node) { delete node; } }
+
+ void set (XMLNode* n) {
+ if (node) {
+ delete node;
+ }
+ node = n;
+ }
+
+ void add (XMLNode* newchild) {
+ if (!node) {
+ node = new XMLNode ("add");
+ }
+ node->add_child_nocopy (*newchild);
+ }
+
+ void clear () {
+ if (node) {
+ delete node;
+ node = 0;
+ }
+ }
+
+ bool empty () const { return node == 0 || node->children().empty(); }
+
+ const XMLNode& get_node() const { return *node; }
private:
- XMLNode* node;
+ XMLNode* node;
};
+class ProcessorSelection : public PBD::ScopedConnectionList, public sigc::trackable
+{
+ public:
+ ProcessorSelection () {}
+
+ XMLProcessorSelection processors;
+ sigc::signal<void> ProcessorsChanged;
+
+ ProcessorSelection& operator= (const ProcessorSelection& other);
+
+ void clear ();
+ bool empty();
+
+ void set (XMLNode* node);
+ void add (XMLNode* node);
+
+ void clear_processors ();
+};
+
+bool operator==(const ProcessorSelection& a, const ProcessorSelection& b);
+
#endif /* __ardour_gtk_processor_selection_h__ */
diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
index ea7980fb7b..f0ed177500 100644
--- a/gtk2_ardour/public_editor.h
+++ b/gtk2_ardour/public_editor.h
@@ -40,6 +40,8 @@
#include "pbd/statefuldestructible.h"
+#include "ardour/session_handle.h"
+
#include "canvas/fwd.h"
#include "gtkmm2ext/actions.h"
@@ -47,6 +49,7 @@
#include "gtkmm2ext/tabbable.h"
#include "gtkmm2ext/visibility_tracker.h"
+#include "axis_provider.h"
#include "editing.h"
#include "selection.h"
@@ -105,8 +108,8 @@ using ARDOUR::framecnt_t;
* of PublicEditor need not be recompiled if private methods or member variables
* change.
*/
-class PublicEditor : public Gtkmm2ext::Tabbable {
-public:
+class PublicEditor : public Gtkmm2ext::Tabbable, public ARDOUR::SessionHandlePtr, public AxisViewProvider {
+ public:
PublicEditor (Gtk::Widget& content);
virtual ~PublicEditor ();
@@ -123,9 +126,6 @@ public:
*/
virtual void set_session (ARDOUR::Session* s) = 0;
- /** @return The Session that we are editing, or 0 */
- virtual ARDOUR::Session* session () const = 0;
-
/** Set the snap type.
* @param t Snap type (defined in editing_syms.h)
*/
@@ -353,6 +353,8 @@ public:
virtual RouteTimeAxisView* get_route_view_by_route_id (const PBD::ID& id) const = 0;
+ virtual TimeAxisView* time_axis_view_from_stripable (boost::shared_ptr<ARDOUR::Stripable> s) const = 0;
+
virtual void get_equivalent_regions (RegionView* rv, std::vector<RegionView*>&, PBD::PropertyID) const = 0;
virtual RegionView* regionview_from_region (boost::shared_ptr<ARDOUR::Region>) const = 0;
virtual RouteTimeAxisView* rtav_from_route (boost::shared_ptr<ARDOUR::Route>) const = 0;
@@ -422,15 +424,13 @@ public:
virtual ArdourCanvas::GtkCanvasViewport* get_track_canvas() const = 0;
- virtual TimeAxisView* axis_view_from_stripable (boost::shared_ptr<ARDOUR::Stripable>) const = 0;
-
virtual void set_current_trimmable (boost::shared_ptr<ARDOUR::Trimmable>) = 0;
virtual void set_current_movable (boost::shared_ptr<ARDOUR::Movable>) = 0;
virtual void center_screen (framepos_t) = 0;
virtual TrackViewList axis_views_from_routes (boost::shared_ptr<ARDOUR::RouteList>) const = 0;
- virtual TrackViewList const & get_track_views () = 0;
+ virtual TrackViewList const & get_track_views () const = 0;
virtual DragManager* drags () const = 0;
virtual void maybe_autoscroll (bool, bool, bool from_headers) = 0;
diff --git a/gtk2_ardour/route_params_ui.cc b/gtk2_ardour/route_params_ui.cc
index a8ddc02c1f..b377c838db 100644
--- a/gtk2_ardour/route_params_ui.cc
+++ b/gtk2_ardour/route_params_ui.cc
@@ -56,9 +56,9 @@ using namespace Gtk;
using namespace Gtkmm2ext;
RouteParams_UI::RouteParams_UI ()
- : ArdourWindow (_("Tracks and Busses")),
- latency_apply_button (Stock::APPLY),
- track_menu(0)
+ : ArdourWindow (_("Tracks and Busses"))
+ , latency_apply_button (Stock::APPLY)
+ , track_menu(0)
{
insert_box = 0;
_input_iosel = 0;
@@ -235,7 +235,7 @@ RouteParams_UI::setup_processor_boxes()
cleanup_processor_boxes();
// construct new redirect boxes
- insert_box = new ProcessorBox (_session, boost::bind (&RouteParams_UI::plugin_selector, this), _rr_selection, 0);
+ insert_box = new ProcessorBox (_session, boost::bind (&RouteParams_UI::plugin_selector, this), _p_selection, 0);
insert_box->set_route (_route);
boost::shared_ptr<AudioTrack> at = boost::dynamic_pointer_cast<AudioTrack>(_route);
diff --git a/gtk2_ardour/route_params_ui.h b/gtk2_ardour/route_params_ui.h
index 83ddf27110..2f04590c2b 100644
--- a/gtk2_ardour/route_params_ui.h
+++ b/gtk2_ardour/route_params_ui.h
@@ -40,7 +40,7 @@
#include "ardour_window.h"
#include "processor_box.h"
-#include "route_processor_selection.h"
+#include "processor_selection.h"
#include "latency_gui.h"
namespace ARDOUR {
@@ -113,7 +113,7 @@ class RouteParams_UI : public ArdourWindow, public PBD::ScopedConnectionList
IOSelector * _output_iosel;
PluginSelector *_plugin_selector;
- RouteProcessorSelection _rr_selection;
+ ProcessorSelection _p_selection;
boost::shared_ptr<ARDOUR::Route> _route;
PBD::ScopedConnection _route_processors_connection;
diff --git a/gtk2_ardour/route_processor_selection.cc b/gtk2_ardour/route_processor_selection.cc
index 5b0b48c4ba..0dc15e7f8a 100644
--- a/gtk2_ardour/route_processor_selection.cc
+++ b/gtk2_ardour/route_processor_selection.cc
@@ -19,21 +19,27 @@
#include <algorithm>
#include <sigc++/bind.h>
+
#include "pbd/error.h"
+#include "pbd/i18n.h"
+#include "ardour/selection.h"
+#include "ardour/session.h"
+#include "ardour/session_handle.h"
+
+#include "axis_provider.h"
#include "gui_thread.h"
#include "mixer_strip.h"
+#include "mixer_ui.h"
#include "route_processor_selection.h"
#include "route_ui.h"
-#include "pbd/i18n.h"
-
using namespace std;
using namespace ARDOUR;
using namespace PBD;
-
-RouteProcessorSelection::RouteProcessorSelection()
+RouteProcessorSelection::RouteProcessorSelection (SessionHandlePtr& s, AxisViewProvider& ap)
+ : shp (s), avp (ap)
{
}
@@ -41,7 +47,7 @@ RouteProcessorSelection&
RouteProcessorSelection::operator= (const RouteProcessorSelection& other)
{
if (&other != this) {
- processors = other.processors;
+ (*((ProcessorSelection*) this)) = (*((ProcessorSelection const *) &other));
axes = other.axes;
}
return *this;
@@ -62,46 +68,57 @@ RouteProcessorSelection::clear ()
}
void
-RouteProcessorSelection::clear_processors ()
+RouteProcessorSelection::clear_routes ()
{
- processors.clear ();
- ProcessorsChanged ();
+ if (shp.session()) {
+ PresentationInfo::ChangeSuspender cs;
+ shp.session()->selection().clear_stripables ();
+ }
}
void
-RouteProcessorSelection::clear_routes ()
+RouteProcessorSelection::presentation_info_changed (PropertyChange const & what_changed)
{
- PresentationInfo::ChangeSuspender cs;
+ Session* s = shp.session();
- for (AxisViewSelection::iterator i = axes.begin(); i != axes.end(); ++i) {
- (*i)->set_selected (false);
+ if (!s) {
+ /* too early ... session handle provider doesn't know about the
+ session yet.
+ */
+ return;
}
- axes.clear ();
- drop_connections ();
-}
-void
-RouteProcessorSelection::add (XMLNode* node)
-{
- // XXX check for duplicate
- processors.add (node);
- ProcessorsChanged();
-}
+ PropertyChange pc;
+ pc.add (Properties::selected);
-void
-RouteProcessorSelection::set (XMLNode* node)
-{
- clear_processors ();
- processors.set (node);
- ProcessorsChanged ();
+ CoreSelection::StripableAutomationControls sc;
+ s->selection().get_stripables (sc);
+
+ for (AxisViewSelection::iterator a = axes.begin(); a != axes.end(); ++a) {
+ (*a)->set_selected (false);
+ }
+
+ axes.clear ();
+
+ for (CoreSelection::StripableAutomationControls::const_iterator i = sc.begin(); i != sc.end(); ++i) {
+ AxisView* av = avp.axis_view_by_stripable ((*i).stripable);
+ if (av) {
+ axes.insert (av);
+ av->set_selected (true);
+ }
+ }
}
void
RouteProcessorSelection::add (AxisView* r)
{
+ if (!shp.session()) {
+ return;
+ }
+
if (axes.insert (r).second) {
- r->set_selected (true);
+ shp.session()->selection().add (r->stripable(), boost::shared_ptr<AutomationControl>());
MixerStrip* ms = dynamic_cast<MixerStrip*> (r);
@@ -114,23 +131,20 @@ RouteProcessorSelection::add (AxisView* r)
void
RouteProcessorSelection::remove (AxisView* r)
{
- ENSURE_GUI_THREAD (*this, &RouteProcessorSelection::remove, r);
- PresentationInfo::ChangeSuspender cs;
-
- AxisViewSelection::iterator i;
- if ((i = find (axes.begin(), axes.end(), r)) != axes.end()) {
- AxisView* av = *i;
- axes.erase (i);
- av->set_selected (false);
+ if (!shp.session()) {
+ return;
}
+ ENSURE_GUI_THREAD (*this, &RouteProcessorSelection::remove, r);
+ shp.session()->selection().remove (r->stripable(), boost::shared_ptr<AutomationControl>());
}
void
RouteProcessorSelection::set (AxisView* r)
{
- PresentationInfo::ChangeSuspender cs;
- clear_routes ();
- add (r);
+ if (!shp.session()) {
+ return;
+ }
+ shp.session()->selection().set (r->stripable(), boost::shared_ptr<AutomationControl>());
}
bool
diff --git a/gtk2_ardour/route_processor_selection.h b/gtk2_ardour/route_processor_selection.h
index c708723e4d..b0e7c36fbd 100644
--- a/gtk2_ardour/route_processor_selection.h
+++ b/gtk2_ardour/route_processor_selection.h
@@ -26,34 +26,36 @@
#include "processor_selection.h"
#include "route_ui_selection.h"
-class RouteProcessorSelection : public PBD::ScopedConnectionList, public sigc::trackable
+namespace ARDOUR {
+ class SessionHandlePtr;
+}
+
+class AxisViewProvider;
+
+class RouteProcessorSelection : public ProcessorSelection
{
public:
- ProcessorSelection processors;
AxisViewSelection axes;
- RouteProcessorSelection();
+ RouteProcessorSelection (ARDOUR::SessionHandlePtr&, AxisViewProvider&);
RouteProcessorSelection& operator= (const RouteProcessorSelection& other);
- sigc::signal<void> ProcessorsChanged;
-
void clear ();
bool empty();
- void set (XMLNode* node);
- void add (XMLNode* node);
-
void set (AxisView*);
void add (AxisView*);
void remove (AxisView*);
+ bool selected (AxisView*);
- void clear_processors ();
void clear_routes ();
- bool selected (AxisView*);
+ void presentation_info_changed (PBD::PropertyChange const & what_changed);
private:
+ ARDOUR::SessionHandlePtr& shp;
+ AxisViewProvider& avp;
void removed (AxisView*);
};
diff --git a/gtk2_ardour/selection.cc b/gtk2_ardour/selection.cc
index 1114222248..23d89d0786 100644
--- a/gtk2_ardour/selection.cc
+++ b/gtk2_ardour/selection.cc
@@ -24,9 +24,10 @@
#include "pbd/stacktrace.h"
#include "pbd/types_convert.h"
+#include "ardour/evoral_types_convert.h"
#include "ardour/playlist.h"
#include "ardour/rc_configuration.h"
-#include "ardour/evoral_types_convert.h"
+#include "ardour/selection.h"
#include "control_protocol/control_protocol.h"
@@ -65,9 +66,6 @@ Selection::Selection (const PublicEditor* e)
/* we have disambiguate which remove() for the compiler */
- void (Selection::*track_remove)(TimeAxisView*) = &Selection::remove;
- TimeAxisView::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (track_remove, this, _1), gui_context());
-
void (Selection::*marker_remove)(ArdourMarker*) = &Selection::remove;
ArdourMarker::CatchDeletion.connect (*this, MISSING_INVALIDATOR, boost::bind (marker_remove, this, _1), gui_context());
@@ -131,20 +129,6 @@ Selection::clear_objects (bool with_signal)
}
void
-Selection::clear_tracks (bool with_signal)
-{
- if (!tracks.empty()) {
- PresentationInfo::ChangeSuspender cs;
-
- for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
- (*x)->set_selected (false);
- }
-
- tracks.clear ();
- }
-}
-
-void
Selection::clear_time (bool with_signal)
{
time.clear();
@@ -272,38 +256,6 @@ Selection::toggle (boost::shared_ptr<Playlist> pl)
}
void
-Selection::toggle (const TrackViewList& track_list)
-{
- PresentationInfo::ChangeSuspender cs;
-
- for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
- if (dynamic_cast<VCATimeAxisView*> (*i)) {
- continue;
- }
- toggle ((*i));
- }
-}
-
-void
-Selection::toggle (TimeAxisView* track)
-{
- if (dynamic_cast<VCATimeAxisView*> (track)) {
- return;
- }
-
- TrackSelection::iterator i;
-
- if ((i = find (tracks.begin(), tracks.end(), track)) == tracks.end()) {
- tracks.push_back (track);
- track->set_selected (true);
- } else {
- tracks.erase (i);
- track->set_selected (false);
- }
-
-}
-
-void
Selection::toggle (const MidiNoteSelection& midi_note_list)
{
clear_time(); //enforce object/range exclusivity
@@ -405,10 +357,10 @@ Selection::toggle (framepos_t start, framepos_t end)
void
Selection::add (boost::shared_ptr<Playlist> pl)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
if (find (playlists.begin(), playlists.end(), pl) == playlists.end()) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
pl->use ();
playlists.push_back(pl);
PlaylistsChanged ();
@@ -418,9 +370,6 @@ Selection::add (boost::shared_ptr<Playlist> pl)
void
Selection::add (const list<boost::shared_ptr<Playlist> >& pllist)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
-
bool changed = false;
for (list<boost::shared_ptr<Playlist> >::const_iterator i = pllist.begin(); i != pllist.end(); ++i) {
@@ -432,51 +381,21 @@ Selection::add (const list<boost::shared_ptr<Playlist> >& pllist)
}
if (changed) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
PlaylistsChanged ();
}
}
void
-Selection::add (TrackViewList const & track_list)
-{
- clear_objects(); //enforce object/range exclusivity
-
- PresentationInfo::ChangeSuspender cs;
-
- TrackViewList added = tracks.add (track_list);
-
- if (!added.empty()) {
- for (TrackViewList::iterator x = added.begin(); x != added.end(); ++x) {
- if (dynamic_cast<VCATimeAxisView*> (*x)) {
- continue;
- }
- (*x)->set_selected (true);
- }
- }
-}
-
-void
-Selection::add (TimeAxisView* track)
-{
- if (dynamic_cast<VCATimeAxisView*> (track)) {
- return;
- }
-
- TrackViewList tr;
- tr.push_back (track);
- add (tr);
-}
-
-void
Selection::add (const MidiNoteSelection& midi_list)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
-
const MidiNoteSelection::const_iterator b = midi_list.begin();
const MidiNoteSelection::const_iterator e = midi_list.end();
if (!midi_list.empty()) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
midi_notes.insert (midi_notes.end(), b, e);
MidiNotesChanged ();
}
@@ -496,9 +415,6 @@ Selection::add (MidiCutBuffer* midi)
void
Selection::add (vector<RegionView*>& v)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
-
/* XXX This method or the add (const RegionSelection&) needs to go
*/
@@ -511,6 +427,8 @@ Selection::add (vector<RegionView*>& v)
}
if (changed) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
RegionsChanged ();
}
}
@@ -518,9 +436,6 @@ Selection::add (vector<RegionView*>& v)
void
Selection::add (const RegionSelection& rs)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
-
/* XXX This method or the add (const vector<RegionView*>&) needs to go
*/
@@ -533,6 +448,8 @@ Selection::add (const RegionSelection& rs)
}
if (changed) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
RegionsChanged ();
}
}
@@ -540,12 +457,11 @@ Selection::add (const RegionSelection& rs)
void
Selection::add (RegionView* r)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
-
if (find (regions.begin(), regions.end(), r) == regions.end()) {
bool changed = regions.add (r);
if (changed) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
RegionsChanged ();
}
}
@@ -624,16 +540,18 @@ Selection::replace (uint32_t sid, framepos_t start, framepos_t end)
void
Selection::add (boost::shared_ptr<Evoral::ControlList> cl)
{
- clear_time(); //enforce object/range exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ boost::shared_ptr<ARDOUR::AutomationList> al = boost::dynamic_pointer_cast<ARDOUR::AutomationList>(cl);
- boost::shared_ptr<ARDOUR::AutomationList> al
- = boost::dynamic_pointer_cast<ARDOUR::AutomationList>(cl);
if (!al) {
warning << "Programming error: Selected list is not an ARDOUR::AutomationList" << endmsg;
return;
}
+ if (!cl->empty()) {
+ clear_time(); //enforce object/range exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
+
/* The original may change so we must store a copy (not a pointer) here.
* e.g AutomationLine rewrites the list with gain mapping.
* the downside is that we can't perfom duplicate checks.
@@ -644,38 +562,6 @@ Selection::add (boost::shared_ptr<Evoral::ControlList> cl)
}
void
-Selection::remove (TimeAxisView* track)
-{
- list<TimeAxisView*>::iterator i;
- if ((i = find (tracks.begin(), tracks.end(), track)) != tracks.end()) {
- /* erase first, because set_selected() will remove the track
- from the selection, invalidating the iterator.
-
- In fact, we don't really even need to do the erase, but this is
- a hangover of axis view selection being in the GUI.
- */
- tracks.erase (i);
- track->set_selected (false);
- }
-}
-
-void
-Selection::remove (const TrackViewList& track_list)
-{
- PresentationInfo::ChangeSuspender cs;
-
- for (TrackViewList::const_iterator i = track_list.begin(); i != track_list.end(); ++i) {
-
- TrackViewList::iterator x = find (tracks.begin(), tracks.end(), *i);
-
- if (x != tracks.end()) {
- tracks.erase (x);
- (*i)->set_selected (false);
- }
- }
-}
-
-void
Selection::remove (ControlPoint* p)
{
PointSelection::iterator i = find (points.begin(), points.end(), p);
@@ -801,67 +687,12 @@ Selection::remove (boost::shared_ptr<ARDOUR::AutomationList> ac)
}
void
-Selection::set (TimeAxisView* track)
-{
- if (dynamic_cast<VCATimeAxisView*> (track)) {
- return;
- }
- clear_objects (); //enforce object/range exclusivity
-
- PresentationInfo::ChangeSuspender cs;
-
- if (!tracks.empty()) {
-
- if (tracks.size() == 1 && tracks.front() == track) {
- /* already single selection: nothing to do */
- return;
- }
-
- for (TrackViewList::iterator x = tracks.begin(); x != tracks.end(); ++x) {
- (*x)->set_selected (false);
- }
-
- tracks.clear ();
- }
-
- add (track);
-}
-
-void
-Selection::set (const TrackViewList& track_list)
-{
- clear_objects(); //enforce object/range exclusivity
-
-
- TrackViewList to_be_added;
- TrackViewList to_be_removed;
-
- for (TrackViewList::const_iterator x = tracks.begin(); x != tracks.end(); ++x) {
- if (find (track_list.begin(), track_list.end(), *x) == track_list.end()) {
- to_be_removed.push_back (*x);
- }
- }
-
- for (TrackViewList::const_iterator x = track_list.begin(); x != track_list.end(); ++x) {
- if (dynamic_cast<VCATimeAxisView*> (*x)) {
- continue;
- }
- if (find (tracks.begin(), tracks.end(), *x) == tracks.end()) {
- to_be_added.push_back (*x);
- }
- }
-
- PresentationInfo::ChangeSuspender cs;
- remove (to_be_removed);
- add (to_be_added);
-
-}
-
-void
Selection::set (const MidiNoteSelection& midi_list)
{
- clear_time (); //enforce region/object exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ if (!midi_list.empty()) {
+ clear_time (); //enforce region/object exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
clear_objects ();
add (midi_list);
}
@@ -869,8 +700,10 @@ Selection::set (const MidiNoteSelection& midi_list)
void
Selection::set (boost::shared_ptr<Playlist> playlist)
{
- clear_time (); //enforce region/object exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ if (playlist) {
+ clear_time (); //enforce region/object exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
clear_objects ();
add (playlist);
}
@@ -878,7 +711,9 @@ Selection::set (boost::shared_ptr<Playlist> playlist)
void
Selection::set (const list<boost::shared_ptr<Playlist> >& pllist)
{
- clear_time(); //enforce region/object exclusivity
+ if (!pllist.empty()) {
+ clear_time(); //enforce region/object exclusivity
+ }
clear_objects ();
add (pllist);
}
@@ -886,8 +721,10 @@ Selection::set (const list<boost::shared_ptr<Playlist> >& pllist)
void
Selection::set (const RegionSelection& rs)
{
- clear_time(); //enforce region/object exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ if (!rs.empty()) {
+ clear_time(); //enforce region/object exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
clear_objects();
regions = rs;
RegionsChanged(); /* EMIT SIGNAL */
@@ -896,8 +733,10 @@ Selection::set (const RegionSelection& rs)
void
Selection::set (MidiRegionView* mrv)
{
- clear_time(); //enforce region/object exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ if (mrv) {
+ clear_time(); //enforce region/object exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
clear_objects ();
add (mrv);
}
@@ -905,8 +744,10 @@ Selection::set (MidiRegionView* mrv)
void
Selection::set (RegionView* r, bool /*also_clear_tracks*/)
{
- clear_time(); //enforce region/object exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ if (r) {
+ clear_time(); //enforce region/object exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
clear_objects ();
add (r);
}
@@ -914,8 +755,11 @@ Selection::set (RegionView* r, bool /*also_clear_tracks*/)
void
Selection::set (vector<RegionView*>& v)
{
- clear_time(); //enforce region/object exclusivity
- clear_tracks(); //enforce object/track exclusivity
+ if (!v.empty()) {
+ clear_time(); //enforce region/object exclusivity
+ clear_tracks(); //enforce object/track exclusivity
+ }
+
clear_objects();
add (v);
@@ -1000,12 +844,6 @@ Selection::selected (ArdourMarker* m) const
}
bool
-Selection::selected (TimeAxisView* tv) const
-{
- return tv->selected ();
-}
-
-bool
Selection::selected (RegionView* rv) const
{
return find (regions.begin(), regions.end(), rv) != regions.end();
@@ -1384,26 +1222,19 @@ Selection::set_state (XMLNode const & node, int)
clear_midi_notes ();
clear_points ();
clear_time ();
- clear_tracks ();
clear_markers ();
RegionSelection selected_regions;
+ /* NOTE: stripable/time-axis-view selection is saved/restored by
+ * ARDOUR::CoreSelection, not this Selection object
+ */
+
PBD::ID id;
XMLNodeList children = node.children ();
- for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
- if ((*i)->name() == X_("RouteView")) {
-
- if (!(*i)->get_property (X_("id"), id)) {
- assert(false); // handle this more gracefully?
- }
- RouteTimeAxisView* rtv = editor->get_route_view_by_route_id (id);
- if (rtv) {
- add (rtv);
- }
-
- } else if ((*i)->name() == X_("Region")) {
+ for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
+ if ((*i)->name() == X_("Region")) {
if (!(*i)->get_property (X_("id"), id)) {
assert(false);
@@ -1594,3 +1425,252 @@ Selection::remove_regions (TimeAxisView* t)
i = tmp;
}
}
+
+/* TIME AXIS VIEW ... proxy for Stripable/Controllable
+ *
+ * public methods just modify the CoreSelection; PresentationInfo::Changed will
+ * trigger Selection::core_selection_changed() and we will update our own data
+ * structures there.
+ */
+
+void
+Selection::toggle (const TrackViewList& track_list)
+{
+ TrackViewList t = add_grouped_tracks (track_list);
+
+ CoreSelection& selection (editor->session()->selection());
+ PresentationInfo::ChangeSuspender cs;
+
+ for (TrackSelection::const_iterator i = t.begin(); i != t.end(); ++i) {
+ boost::shared_ptr<Stripable> s = (*i)->stripable ();
+ boost::shared_ptr<AutomationControl> c = (*i)->control ();
+ selection.toggle (s, c);
+ }
+}
+
+void
+Selection::toggle (TimeAxisView* track)
+{
+ if (dynamic_cast<VCATimeAxisView*> (track)) {
+ return;
+ }
+
+ TrackViewList tr;
+ tr.push_back (track);
+ toggle (tr);
+}
+
+void
+Selection::add (TrackViewList const & track_list)
+{
+ TrackViewList t = add_grouped_tracks (track_list);
+
+ CoreSelection& selection (editor->session()->selection());
+ PresentationInfo::ChangeSuspender cs;
+
+ for (TrackSelection::const_iterator i = t.begin(); i != t.end(); ++i) {
+ boost::shared_ptr<Stripable> s = (*i)->stripable ();
+ boost::shared_ptr<AutomationControl> c = (*i)->control ();
+ selection.add (s, c);
+ }
+}
+
+void
+Selection::add (TimeAxisView* track)
+{
+ if (dynamic_cast<VCATimeAxisView*> (track)) {
+ return;
+ }
+
+ TrackViewList tr;
+ tr.push_back (track);
+ add (tr);
+}
+
+void
+Selection::remove (TimeAxisView* track)
+{
+ if (dynamic_cast<VCATimeAxisView*> (track)) {
+ return;
+ }
+
+ TrackViewList tvl;
+ tvl.push_back (track);
+ remove (tvl);
+}
+
+void
+Selection::remove (const TrackViewList& t)
+{
+ CoreSelection& selection (editor->session()->selection());
+ PresentationInfo::ChangeSuspender cs;
+
+ for (TrackSelection::const_iterator i = t.begin(); i != t.end(); ++i) {
+ boost::shared_ptr<Stripable> s = (*i)->stripable ();
+ boost::shared_ptr<AutomationControl> c = (*i)->control ();
+ selection.remove (s, c);
+ }
+}
+
+void
+Selection::set (TimeAxisView* track)
+{
+ if (dynamic_cast<VCATimeAxisView*> (track)) {
+ return;
+ }
+
+ TrackViewList tvl;
+ tvl.push_back (track);
+ set (tvl);
+}
+
+void
+Selection::set (const TrackViewList& track_list)
+{
+ TrackViewList t = add_grouped_tracks (track_list);
+
+ CoreSelection& selection (editor->session()->selection());
+ PresentationInfo::ChangeSuspender cs;
+
+ selection.clear_stripables ();
+
+ for (TrackSelection::const_iterator i = t.begin(); i != t.end(); ++i) {
+ boost::shared_ptr<Stripable> s = (*i)->stripable ();
+ boost::shared_ptr<AutomationControl> c = (*i)->control ();
+ selection.add (s, c);
+ }
+}
+
+void
+Selection::clear_tracks (bool)
+{
+ Session* s = editor->session();
+ if (s) {
+ CoreSelection& selection (s->selection());
+ selection.clear_stripables ();
+ }
+}
+
+bool
+Selection::selected (TimeAxisView* tv) const
+{
+ Session* session = editor->session();
+
+ if (!session) {
+ return false;
+ }
+
+ CoreSelection& selection (session->selection());
+ boost::shared_ptr<Stripable> s = tv->stripable ();
+ boost::shared_ptr<AutomationControl> c = tv->control ();
+
+ if (c) {
+ return selection.selected (c);
+ }
+
+ return selection.selected (s);
+}
+
+TrackViewList
+Selection::add_grouped_tracks (TrackViewList const & t)
+{
+ TrackViewList added;
+
+ for (TrackSelection::const_iterator i = t.begin(); i != t.end(); ++i) {
+ if (dynamic_cast<VCATimeAxisView*> (*i)) {
+ continue;
+ }
+
+ /* select anything in the same select-enabled route group */
+ ARDOUR::RouteGroup* rg = (*i)->route_group ();
+
+ if (rg && rg->is_active() && rg->is_select ()) {
+
+ TrackViewList tr = editor->axis_views_from_routes (rg->route_list ());
+
+ for (TrackViewList::iterator j = tr.begin(); j != tr.end(); ++j) {
+
+ /* Do not add the trackview passed in as an
+ * argument, because we want that to be on the
+ * end of the list.
+ */
+
+ if (*j != *i) {
+ if (!added.contains (*j)) {
+ added.push_back (*j);
+ }
+ }
+ }
+ }
+ }
+
+ /* now add the the trackview's passed in as actual arguments */
+ added.insert (added.end(), t.begin(), t.end());
+
+ return added;
+}
+
+#if 0
+static void dump_tracks (Selection const & s)
+{
+ cerr << "--TRACKS [" << s.tracks.size() << ']' << ":\n";
+ for (TrackViewList::const_iterator x = s.tracks.begin(); x != s.tracks.end(); ++x) {
+ cerr << (*x)->name() << ' ' << (*x)->stripable() << " C = " << (*x)->control() << endl;
+ }
+ cerr << "///\n";
+}
+#endif
+
+void
+Selection::core_selection_changed (PropertyChange const & what_changed)
+{
+ PropertyChange pc;
+
+ pc.add (Properties::selected);
+
+ if (!what_changed.contains (pc)) {
+ return;
+ }
+
+ CoreSelection& selection (editor->session()->selection());
+
+ if (selection.selected()) {
+ clear_objects(); // enforce object/range exclusivity
+ }
+
+ tracks.clear (); // clear stage for whatever tracks are now selected (maybe none)
+
+ TrackViewList const & tvl (editor->get_track_views ());
+
+ for (TrackViewList::const_iterator x = tvl.begin(); x != tvl.end(); ++x) {
+
+ boost::shared_ptr<Stripable> s = (*x)->stripable ();
+ boost::shared_ptr<AutomationControl> c = (*x)->control ();
+
+ if (!s) {
+ continue;
+ }
+
+ TimeAxisView* tav = editor->time_axis_view_from_stripable (s);
+
+ if (!tav) {
+ continue;
+ }
+
+ if ((c && selection.selected (c)) || selection.selected (s)) {
+ tracks.push_back (tav);
+ }
+
+ TimeAxisView::Children kids = tav->get_child_list ();
+
+ for (TimeAxisView::Children::iterator j = kids.begin(); j != kids.end(); ++j) {
+ s = (*j)->stripable ();
+ c = (*j)->control ();
+
+ if ((c && selection.selected (c)) || selection.selected (s)) {
+ tracks.push_back ((*j).get());
+ }
+ }
+
+ }
+}
diff --git a/gtk2_ardour/selection.h b/gtk2_ardour/selection.h
index 959690b95d..7e8ba19d7b 100644
--- a/gtk2_ardour/selection.h
+++ b/gtk2_ardour/selection.h
@@ -225,9 +225,13 @@ class Selection : public sigc::trackable, public PBD::ScopedConnectionList
std::list<std::pair<PBD::ID const, std::list<Evoral::event_id_t> > > pending_midi_note_selection;
+ void core_selection_changed (PBD::PropertyChange const & pc);
+
private:
PublicEditor const * editor;
uint32_t next_time_id;
+
+ TrackViewList add_grouped_tracks (TrackViewList const & t);
};
bool operator==(const Selection& a, const Selection& b);
diff --git a/gtk2_ardour/time_axis_view.cc b/gtk2_ardour/time_axis_view.cc
index 9997349628..5bd26b193a 100644
--- a/gtk2_ardour/time_axis_view.cc
+++ b/gtk2_ardour/time_axis_view.cc
@@ -769,19 +769,9 @@ TimeAxisView::set_selected (bool yn)
time_axis_vbox.set_name (controls_base_unselected_name);
hide_selection ();
-
- /* children will be set for the yn=true case. but when deselecting
- the editor only has a list of top-level trackviews, so we
- have to do this here.
- */
-
- for (Children::iterator i = children.begin(); i != children.end(); ++i) {
- (*i)->set_selected (false);
- }
}
time_axis_frame.show();
-
}
void
diff --git a/gtk2_ardour/track_selection.cc b/gtk2_ardour/track_selection.cc
index ac3d8b68e5..ad761ef4cd 100644
--- a/gtk2_ardour/track_selection.cc
+++ b/gtk2_ardour/track_selection.cc
@@ -39,47 +39,3 @@ TrackSelection::~TrackSelection ()
{
}
-TrackViewList
-TrackSelection::add (TrackViewList const & t)
-{
- TrackViewList added;
-
- for (TrackSelection::const_iterator i = t.begin(); i != t.end(); ++i) {
- if (dynamic_cast<VCATimeAxisView*> (*i)) {
- continue;
- }
-
- /* select anything in the same select-enabled route group */
- ARDOUR::RouteGroup* rg = (*i)->route_group ();
-
- if (rg && rg->is_active() && rg->is_select ()) {
-
- TrackViewList tr = _editor->axis_views_from_routes (rg->route_list ());
-
- for (TrackViewList::iterator j = tr.begin(); j != tr.end(); ++j) {
-
- /* Do not add the trackview passed in as an
- * argument, because we want that to be on the
- * end of the list.
- */
-
- if (*j != *i) {
- if (!contains (*j)) {
- added.push_back (*j);
- push_back (*j);
- }
- }
- }
- }
-
- /* now add the the trackview's passed in as actual arguments */
-
- if (!contains (*i)) {
- added.push_back (*i);
- push_back (*i);
- }
- }
-
-
- return added;
-}
diff --git a/gtk2_ardour/track_selection.h b/gtk2_ardour/track_selection.h
index 2e9927ab42..8c7aac45c4 100644
--- a/gtk2_ardour/track_selection.h
+++ b/gtk2_ardour/track_selection.h
@@ -35,8 +35,6 @@ public:
virtual ~TrackSelection ();
- TrackViewList add (TrackViewList const &);
-
template <typename Function>
void foreach_time_axis (Function f) {
for (iterator i = begin(); i != end(); ++i) {
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index 646ae17d6b..b925e2657b 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -202,6 +202,7 @@ gtk2_ardour_sources = [
'port_matrix_labels.cc',
'port_matrix_row_labels.cc',
'processor_box.cc',
+ 'processor_selection.cc',
'patch_change_dialog.cc',
'progress_reporter.cc',
'prompter.cc',