Optimize automation-event process splitting
[ardour.git] / gtk2_ardour / editor_selection.cc
index c46ef04a64331d47879d7cf40013158075c5067e..227eaa4a63247da4d083976930b16885bdbd7850 100644 (file)
 #include <cstdlib>
 
 #include "pbd/stacktrace.h"
+#include "pbd/unwind.h"
 
+#include "ardour/control_protocol_manager.h"
 #include "ardour/midi_region.h"
 #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 "ardour/vca.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"
@@ -40,8 +44,9 @@
 #include "editor_regions.h"
 #include "editor_cursors.h"
 #include "midi_region_view.h"
+#include "sfdb_ui.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -86,10 +91,6 @@ Editor::extend_selection_to_track (TimeAxisView& view)
 
        sorted.sort (cmp);
 
-       if (!selection->selected (&view)) {
-               to_be_added.push_back (&view);
-       }
-
        /* figure out if we should go forward or backwards */
 
        for (TrackViewList::iterator i = sorted.begin(); i != sorted.end(); ++i) {
@@ -155,6 +156,10 @@ Editor::extend_selection_to_track (TimeAxisView& view)
                }
        }
 
+       if (!selection->selected (&view)) {
+               to_be_added.push_back (&view);
+       }
+
        if (!to_be_added.empty()) {
                selection->add (to_be_added);
                return true;
@@ -172,6 +177,7 @@ Editor::select_all_tracks ()
                        visible_views.push_back (*i);
                }
        }
+       PBD::Unwinder<bool> uw (_track_selection_change_without_scroll, true);
        selection->set (visible_views);
 }
 
@@ -185,22 +191,17 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
                return;
        }
 
+       PBD::Unwinder<bool> uw (_editor_track_selection_change_without_scroll, true);
+
        RouteGroup* group = NULL;
        if (clicked_routeview) {
                group = clicked_routeview->route()->route_group();
        }
 
-       bool had_tracks = !selection->tracks.empty();
-       RouteGroup& arg (_session->all_route_group());
-
        switch (op) {
        case Selection::Toggle:
                if (selection->selected (clicked_axisview)) {
-                       if (arg.is_select() && arg.is_active()) {
-                               for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-                                       selection->remove(*i);
-                               }
-                       } else if (group && group->is_active()) {
+                       if (group && group->is_active()) {
                                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
                                        if ((*i)->route_group() == group) {
                                                selection->remove(*i);
@@ -210,11 +211,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
                                selection->remove (clicked_axisview);
                        }
                } else {
-                       if (arg.is_select() && arg.is_active()) {
-                               for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-                                       selection->add(*i);
-                               }
-                       } else if (group && group->is_active()) {
+                       if (group && group->is_active()) {
                                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
                                        if ((*i)->route_group() == group) {
                                                selection->add(*i);
@@ -227,14 +224,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
                break;
 
        case Selection::Add:
-               if (!had_tracks && arg.is_select() && arg.is_active()) {
-                       /* nothing was selected already, and all group is active etc. so use
-                          all tracks.
-                       */
-                       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-                               selection->add(*i);
-                       }
-               } else if (group && group->is_active()) {
+               if (group && group->is_active()) {
                        for (TrackViewList::iterator i  = track_views.begin(); i != track_views.end (); ++i) {
                                if ((*i)->route_group() == group) {
                                        selection->add(*i);
@@ -247,14 +237,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
 
        case Selection::Set:
                selection->clear();
-               if (!had_tracks && arg.is_select() && arg.is_active()) {
-                       /* nothing was selected already, and all group is active etc. so use
-                          all tracks.
-                       */
-                       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end (); ++i) {
-                               selection->add(*i);
-                       }
-               } else if (group && group->is_active()) {
+               if (group && group->is_active()) {
                        for (TrackViewList::iterator i  = track_views.begin(); i != track_views.end (); ++i) {
                                if ((*i)->route_group() == group) {
                                        selection->add(*i);
@@ -274,7 +257,7 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op)
 void
 Editor::set_selected_track (TimeAxisView& view, Selection::Operation op, bool no_remove)
 {
-       begin_reversible_selection_op(_("Set Selected Track"));
+       begin_reversible_selection_op (X_("Set Selected Track"));
 
        switch (op) {
        case Selection::Toggle:
@@ -288,9 +271,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:
@@ -326,18 +307,34 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation
                return false;
        }
 
+       bool ret = false;
+
        switch (op) {
        case Selection::Set:
-               if (press) {
+               if (!selection->selected (clicked_control_point)) {
                        selection->set (clicked_control_point);
+                       ret = true;
+               } else {
+                       /* clicked on an already selected point */
+                       if (press) {
+                               break;
+                       } else {
+                               if (selection->points.size() > 1) {
+                                       selection->set (clicked_control_point);
+                                       ret = true;
+                               }
+                       }
                }
                break;
+
        case Selection::Add:
                if (press) {
                        selection->add (clicked_control_point);
+                       ret = true;
                }
                break;
        case Selection::Toggle:
+
                /* This is a bit of a hack; if we Primary-Click-Drag a control
                   point (for push drag) we want the point we clicked on to be
                   selected, otherwise we end up confusingly dragging an
@@ -352,9 +349,11 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation
                        */
                        selection->toggle (clicked_control_point);
                        _control_point_toggled_on_press = true;
+                       ret = true;
                } else if (!press && !_control_point_toggled_on_press) {
                        /* This is the release, and the point wasn't toggled on the press, so do it now */
                        selection->toggle (clicked_control_point);
+                       ret = true;
                } else {
                        /* Reset our flag */
                        _control_point_toggled_on_press = false;
@@ -365,7 +364,7 @@ Editor::set_selected_control_point_from_click (bool press, Selection::Operation
                break;
        }
 
-       return true;
+       return ret;
 }
 
 void
@@ -400,7 +399,7 @@ Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeA
 
        RouteGroup* group = route_basis->route()->route_group();
 
-       if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id) ) {
+       if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id)) {
 
                /* the basis is a member of an active route group, with the appropriate
                   properties; find other members */
@@ -444,7 +443,7 @@ Editor::mapover_tracks_with_unique_playlists (sigc::slot<void, RouteTimeAxisView
 
        RouteGroup* group = route_basis->route()->route_group(); // could be null, not a problem
 
-       if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id) ) {
+       if (group && group->enabled_property(prop) && group->enabled_property (Properties::active.property_id)) {
 
                /* the basis is a member of an active route group, with the appropriate
                   properties; find other members */
@@ -453,7 +452,7 @@ Editor::mapover_tracks_with_unique_playlists (sigc::slot<void, RouteTimeAxisView
                        RouteTimeAxisView* v = dynamic_cast<RouteTimeAxisView*> (*i);
 
                        if (v && v->route()->route_group() == group) {
-                               
+
                                boost::shared_ptr<Track> t = v->track();
                                if (t) {
                                        if (playlists.insert (t->playlist()).second) {
@@ -626,7 +625,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                                if (press) {
 
                                        if (selection->selected (clicked_routeview)) {
-                                               get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
+                                               get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::group_select.property_id);
                                        } else {
                                                all_equivalent_regions.push_back (clicked_regionview);
                                        }
@@ -644,7 +643,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
 
                case Selection::Set:
                        if (!selection->selected (clicked_regionview)) {
-                               get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
+                               get_equivalent_regions (clicked_regionview, all_equivalent_regions, ARDOUR::Properties::group_select.property_id);
                                selection->set (all_equivalent_regions);
                                commit = true;
                        } else {
@@ -652,9 +651,12 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                                if (press)
                                        goto out;
                                else {
-                                       get_equivalent_regions(clicked_regionview, all_equivalent_regions, ARDOUR::Properties::select.property_id);
-                                       selection->set(all_equivalent_regions);
-                                       commit = true;
+                                       if (selection->regions.size() > 1) {
+                                               /* collapse region selection down to just this one region (and its equivalents) */
+                                               get_equivalent_regions(clicked_regionview, all_equivalent_regions, ARDOUR::Properties::group_select.property_id);
+                                               selection->set(all_equivalent_regions);
+                                               commit = true;
+                                       }
                                }
                        }
                        break;
@@ -667,24 +669,24 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
        } else if (op == Selection::Extend) {
 
                list<Selectable*> results;
-               framepos_t last_frame;
-               framepos_t first_frame;
+               samplepos_t last_sample;
+               samplepos_t first_sample;
                bool same_track = false;
 
                /* 1. find the last selected regionview in the track that was clicked in */
 
-               last_frame = 0;
-               first_frame = max_framepos;
+               last_sample = 0;
+               first_sample = max_samplepos;
 
                for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
                        if (&(*x)->get_time_axis_view() == &clicked_regionview->get_time_axis_view()) {
 
-                               if ((*x)->region()->last_frame() > last_frame) {
-                                       last_frame = (*x)->region()->last_frame();
+                               if ((*x)->region()->last_sample() > last_sample) {
+                                       last_sample = (*x)->region()->last_sample();
                                }
 
-                               if ((*x)->region()->first_frame() < first_frame) {
-                                       first_frame = (*x)->region()->first_frame();
+                               if ((*x)->region()->first_sample() < first_sample) {
+                                       first_sample = (*x)->region()->first_sample();
                                }
 
                                same_track = true;
@@ -695,34 +697,34 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
 
                        /* 2. figure out the boundaries for our search for new objects */
 
-                       switch (clicked_regionview->region()->coverage (first_frame, last_frame)) {
+                       switch (clicked_regionview->region()->coverage (first_sample, last_sample)) {
                        case Evoral::OverlapNone:
-                               if (last_frame < clicked_regionview->region()->first_frame()) {
-                                       first_frame = last_frame;
-                                       last_frame = clicked_regionview->region()->last_frame();
+                               if (last_sample < clicked_regionview->region()->first_sample()) {
+                                       first_sample = last_sample;
+                                       last_sample = clicked_regionview->region()->last_sample();
                                } else {
-                                       last_frame = first_frame;
-                                       first_frame = clicked_regionview->region()->first_frame();
+                                       last_sample = first_sample;
+                                       first_sample = clicked_regionview->region()->first_sample();
                                }
                                break;
 
                        case Evoral::OverlapExternal:
-                               if (last_frame < clicked_regionview->region()->first_frame()) {
-                                       first_frame = last_frame;
-                                       last_frame = clicked_regionview->region()->last_frame();
+                               if (last_sample < clicked_regionview->region()->first_sample()) {
+                                       first_sample = last_sample;
+                                       last_sample = clicked_regionview->region()->last_sample();
                                } else {
-                                       last_frame = first_frame;
-                                       first_frame = clicked_regionview->region()->first_frame();
+                                       last_sample = first_sample;
+                                       first_sample = clicked_regionview->region()->first_sample();
                                }
                                break;
 
                        case Evoral::OverlapInternal:
-                               if (last_frame < clicked_regionview->region()->first_frame()) {
-                                       first_frame = last_frame;
-                                       last_frame = clicked_regionview->region()->last_frame();
+                               if (last_sample < clicked_regionview->region()->first_sample()) {
+                                       first_sample = last_sample;
+                                       last_sample = clicked_regionview->region()->last_sample();
                                } else {
-                                       last_frame = first_frame;
-                                       first_frame = clicked_regionview->region()->first_frame();
+                                       last_sample = first_sample;
+                                       first_sample = clicked_regionview->region()->first_sample();
                                }
                                break;
 
@@ -742,15 +744,15 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                        */
 
 
-                       first_frame = clicked_regionview->region()->position();
-                       last_frame = clicked_regionview->region()->last_frame();
+                       first_sample = clicked_regionview->region()->position();
+                       last_sample = clicked_regionview->region()->last_sample();
 
                        for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
-                               if ((*i)->region()->position() < first_frame) {
-                                       first_frame = (*i)->region()->position();
+                               if ((*i)->region()->position() < first_sample) {
+                                       first_sample = (*i)->region()->position();
                                }
-                               if ((*i)->region()->last_frame() + 1 > last_frame) {
-                                       last_frame = (*i)->region()->last_frame();
+                               if ((*i)->region()->last_sample() + 1 > last_sample) {
+                                       last_sample = (*i)->region()->last_sample();
                                }
                        }
                }
@@ -793,7 +795,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
 
                                        RouteTimeAxisView* closest = 0;
                                        int distance = INT_MAX;
-                                       int key = rtv->route()->order_key ();
+                                       int key = rtv->route()->presentation_info().order ();
 
                                        for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
 
@@ -808,7 +810,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                                                        if (result.second) {
                                                                /* newly added to already_in_selection */
 
-                                                               int d = artv->route()->order_key ();
+                                                               int d = artv->route()->presentation_info().order ();
 
                                                                d -= key;
 
@@ -824,7 +826,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
 
                                                /* now add all tracks between that one and this one */
 
-                                               int okey = closest->route()->order_key ();
+                                               int okey = closest->route()->presentation_info().order ();
 
                                                if (okey > key) {
                                                        swap (okey, key);
@@ -834,7 +836,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                                                        RouteTimeAxisView* artv = dynamic_cast<RouteTimeAxisView*>(*x);
                                                        if (artv && artv != rtv) {
 
-                                                               int k = artv->route()->order_key ();
+                                                               int k = artv->route()->presentation_info().order ();
 
                                                                if (k >= okey && k <= key) {
 
@@ -863,7 +865,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                */
 
                for (set<RouteTimeAxisView*>::iterator t = relevant_tracks.begin(); t != relevant_tracks.end(); ++t) {
-                       (*t)->get_selectables (first_frame, last_frame, -1.0, -1.0, results);
+                       (*t)->get_selectables (first_sample, last_sample, -1.0, -1.0, results);
                }
 
                /* 4. convert to a vector of regions */
@@ -881,13 +883,42 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
                if (!regions.empty()) {
                        selection->add (regions);
                        commit = true;
+               } else if (selection->regions.empty() && !selection->selected (clicked_regionview)) {
+                       /* ensure that at least the clicked regionview is selected. */
+                       selection->set (clicked_regionview);
+                       commit = true;
                }
+
        }
 
 out:
        return commit;
 }
 
+void
+Editor::set_selection (std::list<Selectable*> s, Selection::Operation op)
+{
+       if (s.empty()) {
+               return;
+       }
+       begin_reversible_selection_op (X_("set selection"));
+       switch (op) {
+               case Selection::Toggle:
+                       selection->toggle (s);
+                       break;
+               case Selection::Set:
+                       selection->set (s);
+                       break;
+               case Selection::Extend:
+                       selection->add (s);
+                       break;
+               case Selection::Add:
+                       selection->add (s);
+                       break;
+       }
+
+       commit_reversible_selection_op () ;
+}
 
 void
 Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> region, Selection::Operation op)
@@ -900,7 +931,7 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> regi
                return;
        }
 
-       begin_reversible_selection_op (_("set selected regions"));
+       begin_reversible_selection_op (X_("set selected regions"));
 
        switch (op) {
        case Selection::Toggle:
@@ -943,7 +974,7 @@ Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView*
                return true;
        }
 
-       begin_reversible_selection_op (_("set selected regions"));
+       begin_reversible_selection_op (X_("set selected regions"));
 
        selection->set (rv);
 
@@ -953,58 +984,174 @@ Editor::set_selected_regionview_from_map_event (GdkEventAny* /*ev*/, StreamView*
 }
 
 void
-Editor::track_selection_changed ()
+Editor::presentation_info_changed (PropertyChange const & what_changed)
 {
-       switch (selection->tracks.size()) {
-       case 0:
-               break;
-       default:
-               set_selected_mixer_strip (*(selection->tracks.front()));
-               break;
+       uint32_t n_tracks = 0;
+       uint32_t n_busses = 0;
+       uint32_t n_vcas = 0;
+       uint32_t n_routes = 0;
+       uint32_t n_stripables = 0;
+
+       /* We cannot ensure ordering of the handlers for
+        * PresentationInfo::Changed, so we have to do everything in order
+        * here, as a single handler.
+        */
+
+       if (what_changed.contains (Properties::selected)) {
+               for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
+                       (*i)->set_selected (false);
+                       (*i)->hide_selection ();
+               }
        }
 
-       RouteNotificationListPtr routes (new RouteNotificationList);
+       /* 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);
+       if (what_changed.contains (Properties::selected)) {
 
-               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());
+               StripableNotificationListPtr stripables (new StripableNotificationList);
+
+               switch (selection->tracks.size()) {
+               case 0:
+                       break;
+               default:
+                       set_selected_mixer_strip (*(selection->tracks.back()));
+                       if (!_track_selection_change_without_scroll && !_editor_track_selection_change_without_scroll) {
+                               ensure_time_axis_view_is_visible (*(selection->tracks.back()), false);
+                       }
+                       break;
                }
 
-               if (yn) {
-                       (*i)->reshow_selection (selection->time);
-               } else {
-                       (*i)->hide_selection ();
+               CoreSelection::StripableAutomationControls sc;
+               _session->selection().get_stripables (sc);
+
+               for (CoreSelection::StripableAutomationControls::const_iterator i = sc.begin(); i != sc.end(); ++i) {
+
+                       AxisView* av = axis_view_by_stripable ((*i).stripable);
+
+                       if (!av) {
+                               continue;
+                       }
+
+                       n_stripables++;
+
+                       if (boost::dynamic_pointer_cast<Track> ((*i).stripable)) {
+                               n_tracks++;
+                               n_routes++;
+                       } else if (boost::dynamic_pointer_cast<Route> ((*i).stripable)) {
+                               n_busses++;
+                               n_routes++;
+                       } else if (boost::dynamic_pointer_cast<VCA> ((*i).stripable)) {
+                               n_vcas++;
+                       }
+
+                       TimeAxisView* tav = dynamic_cast<TimeAxisView*> (av);
+
+                       if (!tav) {
+                               assert (0);
+                               continue; /* impossible */
+                       }
+
+                       if (!(*i).controllable) {
+
+                               /* "parent" track selected */
+                               tav->set_selected (true);
+                               tav->reshow_selection (selection->time);
+
+                       } else {
+
+                               /* 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::stripable_selection_sensitive_actions, (n_stripables > 0));
+               ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, (n_tracks > 0));
+               ActionManager::set_sensitive (ActionManager::bus_selection_sensitive_actions, (n_busses > 0));
+               ActionManager::set_sensitive (ActionManager::route_selection_sensitive_actions, (n_routes > 0));
+               ActionManager::set_sensitive (ActionManager::vca_selection_sensitive_actions, (n_vcas > 0));
+
+               sensitize_the_right_region_actions (false);
+
+               /* STEP 4: notify control protocols */
+
+               ControlProtocolManager::instance().stripable_selection_changed (stripables);
+
+               if (sfbrowser && _session && !_session->deletion_in_progress()) {
+                       uint32_t audio_track_cnt = 0;
+                       uint32_t midi_track_cnt = 0;
 
-               if (yn) {
-                       RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*i);
-                       if (rtav) {
-                               routes->push_back (rtav->route());
+                       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);
                }
        }
 
-       ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
+       /* STEP 4: update EditorRoutes treeview */
+
+       PropertyChange soh;
 
-       /* notify control protocols */
-       
-       ControlProtocol::TrackSelectionChanged (routes);
+       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);
+       }
 }
 
 void
-Editor::time_selection_changed ()
+Editor::track_selection_changed ()
 {
-       if (Profile->get_sae()) {
-               return;
-       }
+       /* reset paste count, so the plaste location doesn't get incremented
+        * if we want to paste in the same place, but different track. */
+       paste_count = 0;
 
+       if ( _session->solo_selection_active() )
+               play_solo_selection(false);
+}
+
+void
+Editor::time_selection_changed ()
+{
        /* XXX this is superficially inefficient. Hide the selection in all
         * tracks, then show it in all selected tracks.
         *
@@ -1027,6 +1174,19 @@ Editor::time_selection_changed ()
        } else {
                ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
        }
+
+       /* propagate into backend, but only when there is no drag or we are at
+        * the end of a drag, otherwise this is too expensive (could case a
+        * locate per mouse motion event.
+        */
+
+       if (_session && !_drags->active()) {
+               if (selection->time.length() != 0) {
+                       _session->set_range_selection (selection->time.start(), selection->time.end_sample());
+               } else {
+                       _session->clear_range_selection ();
+               }
+       }
 }
 
 /** Set all region actions to have a given sensitivity */
@@ -1042,23 +1202,87 @@ Editor::sensitize_all_region_actions (bool s)
        _all_region_actions_sensitized = s;
 }
 
-/** Sensitize region-based actions based on the selection ONLY, ignoring the entered_regionview.
- *  This method should be called just before displaying a Region menu.  When a Region menu is not
- *  currently being shown, all region actions are sensitized so that hotkey-triggered actions
- *  on entered_regionviews work without having to check sensitivity every time the selection or
- *  entered_regionview changes.
+/** Sensitize region-based actions.
  *
- *  This method also sets up toggle action state as appropriate.
+ *  This method is called from whenever we leave the canvas, either by moving
+ *  the pointer out of it, or by popping up a context menu. See
+ *  Editor::{entered,left}_track_canvas() for details there.
  */
 void
-Editor::sensitize_the_right_region_actions ()
+Editor::sensitize_the_right_region_actions (bool because_canvas_crossing)
 {
+       bool have_selection = false;
+       bool have_entered = false;
+       bool have_edit_point = false;
+       RegionSelection rs;
+
+       // std::cerr << "STRRA: crossing ? " << because_canvas_crossing << " within ? " << within_track_canvas
+       // << std::endl;
+
+       if (!selection->regions.empty()) {
+               have_selection = true;
+               rs = selection->regions;
+       }
+
+       if (entered_regionview) {
+               have_entered = true;
+               rs.add (entered_regionview);
+       }
+
+       if (rs.empty() && !selection->tracks.empty()) {
 
-       RegionSelection rs = get_regions_from_selection_and_entered ();
-       sensitize_all_region_actions (!rs.empty ());
+               /* no selected regions, but some selected tracks.
+                */
+
+               if (_edit_point == EditAtMouse) {
+                       if (!within_track_canvas) {
+                               /* pointer is not in canvas, so edit point is meaningless */
+                               have_edit_point = false;
+                       } else {
+                               /* inside canvas. we don't know where the edit
+                                  point will be when an action is invoked, but
+                                  assume it could intersect with a region.
+                               */
+                               have_edit_point = true;
+                       }
+               } else {
+                       RegionSelection at_edit_point;
+                       samplepos_t const where = get_preferred_edit_position (Editing::EDIT_IGNORE_NONE, false, !within_track_canvas);
+                       get_regions_at (at_edit_point, where, selection->tracks);
+                       if (!at_edit_point.empty()) {
+                               have_edit_point = true;
+                       }
+                       if (rs.empty()) {
+                               rs.insert (rs.end(), at_edit_point.begin(), at_edit_point.end());
+                       }
+               }
+       }
+
+       //std::cerr << "\tfinal have selection: " << have_selection
+       // << " have entered " << have_entered
+       // << " have edit point " << have_edit_point
+       // << " EP = " << enum_2_string (_edit_point)
+       // << std::endl;
+
+       typedef std::map<std::string,RegionAction> RegionActionMap;
 
        _ignore_region_action = true;
 
+       for (RegionActionMap::iterator x = region_action_map.begin(); x != region_action_map.end(); ++x) {
+               RegionActionTarget tgt = x->second.target;
+               bool sensitive = false;
+
+               if ((tgt & SelectedRegions) && have_selection) {
+                       sensitive = true;
+               } else if ((tgt & EnteredRegions) && have_entered) {
+                       sensitive = true;
+               } else if ((tgt & EditPointRegions) && have_edit_point) {
+                       sensitive = true;
+               }
+
+               x->second.action->set_sensitive (sensitive);
+       }
+
        /* Look through the regions that are selected and make notes about what we have got */
 
        bool have_audio = false;
@@ -1083,6 +1307,7 @@ Editor::sensitize_the_right_region_actions ()
        bool have_inactive_fade_out = false;
        bool have_active_fade_in = false;
        bool have_active_fade_out = false;
+       bool have_transients = false;
 
        for (list<RegionView*>::const_iterator i = rs.begin(); i != rs.end(); ++i) {
 
@@ -1138,6 +1363,10 @@ Editor::sensitize_the_right_region_actions ()
                        have_not_at_natural_position = true;
                }
 
+               if (r->has_transients ()){
+                       have_transients = true;
+               }
+
                if (ar) {
                        if (ar->envelope_active()) {
                                have_envelope_active = true;
@@ -1163,6 +1392,8 @@ Editor::sensitize_the_right_region_actions ()
                }
        }
 
+       _region_actions->get_action("split-region-at-transients")->set_sensitive (have_transients);
+
        if (rs.size() > 1) {
                _region_actions->get_action("show-region-list-editor")->set_sensitive (false);
                _region_actions->get_action("show-region-properties")->set_sensitive (false);
@@ -1191,6 +1422,7 @@ Editor::sensitize_the_right_region_actions ()
                _region_actions->get_action("quantize-region")->set_sensitive (false);
                _region_actions->get_action("legatize-region")->set_sensitive (false);
                _region_actions->get_action("remove-overlap")->set_sensitive (false);
+               _region_actions->get_action("transform-region")->set_sensitive (false);
                _region_actions->get_action("fork-region")->set_sensitive (false);
                _region_actions->get_action("insert-patch-change-context")->set_sensitive (false);
                _region_actions->get_action("insert-patch-change")->set_sensitive (false);
@@ -1200,13 +1432,7 @@ Editor::sensitize_the_right_region_actions ()
                /* others were already marked sensitive */
        }
 
-       if (_edit_point == EditAtMouse) {
-               _region_actions->get_action("set-region-sync-position")->set_sensitive (false);
-               _region_actions->get_action("trim-front")->set_sensitive (false);
-               _region_actions->get_action("trim-back")->set_sensitive (false);
-               _region_actions->get_action("split-region")->set_sensitive (false);
-               _region_actions->get_action("place-transient")->set_sensitive (false);
-       }
+       /* ok, moving along... */
 
        if (have_compound_regions) {
                _region_actions->get_action("uncombine-regions")->set_sensitive (true);
@@ -1224,10 +1450,13 @@ Editor::sensitize_the_right_region_actions ()
 
        } else {
 
-               _region_actions->get_action("analyze-region")->set_sensitive (false);
+               _region_actions->get_action("loudness-analyze-region")->set_sensitive (false);
+               _region_actions->get_action("spectral-analyze-region")->set_sensitive (false);
                _region_actions->get_action("reset-region-gain-envelopes")->set_sensitive (false);
                _region_actions->get_action("toggle-region-gain-envelope-active")->set_sensitive (false);
                _region_actions->get_action("pitch-shift-region")->set_sensitive (false);
+               _region_actions->get_action("strip-region-silence")->set_sensitive (false);
+               _region_actions->get_action("show-rhythm-ferret")->set_sensitive (false);
 
        }
 
@@ -1250,8 +1479,12 @@ Editor::sensitize_the_right_region_actions ()
        a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-lock-style"));
        a->set_active (have_position_lock_style_music && !have_position_lock_style_audio);
 
-       if (have_position_lock_style_music && have_position_lock_style_audio) {
-               // a->set_inconsistent ();
+       vector<Widget*> proxies = a->get_proxies();
+       for (vector<Widget*>::iterator p = proxies.begin(); p != proxies.end(); ++p) {
+               Gtk::CheckMenuItem* cmi = dynamic_cast<Gtk::CheckMenuItem*> (*p);
+               if (cmi) {
+                       cmi->set_inconsistent (have_position_lock_style_music && have_position_lock_style_audio);
+               }
        }
 
        a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-mute"));
@@ -1289,7 +1522,7 @@ Editor::sensitize_the_right_region_actions ()
        if (have_active_fade_out && have_inactive_fade_out) {
                // a->set_inconsistent ();
        }
-       
+
        bool const have_active_fade = have_active_fade_in || have_active_fade_out;
        bool const have_inactive_fade = have_inactive_fade_in || have_inactive_fade_out;
 
@@ -1299,13 +1532,12 @@ Editor::sensitize_the_right_region_actions ()
        if (have_active_fade && have_inactive_fade) {
                // a->set_inconsistent ();
        }
-       
+
        _ignore_region_action = false;
 
        _all_region_actions_sensitized = false;
 }
 
-
 void
 Editor::region_selection_changed ()
 {
@@ -1327,15 +1559,31 @@ Editor::region_selection_changed ()
        _regions->block_change_connection (false);
        editor_regions_selection_changed_connection.block(false);
 
-       if (!_all_region_actions_sensitized) {
-               /* This selection change might have changed what region actions
-                  are allowed, so sensitize them all in case a key is pressed.
-               */
-               sensitize_all_region_actions (true);
+       sensitize_the_right_region_actions (false);
+
+       /* propagate into backend */
+
+       if (_session) {
+               if (!selection->regions.empty()) {
+                       _session->set_object_selection (selection->regions.start(), selection->regions.end_sample());
+               } else {
+                       _session->clear_object_selection ();
+               }
        }
 
-       if (_session && !_session->transport_rolling() && !selection->regions.empty()) {
-               maybe_locate_with_edit_preroll (selection->regions.start());
+       if (_session->solo_selection_active()) {
+               play_solo_selection(false);
+       }
+
+       /* set nudge button color */
+       if (! get_regions_from_selection_and_entered().empty()) {
+               /* nudge regions */
+               nudge_forward_button.set_name ("nudge button");
+               nudge_backward_button.set_name ("nudge button");
+       } else {
+               /* nudge marker or playhead */
+               nudge_forward_button.set_name ("generic button");
+               nudge_backward_button.set_name ("generic button");
        }
 }
 
@@ -1356,9 +1604,9 @@ Editor::select_all_in_track (Selection::Operation op)
                return;
        }
 
-       begin_reversible_selection_op(_("Select All in Track"));
+       begin_reversible_selection_op (X_("Select All in Track"));
 
-       clicked_routeview->get_selectables (0, max_framepos, 0, DBL_MAX, touched);
+       clicked_routeview->get_selectables (0, max_samplepos, 0, DBL_MAX, touched);
 
        switch (op) {
        case Selection::Toggle:
@@ -1405,28 +1653,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);
+               (*iter)->get_selectables (0, max_samplepos, 0, DBL_MAX, touched);
        }
 
-
-       begin_reversible_selection_op (_("select all"));
+       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);
@@ -1447,7 +1699,7 @@ Editor::invert_selection_in_track ()
                return;
        }
 
-       begin_reversible_selection_op(_("Invert Selection in Track"));
+       begin_reversible_selection_op (X_("Invert Selection in Track"));
        clicked_routeview->get_inverted_selectables (*selection, touched);
        selection->set (touched);
        commit_reversible_selection_op ();
@@ -1456,7 +1708,6 @@ Editor::invert_selection_in_track ()
 void
 Editor::invert_selection ()
 {
-       list<Selectable *> touched;
 
        if (internal_editing()) {
                for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
@@ -1468,27 +1719,46 @@ Editor::invert_selection ()
                return;
        }
 
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
-               if ((*iter)->hidden()) {
-                       continue;
+       if (!selection->tracks.empty()) {
+
+               TrackViewList inverted;
+
+               for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+                       if (!(*iter)->selected()) {
+                               inverted.push_back (*iter);
+                       }
                }
-               (*iter)->get_inverted_selectables (*selection, touched);
-       }
 
-       begin_reversible_selection_op(_("Invert Selection"));
-       selection->set (touched);
-       commit_reversible_selection_op ();
+               begin_reversible_selection_op (X_("Invert Track Selection"));
+               selection->set (inverted);
+               commit_reversible_selection_op ();
+
+       } else {
+
+               list<Selectable *> touched;
+
+               for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+                       if ((*iter)->hidden()) {
+                               continue;
+                       }
+                       (*iter)->get_inverted_selectables (*selection, touched);
+               }
+
+               begin_reversible_selection_op (X_("Invert ObjectSelection"));
+               selection->set (touched);
+               commit_reversible_selection_op ();
+       }
 }
 
-/** @param start Start time in session frames.
- *  @param end End time in session frames.
+/** @param start Start time in session samples.
+ *  @param end End time in session samples.
  *  @param top Top (lower) y limit in trackview coordinates (ie 0 at the top of the track view)
  *  @param bottom Bottom (higher) y limit in trackview coordinates (ie 0 at the top of the track view)
  *  @param preserve_if_selected true to leave the current selection alone if we're adding to the selection and all of the selectables
  *  within the region are already selected.
  */
 void
-Editor::select_all_within (framepos_t start, framepos_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op, bool preserve_if_selected)
+Editor::select_all_within (samplepos_t start, samplepos_t end, double top, double bot, const TrackViewList& tracklist, Selection::Operation op, bool preserve_if_selected)
 {
        list<Selectable*> found;
 
@@ -1509,7 +1779,7 @@ Editor::select_all_within (framepos_t start, framepos_t end, double top, double
 
        if (preserve_if_selected && op != Selection::Toggle) {
                list<Selectable*>::iterator i = found.begin();
-               while (i != found.end() && (*i)->get_selected()) {
+               while (i != found.end() && (*i)->selected()) {
                        ++i;
                }
 
@@ -1518,7 +1788,7 @@ Editor::select_all_within (framepos_t start, framepos_t end, double top, double
                }
        }
 
-       begin_reversible_selection_op (_("select all within"));
+       begin_reversible_selection_op (X_("select all within"));
        switch (op) {
        case Selection::Add:
                selection->add (found);
@@ -1544,14 +1814,26 @@ Editor::set_selection_from_region ()
                return;
        }
 
-       selection->set (selection->regions.start(), selection->regions.end_frame());
-       
-       //we must now select tracks, because otherwise set_selection_from_region would appear to do nothing
-       //perhaps too drastic; perhaps the user really only wants the region's track selected
-       //but I can't think of any use-case for that (why wouldn't you just select the region?)
-       select_all_tracks();    
-       
-       if (!Profile->get_sae()) {
+       /* find all the tracks that have selected regions */
+
+       set<TimeAxisView*> tracks;
+
+       for (RegionSelection::const_iterator r = selection->regions.begin(); r != selection->regions.end(); ++r) {
+               tracks.insert (&(*r)->get_time_axis_view());
+       }
+
+       TrackViewList tvl;
+       tvl.insert (tvl.end(), tracks.begin(), tracks.end());
+
+       /* select range (this will clear the region selection) */
+
+       selection->set (selection->regions.start(), selection->regions.end_sample());
+
+       /* and select the tracks */
+
+       selection->set (tvl);
+
+       if (!get_smart_mode () || !(mouse_mode == Editing::MouseObject) ) {
                set_mouse_mode (Editing::MouseRange, false);
        }
 }
@@ -1582,12 +1864,20 @@ Editor::set_selection_from_loop()
 void
 Editor::set_selection_from_range (Location& loc)
 {
-       begin_reversible_selection_op (_("set selection from range"));
+       begin_reversible_selection_op (X_("set selection from range"));
+
        selection->set (loc.start(), loc.end());
+
+       // if no tracks are selected, enable all tracks
+       // (_something_ has to be selected for any range selection, otherwise the user won't see anything)
+       if (selection->tracks.empty()) {
+               select_all_tracks();
+       }
+
        commit_reversible_selection_op ();
 
-       if (!Profile->get_sae()) {
-               set_mouse_mode (Editing::MouseRange, false);
+       if (!get_smart_mode () || mouse_mode != Editing::MouseObject) {
+               set_mouse_mode (MouseRange, false);
        }
 }
 
@@ -1600,8 +1890,8 @@ Editor::select_all_selectables_using_time_selection ()
                return;
        }
 
-       framepos_t start = selection->time[clicked_selection].start;
-       framepos_t end = selection->time[clicked_selection].end;
+       samplepos_t start = selection->time[clicked_selection].start;
+       samplepos_t end = selection->time[clicked_selection].end;
 
        if (end - start < 1)  {
                return;
@@ -1622,7 +1912,7 @@ Editor::select_all_selectables_using_time_selection ()
                (*iter)->get_selectables (start, end - 1, 0, DBL_MAX, touched);
        }
 
-       begin_reversible_selection_op (_("select all from range"));
+       begin_reversible_selection_op (X_("select all from range"));
        selection->set (touched);
        commit_reversible_selection_op ();
 }
@@ -1653,7 +1943,7 @@ Editor::select_all_selectables_using_punch()
                }
                (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
        }
-       begin_reversible_selection_op (_("select all from punch"));
+       begin_reversible_selection_op (X_("select all from punch"));
        selection->set (touched);
        commit_reversible_selection_op ();
 
@@ -1684,7 +1974,7 @@ Editor::select_all_selectables_using_loop()
                }
                (*iter)->get_selectables (location->start(), location->end() - 1, 0, DBL_MAX, touched);
        }
-       begin_reversible_selection_op (_("select all from loop"));
+       begin_reversible_selection_op (X_("select all from loop"));
        selection->set (touched);
        commit_reversible_selection_op ();
 
@@ -1693,17 +1983,17 @@ Editor::select_all_selectables_using_loop()
 void
 Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
 {
-       framepos_t start;
-       framepos_t end;
+       samplepos_t start;
+       samplepos_t end;
        list<Selectable *> touched;
 
        if (after) {
-               start = cursor->current_frame();
-               end = _session->current_end_frame();
+               start = cursor->current_sample();
+               end = _session->current_end_sample();
        } else {
-               if (cursor->current_frame() > 0) {
+               if (cursor->current_sample() > 0) {
                        start = 0;
-                       end = cursor->current_frame() - 1;
+                       end = cursor->current_sample() - 1;
                } else {
                        return;
                }
@@ -1720,9 +2010,9 @@ Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
        }
 
        if (after) {
-               begin_reversible_selection_op (_("select all after cursor"));
+               begin_reversible_selection_op (X_("select all after cursor"));
        } else {
-               begin_reversible_selection_op (_("select all before cursor"));
+               begin_reversible_selection_op (X_("select all before cursor"));
        }
 
        TrackViewList* ts;
@@ -1744,17 +2034,17 @@ Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
 }
 
 void
-Editor::select_all_selectables_using_edit (bool after)
+Editor::select_all_selectables_using_edit (bool after, bool from_context_menu)
 {
-       framepos_t start;
-       framepos_t end;
+       samplepos_t start;
+       samplepos_t end;
        list<Selectable *> touched;
 
        if (after) {
-               start = get_preferred_edit_position(false, true);
-               end = _session->current_end_frame();
+               start = get_preferred_edit_position(EDIT_IGNORE_NONE, from_context_menu);
+               end = _session->current_end_sample();
        } else {
-               if ((end = get_preferred_edit_position(false, true)) > 1) {
+               if ((end = get_preferred_edit_position(EDIT_IGNORE_NONE, from_context_menu)) > 1) {
                        start = 0;
                        end -= 1;
                } else {
@@ -1771,9 +2061,9 @@ Editor::select_all_selectables_using_edit (bool after)
        }
 
        if (after) {
-               begin_reversible_selection_op (_("select all after edit"));
+               begin_reversible_selection_op (X_("select all after edit"));
        } else {
-               begin_reversible_selection_op (_("select all before edit"));
+               begin_reversible_selection_op (X_("select all before edit"));
        }
 
        TrackViewList* ts;
@@ -1797,8 +2087,8 @@ Editor::select_all_selectables_using_edit (bool after)
 void
 Editor::select_all_selectables_between (bool within)
 {
-       framepos_t start;
-       framepos_t end;
+       samplepos_t start;
+       samplepos_t end;
        list<Selectable *> touched;
 
        if (!get_edit_op_range (start, end)) {
@@ -1828,7 +2118,7 @@ Editor::select_all_selectables_between (bool within)
                (*iter)->get_selectables (start, end, 0, DBL_MAX, touched, within);
        }
 
-       begin_reversible_selection_op(_("Select all Selectables Between"));
+       begin_reversible_selection_op (X_("Select all Selectables Between"));
        selection->set (touched);
        commit_reversible_selection_op ();
 }
@@ -1836,10 +2126,10 @@ Editor::select_all_selectables_between (bool within)
 void
 Editor::select_range_between ()
 {
-       framepos_t start;
-       framepos_t end;
+       samplepos_t start;
+       samplepos_t end;
 
-       if ( !selection->time.empty() ) {
+       if (!selection->time.empty()) {
                selection->clear_time ();
        }
 
@@ -1847,32 +2137,35 @@ Editor::select_range_between ()
                return;
        }
 
-       begin_reversible_selection_op(_("Select Range Between"));
-       set_mouse_mode (MouseRange);
+       if (!get_smart_mode () || mouse_mode != Editing::MouseObject) {
+               set_mouse_mode (MouseRange, false);
+       }
+
+       begin_reversible_selection_op (X_("Select Range Between"));
        selection->set (start, end);
        commit_reversible_selection_op ();
 }
 
 bool
-Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
+Editor::get_edit_op_range (samplepos_t& start, samplepos_t& end) const
 {
-//     framepos_t m;
+//     samplepos_t m;
 //     bool ignored;
 
        /* if an explicit range exists, use it */
 
-       if ( (mouse_mode == MouseRange || get_smart_mode() ) &&  !selection->time.empty()) {
+       if ((mouse_mode == MouseRange || get_smart_mode()) &&  !selection->time.empty()) {
                /* we know that these are ordered */
                start = selection->time.start();
-               end = selection->time.end_frame();
+               end = selection->time.end_sample();
                return true;
        } else {
                start = 0;
                end = 0;
                return false;
        }
-       
-//     if (!mouse_frame (m, ignored)) {
+
+//     if (!mouse_sample (m, ignored)) {
 //             /* mouse is not in a canvas, try playhead+selected marker.
 //                this is probably most true when using menus.
 //             */
@@ -1882,7 +2175,7 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
 //             }
 
 //             start = selection->markers.front()->position();
-//             end = _session->audible_frame();
+//             end = _session->audible_sample();
 
 //     } else {
 
@@ -1891,10 +2184,10 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
 //                     if (selection->markers.empty()) {
 //                             /* use mouse + playhead */
 //                             start = m;
-//                             end = _session->audible_frame();
+//                             end = _session->audible_sample();
 //                     } else {
 //                             /* use playhead + selected marker */
-//                             start = _session->audible_frame();
+//                             start = _session->audible_sample();
 //                             end = selection->markers.front()->position();
 //                     }
 //                     break;
@@ -1903,7 +2196,7 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
 //                     /* use mouse + selected marker */
 //                     if (selection->markers.empty()) {
 //                             start = m;
-//                             end = _session->audible_frame();
+//                             end = _session->audible_sample();
 //                     } else {
 //                             start = selection->markers.front()->position();
 //                             end = m;
@@ -1957,15 +2250,15 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
 void
 Editor::deselect_all ()
 {
-       begin_reversible_selection_op(_("Deselect All"));
+       begin_reversible_selection_op (X_("Deselect All"));
        selection->clear ();
        commit_reversible_selection_op ();
 }
 
 long
-Editor::select_range (framepos_t s, framepos_t e)
+Editor::select_range (samplepos_t s, samplepos_t e)
 {
-       begin_reversible_selection_op(_("Select Range"));
+       begin_reversible_selection_op (X_("Select Range"));
        selection->add (clicked_axisview);
        selection->time.clear ();
        long ret = selection->set (s, e);