Merge branch 'master' into cairocanvas
[ardour.git] / gtk2_ardour / editor_selection.cc
index b98a7afd731e5b2559ce79e70cda2379f9a0c127..065cfdbcba42fb323049b0b5cf4dd8f0e8a692d6 100644 (file)
 
 #include "pbd/stacktrace.h"
 
-#include "ardour/session.h"
+#include "ardour/midi_region.h"
 #include "ardour/playlist.h"
-#include "ardour/route_group.h"
 #include "ardour/profile.h"
-#include "ardour/midi_region.h"
+#include "ardour/route_group.h"
+#include "ardour/session.h"
+
+#include "control_protocol/control_protocol.h"
 
 #include "editor.h"
 #include "actions.h"
@@ -177,13 +179,12 @@ Editor::select_all_tracks ()
  *  tracks, in which case nothing will happen unless `force' is true.
  */
 void
-Editor::set_selected_track_as_side_effect (Selection::Operation op, bool /*force*/)
+Editor::set_selected_track_as_side_effect (Selection::Operation op)
 {
        if (!clicked_axisview) {
                return;
        }
 
-#if 1
        if (!clicked_routeview) {
                return;
        }
@@ -262,21 +263,8 @@ Editor::set_selected_track_as_side_effect (Selection::Operation op, bool /*force
 
        case Selection::Extend:
                selection->clear();
-               cerr << ("Editor::set_selected_track_as_side_effect  case  Selection::Add  not yet implemented\n");
                break;
        }
-
-#else // the older version
-
-       if (!selection->tracks.empty()) {
-               if (!selection->selected (clicked_axisview)) {
-                       selection->add (clicked_axisview);
-               }
-
-       } else if (force) {
-               selection->set (clicked_axisview);
-       }
-#endif
 }
 
 void
@@ -324,7 +312,7 @@ Editor::set_selected_track_from_click (bool press, Selection::Operation op, bool
 }
 
 bool
-Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*no_remove*/)
+Editor::set_selected_control_point_from_click (bool press, Selection::Operation op)
 {
        if (!clicked_control_point) {
                return false;
@@ -332,13 +320,37 @@ Editor::set_selected_control_point_from_click (Selection::Operation op, bool /*n
 
        switch (op) {
        case Selection::Set:
-               selection->set (clicked_control_point);
+               if (press) {
+                       selection->set (clicked_control_point);
+               }
                break;
        case Selection::Add:
-               selection->add (clicked_control_point);
+               if (press) {
+                       selection->add (clicked_control_point);
+               }
                break;
        case Selection::Toggle:
-               selection->toggle (clicked_control_point);
+               /* 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
+                  unselected point.  So here we ensure that the point is selected
+                  after the press, and if we subsequently get a release (meaning no
+                  drag occurred) we set things up so that the toggle has happened.
+               */
+               if (press && !selection->selected (clicked_control_point)) {
+                       /* This is the button press, and the control point is not selected; make it so,
+                          in case this press leads to a drag.  Also note that having done this, we don't
+                          need to toggle again on release.
+                       */
+                       selection->toggle (clicked_control_point);
+                       _control_point_toggled_on_press = 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);
+               } else {
+                       /* Reset our flag */
+                       _control_point_toggled_on_press = false;
+               }
                break;
        case Selection::Extend:
                /* XXX */
@@ -352,7 +364,7 @@ void
 Editor::get_onscreen_tracks (TrackViewList& tvl)
 {
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               if ((*i)->y_position() < _canvas_height) {
+               if ((*i)->y_position() < _visible_canvas_height) {
                        tvl.push_back (*i);
                }
        }
@@ -401,6 +413,63 @@ Editor::mapover_tracks (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeA
        }
 }
 
+/** Call a slot for a given `basis' track and also for any track that is in the same
+ *  active route group with a particular set of properties.
+ *
+ *  @param sl Slot to call.
+ *  @param basis Basis track.
+ *  @param prop Properties that active edit groups must share to be included in the map.
+ */
+
+void
+Editor::mapover_tracks_with_unique_playlists (sigc::slot<void, RouteTimeAxisView&, uint32_t> sl, TimeAxisView* basis, PBD::PropertyID prop) const
+{
+       RouteTimeAxisView* route_basis = dynamic_cast<RouteTimeAxisView*> (basis);
+       set<boost::shared_ptr<Playlist> > playlists;
+
+       if (route_basis == 0) {
+               return;
+       }
+
+       set<RouteTimeAxisView*> tracks;
+       tracks.insert (route_basis);
+
+       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) ) {
+
+               /* the basis is a member of an active route group, with the appropriate
+                  properties; find other members */
+
+               for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
+                       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) {
+                                               /* haven't seen this playlist yet */
+                                               tracks.insert (v);
+                                       }
+                               } else {
+                                       /* not actually a "Track", but a timeaxis view that
+                                          we should mapover anyway.
+                                       */
+                                       tracks.insert (v);
+                               }
+                       }
+               }
+       }
+
+       /* call the slots */
+       uint32_t const sz = tracks.size ();
+
+       for (set<RouteTimeAxisView*>::iterator i = tracks.begin(); i != tracks.end(); ++i) {
+               sl (**i, sz);
+       }
+}
+
 void
 Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionView * basis, vector<RegionView*>* all_equivs) const
 {
@@ -433,7 +502,7 @@ Editor::mapped_get_equivalent_regions (RouteTimeAxisView& tv, uint32_t, RegionVi
 void
 Editor::get_equivalent_regions (RegionView* basis, vector<RegionView*>& equivalent_regions, PBD::PropertyID property) const
 {
-       mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_time_axis_view(), property);
+       mapover_tracks_with_unique_playlists (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), basis, &equivalent_regions), &basis->get_time_axis_view(), property);
 
        /* add clicked regionview since we skipped all other regions in the same track as the one it was in */
 
@@ -449,7 +518,7 @@ Editor::get_equivalent_regions (RegionSelection & basis, PBD::PropertyID prop) c
 
                vector<RegionView*> eq;
 
-               mapover_tracks (
+               mapover_tracks_with_unique_playlists (
                        sigc::bind (sigc::mem_fun (*this, &Editor::mapped_get_equivalent_regions), *i, &eq),
                        &(*i)->get_time_axis_view(), prop);
 
@@ -463,7 +532,6 @@ Editor::get_equivalent_regions (RegionSelection & basis, PBD::PropertyID prop) c
        return equivalent;
 }
 
-
 int
 Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
 {
@@ -503,7 +571,7 @@ Editor::get_regionview_count_from_region_list (boost::shared_ptr<Region> region)
 
 
 bool
-Editor::set_selected_regionview_from_click (bool press, Selection::Operation op, bool /*no_track_remove*/)
+Editor::set_selected_regionview_from_click (bool press, Selection::Operation op)
 {
        vector<RegionView*> all_equivalent_regions;
        bool commit = false;
@@ -518,7 +586,6 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
 
        if (op == Selection::Toggle || op == Selection::Set) {
 
-
                switch (op) {
                case Selection::Toggle:
                        if (selection->selected (clicked_regionview)) {
@@ -615,7 +682,7 @@ 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)) {
-                       case OverlapNone:
+                       case Evoral::OverlapNone:
                                if (last_frame < clicked_regionview->region()->first_frame()) {
                                        first_frame = last_frame;
                                        last_frame = clicked_regionview->region()->last_frame();
@@ -625,7 +692,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                                }
                                break;
 
-                       case OverlapExternal:
+                       case Evoral::OverlapExternal:
                                if (last_frame < clicked_regionview->region()->first_frame()) {
                                        first_frame = last_frame;
                                        last_frame = clicked_regionview->region()->last_frame();
@@ -635,7 +702,7 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                                }
                                break;
 
-                       case OverlapInternal:
+                       case Evoral::OverlapInternal:
                                if (last_frame < clicked_regionview->region()->first_frame()) {
                                        first_frame = last_frame;
                                        last_frame = clicked_regionview->region()->last_frame();
@@ -645,8 +712,8 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
                                }
                                break;
 
-                       case OverlapStart:
-                       case OverlapEnd:
+                       case Evoral::OverlapStart:
+                       case Evoral::OverlapEnd:
                                /* nothing to do except add clicked region to selection, since it
                                   overlaps with the existing selection in this track.
                                */
@@ -712,7 +779,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 ("editor");
+                                       int key = rtv->route()->order_key (EditorSort);
 
                                        for (RegionSelection::iterator x = selection->regions.begin(); x != selection->regions.end(); ++x) {
 
@@ -727,7 +794,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 ("editor");
+                                                               int d = artv->route()->order_key (EditorSort);
 
                                                                d -= key;
 
@@ -743,7 +810,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 ("editor");
+                                               int okey = closest->route()->order_key (EditorSort);
 
                                                if (okey > key) {
                                                        swap (okey, key);
@@ -753,7 +820,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 ("editor");
+                                                               int k = artv->route()->order_key (EditorSort);
 
                                                                if (k >= okey && k <= key) {
 
@@ -813,7 +880,7 @@ Editor::set_selected_regionview_from_region_list (boost::shared_ptr<Region> regi
 {
        vector<RegionView*> all_equivalent_regions;
 
-       get_regions_corresponding_to (region, all_equivalent_regions);
+       get_regions_corresponding_to (region, all_equivalent_regions, region->whole_file());
 
        if (all_equivalent_regions.empty()) {
                return;
@@ -882,6 +949,8 @@ Editor::track_selection_changed ()
                break;
        }
 
+       RouteNotificationListPtr routes (new RouteNotificationList);
+
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
 
                bool yn = (find (selection->tracks.begin(), selection->tracks.end(), *i) != selection->tracks.end());
@@ -893,16 +962,26 @@ Editor::track_selection_changed ()
                        (*j)->set_selected (find (selection->tracks.begin(), selection->tracks.end(), j->get()) != selection->tracks.end());
                }
 
-               if (yn &&
-                   ((mouse_mode == MouseRange) ||
-                    ((mouse_mode == MouseObject) && (_join_object_range_state == JOIN_OBJECT_RANGE_OBJECT)))) {
+               if (yn) {
                        (*i)->reshow_selection (selection->time);
                } else {
                        (*i)->hide_selection ();
                }
+
+
+               if (yn) {
+                       RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*i);
+                       if (rtav) {
+                               routes->push_back (rtav->route());
+                       }
+               }
        }
 
        ActionManager::set_sensitive (ActionManager::track_selection_sensitive_actions, !selection->tracks.empty());
+
+       /* notify control protocols */
+       
+       ControlProtocol::TrackSelectionChanged (routes);
 }
 
 void
@@ -925,6 +1004,10 @@ Editor::time_selection_changed ()
        } else {
                ActionManager::set_sensitive (ActionManager::time_selection_sensitive_actions, true);
        }
+
+       if (_session && Config->get_always_play_range() && !_session->transport_rolling() && !selection->time.empty()) {
+               _session->request_locate (selection->time.start());
+       }
 }
 
 /** Set all region actions to have a given sensitivity */
@@ -951,19 +1034,6 @@ Editor::sensitize_all_region_actions (bool s)
 void
 Editor::sensitize_the_right_region_actions ()
 {
-       if ((mouse_mode == MouseRange) || (mouse_mode != MouseObject && _join_object_range_state == JOIN_OBJECT_RANGE_RANGE)) {
-               sensitize_all_region_actions (false);
-               if (!selection->time.empty()) {
-                       _region_actions->get_action("split-region")->set_sensitive (true);
-               }
-               return;
-
-       } else if (mouse_mode != MouseObject) {
-               sensitize_all_region_actions (false);
-               return;
-       }
-
-       /* We get here if we are in Object mode */
 
        RegionSelection rs = get_regions_from_selection_and_entered ();
        sensitize_all_region_actions (!rs.empty ());
@@ -973,9 +1043,12 @@ Editor::sensitize_the_right_region_actions ()
        /* Look through the regions that are selected and make notes about what we have got */
 
        bool have_audio = false;
+       bool have_multichannel_audio = false;
        bool have_midi = false;
        bool have_locked = false;
        bool have_unlocked = false;
+       bool have_video_locked = false;
+       bool have_video_unlocked = false;
        bool have_position_lock_style_audio = false;
        bool have_position_lock_style_music = false;
        bool have_muted = false;
@@ -983,12 +1056,14 @@ Editor::sensitize_the_right_region_actions ()
        bool have_opaque = false;
        bool have_non_opaque = false;
        bool have_not_at_natural_position = false;
-       bool have_envelope_visible = false;
-       bool have_envelope_invisible = false;
        bool have_envelope_active = false;
        bool have_envelope_inactive = false;
        bool have_non_unity_scale_amplitude = false;
        bool have_compound_regions = false;
+       bool have_inactive_fade_in = false;
+       bool have_inactive_fade_out = false;
+       bool have_active_fade_in = false;
+       bool have_active_fade_out = false;
 
        for (list<RegionView*>::const_iterator i = rs.begin(); i != rs.end(); ++i) {
 
@@ -997,6 +1072,9 @@ Editor::sensitize_the_right_region_actions ()
 
                if (ar) {
                        have_audio = true;
+                       if (ar->n_channels() > 1) {
+                               have_multichannel_audio = true;
+                       }
                }
 
                if (boost::dynamic_pointer_cast<MidiRegion> (r)) {
@@ -1013,6 +1091,12 @@ Editor::sensitize_the_right_region_actions ()
                        have_unlocked = true;
                }
 
+               if (r->video_locked()) {
+                       have_video_locked = true;
+               } else {
+                       have_video_unlocked = true;
+               }
+
                if (r->position_lock_style() == MusicTime) {
                        have_position_lock_style_music = true;
                } else {
@@ -1036,20 +1120,6 @@ Editor::sensitize_the_right_region_actions ()
                }
 
                if (ar) {
-                       /* its a bit unfortunate that "envelope visible" is a view-only
-                          property. we have to find the regionview to able to check
-                          its current setting.
-                       */
-
-                       have_envelope_invisible = true;
-
-                       if (*i) {
-                               AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*i);
-                               if (arv && arv->envelope_visible()) {
-                                       have_envelope_visible = true;
-                               }
-                       }
-
                        if (ar->envelope_active()) {
                                have_envelope_active = true;
                        } else {
@@ -1059,6 +1129,18 @@ Editor::sensitize_the_right_region_actions ()
                        if (ar->scale_amplitude() != 1) {
                                have_non_unity_scale_amplitude = true;
                        }
+
+                       if (ar->fade_in_active ()) {
+                               have_active_fade_in = true;
+                       } else {
+                               have_inactive_fade_in = true;
+                       }
+
+                       if (ar->fade_out_active ()) {
+                               have_active_fade_out = true;
+                       } else {
+                               have_inactive_fade_out = true;
+                       }
                }
        }
 
@@ -1067,6 +1149,9 @@ Editor::sensitize_the_right_region_actions ()
                _region_actions->get_action("show-region-properties")->set_sensitive (false);
                _region_actions->get_action("rename-region")->set_sensitive (false);
                if (have_audio) {
+                       /* XXX need to check whether there is than 1 per
+                          playlist, because otherwise this makes no sense.
+                       */
                        _region_actions->get_action("combine-regions")->set_sensitive (true);
                } else {
                        _region_actions->get_action("combine-regions")->set_sensitive (false);
@@ -1077,20 +1162,28 @@ Editor::sensitize_the_right_region_actions ()
                _region_actions->get_action("combine-regions")->set_sensitive (false);
        }
 
+       if (!have_multichannel_audio) {
+               _region_actions->get_action("split-multichannel-region")->set_sensitive (false);
+       }
+
        if (!have_midi) {
+               editor_menu_actions->get_action("RegionMenuMIDI")->set_sensitive (false);
                _region_actions->get_action("show-region-list-editor")->set_sensitive (false);
                _region_actions->get_action("quantize-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);
                _region_actions->get_action("transpose-region")->set_sensitive (false);
+       } else {
+               editor_menu_actions->get_action("RegionMenuMIDI")->set_sensitive (true);
+               /* others were already marked sensitive */
        }
 
        if (_edit_point == EditAtMouse) {
-#if 0
                _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);
-#endif
                _region_actions->get_action("place-transient")->set_sensitive (false);
        }
 
@@ -1102,23 +1195,16 @@ Editor::sensitize_the_right_region_actions ()
 
        if (have_audio) {
 
-               if (have_envelope_visible && !have_envelope_invisible) {
-                       Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-gain-envelope-visible"))->set_active ();
-               } else if (have_envelope_visible && have_envelope_invisible) {
-                       // _region_actions->get_action("toggle-region-gain-envelope-visible")->set_inconsistent ();
-               }
-
                if (have_envelope_active && !have_envelope_inactive) {
                        Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-gain-envelope-active"))->set_active ();
                } else if (have_envelope_active && have_envelope_inactive) {
-                       // _region_actions->get_action("toggle-region-gain-envelope-active")->set_inconsistent ();
+                       // Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-gain-envelope-active"))->set_inconsistent ();
                }
 
        } else {
 
                _region_actions->get_action("analyze-region")->set_sensitive (false);
                _region_actions->get_action("reset-region-gain-envelopes")->set_sensitive (false);
-               _region_actions->get_action("toggle-region-gain-envelope-visible")->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);
 
@@ -1128,25 +1214,35 @@ Editor::sensitize_the_right_region_actions ()
                _region_actions->get_action("reset-region-scale-amplitude")->set_sensitive (false);
        }
 
-       Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-lock"))->set_active (have_locked && !have_unlocked);
+       Glib::RefPtr<ToggleAction> a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-lock"));
+       a->set_active (have_locked && !have_unlocked);
        if (have_locked && have_unlocked) {
-               // _region_actions->get_action("toggle-region-lock")->set_inconsistent ();
+               // a->set_inconsistent ();
+       }
+
+       a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-video-lock"));
+       a->set_active (have_video_locked && !have_video_unlocked);
+       if (have_video_locked && have_video_unlocked) {
+               // a->set_inconsistent ();
        }
 
-       Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-lock-style"))->set_active (have_position_lock_style_music && !have_position_lock_style_audio);
+       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) {
-               // _region_actions->get_action("toggle-region-lock-style")->set_inconsistent ();
+               // a->set_inconsistent ();
        }
 
-       Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-mute"))->set_active (have_muted && !have_unmuted);
+       a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-mute"));
+       a->set_active (have_muted && !have_unmuted);
        if (have_muted && have_unmuted) {
-               // _region_actions->get_action("toggle-region-mute")->set_inconsistent ();
+               // a->set_inconsistent ();
        }
 
-       Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-opaque-region"))->set_active (have_opaque && !have_non_opaque);
+       a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-opaque-region"));
+       a->set_active (have_opaque && !have_non_opaque);
        if (have_opaque && have_non_opaque) {
-               // _region_actions->get_action("toggle-opaque-region")->set_inconsistent ();
+               // a->set_inconsistent ();
        }
 
        if (!have_not_at_natural_position) {
@@ -1160,6 +1256,29 @@ Editor::sensitize_the_right_region_actions ()
                _region_actions->get_action("insert-region-from-region-list")->set_sensitive (true);
        }
 
+       a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-fade-in"));
+       a->set_active (have_active_fade_in && !have_inactive_fade_in);
+       if (have_active_fade_in && have_inactive_fade_in) {
+               // a->set_inconsistent ();
+       }
+
+       a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-fade-out"));
+       a->set_active (have_active_fade_out && !have_inactive_fade_out);
+
+       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;
+
+       a = Glib::RefPtr<ToggleAction>::cast_dynamic (_region_actions->get_action("toggle-region-fades"));
+       a->set_active (have_active_fade && !have_inactive_fade);
+
+       if (have_active_fade && have_inactive_fade) {
+               // a->set_inconsistent ();
+       }
+       
        _ignore_region_action = false;
 
        _all_region_actions_sensitized = false;
@@ -1187,7 +1306,16 @@ Editor::region_selection_changed ()
        _regions->block_change_connection (false);
        editor_regions_selection_changed_connection.block(false);
 
-       sensitize_the_right_region_actions ();
+       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);
+       }
+
+       if (_session && !_session->transport_rolling() && !selection->regions.empty()) {
+               maybe_locate_with_edit_preroll (selection->regions.start());
+       }
 }
 
 void
@@ -1241,17 +1369,48 @@ Editor::select_all (Selection::Operation op)
 {
        list<Selectable *> touched;
 
+       TrackViewList ts;
+
+       if (selection->tracks.empty()) {
+               if (entered_track) {
+                       ts.push_back (entered_track);
+               } else {
+                       ts = track_views;
+               }
+       } else {
+               ts = selection->tracks;
+       }
+
        if (_internal_editing) {
-               select_all_internal_edit (op);
-               return;
+
+               bool midi_selected = false;
+
+               for (TrackViewList::iterator iter = ts.begin(); iter != ts.end(); ++iter) {
+                       if ((*iter)->hidden()) {
+                               continue;
+                       }
+                       
+                       RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (*iter);
+
+                       if (rtav && rtav->is_midi_track()) {
+                               midi_selected = true;
+                               break;
+                       }
+               }
+
+               if (midi_selected) {
+                       select_all_internal_edit (op);
+                       return;
+               }
        }
 
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+       for (TrackViewList::iterator iter = ts.begin(); iter != ts.end(); ++iter) {
                if ((*iter)->hidden()) {
                        continue;
                }
                (*iter)->get_selectables (0, max_framepos, 0, DBL_MAX, touched);
        }
+
        begin_reversible_command (_("select all"));
        switch (op) {
        case Selection::Add:
@@ -1518,12 +1677,12 @@ Editor::select_all_selectables_using_cursor (EditorCursor *cursor, bool after)
        list<Selectable *> touched;
 
        if (after) {
-               start = cursor->current_frame;
+               start = cursor->current_frame();
                end = _session->current_end_frame();
        } else {
-               if (cursor->current_frame > 0) {
+               if (cursor->current_frame() > 0) {
                        start = 0;
-                       end = cursor->current_frame - 1;
+                       end = cursor->current_frame() - 1;
                } else {
                        return;
                }
@@ -1657,7 +1816,7 @@ Editor::select_range_between ()
        framepos_t start;
        framepos_t end;
 
-       if (mouse_mode == MouseRange && !selection->time.empty()) {
+       if ( !selection->time.empty() ) {
                selection->clear_time ();
        }
 
@@ -1675,9 +1834,9 @@ Editor::get_edit_op_range (framepos_t& start, framepos_t& end) const
        framepos_t m;
        bool ignored;
 
-       /* in range mode, use any existing selection */
+       /* if an explicit range exists, use it */
 
-       if (mouse_mode == MouseRange && !selection->time.empty()) {
+       if (!selection->time.empty()) {
                /* we know that these are ordered */
                start = selection->time.start();
                end = selection->time.end_frame();
@@ -1773,13 +1932,9 @@ Editor::deselect_all ()
 }
 
 long
-Editor::select_range_around_region (RegionView* rv)
+Editor::select_range (framepos_t s, framepos_t e)
 {
-       assert (rv);
-
-       selection->set (&rv->get_time_axis_view());
-
+       selection->add (clicked_axisview);
        selection->time.clear ();
-       boost::shared_ptr<Region> r = rv->region ();
-       return selection->set (r->position(), r->position() + r->length());
+       return selection->set (s, e);
 }