Fix quantization and other time-related ops.
[ardour.git] / gtk2_ardour / editor.cc
index f3195daec271359348670b7499687ff7a565ddc4..ce6e6b15ae5ca0a32b5617fa46a983b4b69a8a6b 100644 (file)
@@ -45,6 +45,7 @@
 #include "pbd/unknown_type.h"
 #include "pbd/unwind.h"
 #include "pbd/stacktrace.h"
+#include "pbd/timersub.h"
 
 #include <glibmm/miscutils.h>
 #include <glibmm/uriutils.h>
 #include "tempo_lines.h"
 #include "time_axis_view.h"
 #include "utils.h"
+#include "verbose_cursor.h"
 
 #include "i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace Gtk;
 using namespace Glib;
@@ -139,9 +142,9 @@ const double Editor::timebar_height = 15.0;
 
 static const gchar *_snap_type_strings[] = {
        N_("CD Frames"),
-       N_("Timecode Frames"),
-       N_("Timecode Seconds"),
-       N_("Timecode Minutes"),
+       N_("TC Frames"),
+       N_("TC Seconds"),
+       N_("TC Minutes"),
        N_("Seconds"),
        N_("Minutes"),
        N_("Beats/128"),
@@ -185,6 +188,14 @@ static const gchar *_edit_point_strings[] = {
        0
 };
 
+static const gchar *_edit_mode_strings[] = {
+       N_("Slide"),
+       N_("Splice"),
+       N_("Ripple"),
+       N_("Lock"),
+       0
+};
+
 static const gchar *_zoom_focus_strings[] = {
        N_("Left"),
        N_("Right"),
@@ -208,6 +219,8 @@ static const gchar *_rb_opt_strings[] = {
 };
 #endif
 
+#define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
+
 static void
 pane_size_watcher (Paned* pane)
 {
@@ -261,7 +274,6 @@ Editor::Editor ()
 
          /* tool bar related */
 
-       , zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
        , toolbar_selection_clock_table (2,3)
        , _mouse_mode_tearoff (0)
        , automation_mode_button (_("mode"))
@@ -300,13 +312,18 @@ Editor::Editor ()
        clicked_control_point = 0;
        last_update_frame = 0;
         pre_press_cursor = 0;
+       last_paste_pos = 0;
+       paste_count = 0;
        _drags = new DragManager (this);
+       lock_dialog = 0;
+       ruler_dialog = 0;
        current_mixer_strip = 0;
        tempo_lines = 0;
 
        snap_type_strings =  I18N (_snap_type_strings);
        snap_mode_strings =  I18N (_snap_mode_strings);
        zoom_focus_strings = I18N (_zoom_focus_strings);
+       edit_mode_strings = I18N (_edit_mode_strings);
        edit_point_strings = I18N (_edit_point_strings);
 #ifdef USE_RUBBERBAND
        rb_opt_strings = I18N (_rb_opt_strings);
@@ -373,24 +390,22 @@ Editor::Editor ()
 
        sfbrowser = 0;
 
-       location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
-       location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
-       location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
-       location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
-       location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
+       location_marker_color = ARDOUR_UI::config()->get_LocationMarker();
+       location_range_color = ARDOUR_UI::config()->get_LocationRange();
+       location_cd_marker_color = ARDOUR_UI::config()->get_LocationCDMarker();
+       location_loop_color = ARDOUR_UI::config()->get_LocationLoop();
+       location_punch_color = ARDOUR_UI::config()->get_LocationPunch();
 
        zoom_focus = ZoomFocusLeft;
        _edit_point = EditAtMouse;
        _internal_editing = false;
        current_canvas_cursor = 0;
-       _visible_track_count = 16;
+       _visible_track_count = -1;
 
        samples_per_pixel = 2048; /* too early to use reset_zoom () */
 
        _scroll_callbacks = 0;
 
-       zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
-
        bbt_label.set_name ("EditorRulerLabel");
        bbt_label.set_size_request (-1, (int)timebar_height);
        bbt_label.set_alignment (1.0, 0.5);
@@ -471,6 +486,8 @@ Editor::Editor ()
 
        initialize_canvas ();
 
+       CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
+
        _summary = new EditorSummary (this);
 
        selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
@@ -500,6 +517,7 @@ Editor::Editor ()
 
        _cursors = new MouseCursors;
        _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
+       cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
 
        ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
 
@@ -537,6 +555,12 @@ Editor::Editor ()
        _snapshots = new EditorSnapshots (this);
        _locations = new EditorLocations (this);
 
+       /* these are static location signals */
+
+       Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
+       Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
+       Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
+
        add_notebook_page (_("Regions"), _regions->widget ());
        add_notebook_page (_("Tracks & Busses"), _routes->widget ());
        add_notebook_page (_("Snapshots"), _snapshots->widget ());
@@ -659,11 +683,9 @@ Editor::Editor ()
        /* nudge stuff */
 
        nudge_forward_button.set_name ("nudge button");
-//     nudge_forward_button.add_elements (ArdourButton::Inset);
        nudge_forward_button.set_image(::get_icon("nudge_right"));
 
        nudge_backward_button.set_name ("nudge button");
-//     nudge_backward_button.add_elements (ArdourButton::Inset);
        nudge_backward_button.set_image(::get_icon("nudge_left"));
 
        fade_context_menu.set_name ("ArdourContextMenu");
@@ -741,8 +763,9 @@ Editor::Editor ()
        _last_region_menu_was_main = false;
        _popup_region_menu_item = 0;
 
+       _ignore_follow_edits = false;
+
        _show_marker_lines = false;
-       _over_region_trim_target = false;
 
         /* Button bindings */
 
@@ -756,9 +779,14 @@ Editor::Editor ()
         }
 
        constructed = true;
-       instant_save ();
+
+       /* grab current parameter state */
+       boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
+       ARDOUR_UI::config()->map_parameters (pc);
 
        setup_fade_images ();
+
+       instant_save ();
 }
 
 Editor::~Editor()
@@ -768,6 +796,7 @@ Editor::~Editor()
        delete _route_groups;
        delete _track_canvas_viewport;
        delete _drags;
+       delete nudge_clock;
 }
 
 XMLNode*
@@ -784,16 +813,28 @@ Editor::button_settings () const
 }
 
 void
-Editor::add_toplevel_controls (Container& cont)
+Editor::add_toplevel_menu (Container& cont)
 {
        vpacker.pack_start (cont, false, false);
        cont.show_all ();
 }
 
+void
+Editor::add_transport_frame (Container& cont)
+{
+       if(ARDOUR::Profile->get_mixbus()) {
+               global_vpacker.pack_start (cont, false, false);
+               global_vpacker.reorder_child (cont, 0);
+               cont.show_all ();
+       } else {
+               vpacker.pack_start (cont, false, false);
+       }
+}
+
 bool
 Editor::get_smart_mode () const
 {
-       return ( (current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active() );
+       return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
 }
 
 void
@@ -818,8 +859,6 @@ Editor::catch_vanishing_regionview (RegionView *rv)
        if (!_all_region_actions_sensitized) {
                sensitize_all_region_actions (true);
        }
-
-       _over_region_trim_target = false;
 }
 
 void
@@ -833,7 +872,9 @@ Editor::set_entered_regionview (RegionView* rv)
                entered_regionview->exited ();
        }
 
-       if ((entered_regionview = rv) != 0) {
+       entered_regionview = rv;
+
+       if (entered_regionview  != 0) {
                entered_regionview->entered (internal_editing ());
        }
 
@@ -852,7 +893,9 @@ Editor::set_entered_track (TimeAxisView* tav)
                entered_track->exited ();
        }
 
-       if ((entered_track = tav) != 0) {
+       entered_track = tav;
+
+       if (entered_track) {
                entered_track->entered ();
        }
 }
@@ -861,6 +904,7 @@ void
 Editor::show_window ()
 {
        if (!is_visible ()) {
+               DisplaySuspender ds;
                show_all ();
 
                /* XXX: this is a bit unfortunate; it would probably
@@ -887,7 +931,7 @@ Editor::show_window ()
 
                if (current_mixer_strip) {
                        current_mixer_strip->hide_things ();
-                       current_mixer_strip->parameter_changed ("mixer-strip-visibility");
+                       current_mixer_strip->parameter_changed ("mixer-element-visibility");
                }
        }
 
@@ -908,23 +952,6 @@ Editor::instant_save ()
        }
 }
 
-void
-Editor::zoom_adjustment_changed ()
-{
-       if (_session == 0) {
-               return;
-       }
-
-       framecnt_t fpu = llrintf (zoom_range_clock->current_duration() / _visible_canvas_width);
-       bool clamped = clamp_samples_per_pixel (fpu);
-       
-       if (clamped) {
-               zoom_range_clock->set ((framepos_t) floor (fpu * _visible_canvas_width));
-       }
-
-       temporal_zoom (fpu);
-}
-
 void
 Editor::control_vertical_zoom_in_all ()
 {
@@ -1038,12 +1065,12 @@ Editor::control_scroll (float fraction)
                _dragging_playhead = true;
        }
 
-       if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
+       if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
                *_control_scroll_target = 0;
        } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
                *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
        } else {
-               *_control_scroll_target += (framepos_t) floor (step);
+               *_control_scroll_target += (framepos_t) trunc (step);
        }
 
        /* move visuals, we'll catch up with it later */
@@ -1105,6 +1132,79 @@ Editor::on_realize ()
 {
        Window::on_realize ();
        Realized ();
+
+       if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
+               start_lock_event_timing ();
+       }
+
+       signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
+}
+
+void
+Editor::start_lock_event_timing ()
+{
+       /* check if we should lock the GUI every 30 seconds */
+
+       Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
+}
+
+bool
+Editor::generic_event_handler (GdkEvent* ev)
+{
+       switch (ev->type) {
+       case GDK_BUTTON_PRESS:
+       case GDK_BUTTON_RELEASE:
+       case GDK_MOTION_NOTIFY:
+       case GDK_KEY_PRESS:
+       case GDK_KEY_RELEASE:
+               gettimeofday (&last_event_time, 0);
+               break;
+
+       case GDK_LEAVE_NOTIFY:
+               switch (ev->crossing.detail) {
+               case GDK_NOTIFY_UNKNOWN:
+               case GDK_NOTIFY_INFERIOR:
+               case GDK_NOTIFY_ANCESTOR:
+                       break; 
+               case GDK_NOTIFY_VIRTUAL:
+               case GDK_NOTIFY_NONLINEAR:
+               case GDK_NOTIFY_NONLINEAR_VIRTUAL:
+                       /* leaving window, so reset focus, thus ending any and
+                          all text entry operations.
+                       */
+                       reset_focus();
+                       break;
+               }
+               break;
+
+       default:
+               break;
+       }
+
+       return false;
+}
+
+bool
+Editor::lock_timeout_callback ()
+{
+       struct timeval now, delta;
+
+       gettimeofday (&now, 0);
+
+       timersub (&now, &last_event_time, &delta);
+
+       if (delta.tv_sec > (time_t) ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
+               lock ();
+               /* don't call again. Returning false will effectively
+                  disconnect us from the timer callback.
+
+                  unlock() will call start_lock_event_timing() to get things
+                  started again.
+               */
+               return false;
+       }
+
+       return true;
 }
 
 void
@@ -1188,7 +1288,6 @@ Editor::set_session (Session *t)
                return;
        }
 
-       zoom_range_clock->set_session (_session);
        _playlist_selector->set_session (_session);
        nudge_clock->set_session (_session);
        _summary->set_session (_session);
@@ -1259,7 +1358,6 @@ Editor::set_session (Session *t)
        _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
        _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
        _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
-       _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
        _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
 
        playhead_cursor->show ();
@@ -1701,6 +1799,9 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
        edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
        edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
 
+       edit_items.push_back (SeparatorElem());
+       edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
+
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
 
@@ -1791,7 +1892,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        select_menu->set_name ("ArdourContextMenu");
 
        select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
-       select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
+       select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
        select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
        select_items.push_back (SeparatorElem());
@@ -1868,7 +1969,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        select_menu->set_name ("ArdourContextMenu");
 
        select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
-       select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
+       select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
        select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
        select_items.push_back (SeparatorElem());
@@ -2003,13 +2104,16 @@ Editor::set_edit_point_preference (EditPoint ep, bool force)
        bool changed = (_edit_point != ep);
 
        _edit_point = ep;
-       string str = edit_point_strings[(int)ep];
+       if (Profile->get_mixbus())
+               if (ep == EditAtSelectedMarker)
+                       ep = EditAtPlayhead;
 
+       string str = edit_point_strings[(int)ep];
        if (str != edit_point_selector.get_text ()) {
                edit_point_selector.set_text (str);
        }
 
-       set_canvas_cursor ();
+       reset_canvas_cursor ();
 
        if (!force && !changed) {
                return;
@@ -2099,7 +2203,12 @@ Editor::set_state (const XMLNode& node, int /*version*/)
        if (_session && (prop = node.property ("playhead"))) {
                framepos_t pos;
                sscanf (prop->value().c_str(), "%" PRIi64, &pos);
-               playhead_cursor->set_position (pos);
+               if (pos >= 0) {
+                       playhead_cursor->set_position (pos);
+               } else {
+                       warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
+                       playhead_cursor->set_position (0);
+               }
        } else {
                playhead_cursor->set_position (0);
        }
@@ -2415,7 +2524,7 @@ Editor::get_state ()
  *  in stacked or expanded region display mode, otherwise 0.
  */
 std::pair<TimeAxisView *, double>
-Editor::trackview_by_y_position (double y, bool trackview_relative_offset)
+Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
 {
        if (!trackview_relative_offset) {
                y -= _trackview_group->canvas_origin().y;
@@ -2425,7 +2534,7 @@ Editor::trackview_by_y_position (double y, bool trackview_relative_offset)
                return std::make_pair ( (TimeAxisView *) 0, 0);
        }
 
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+       for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
                        
                std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
                        
@@ -2443,7 +2552,7 @@ Editor::trackview_by_y_position (double y, bool trackview_relative_offset)
  *  @param event Event to get current key modifier information from, or 0.
  */
 void
-Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
+Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
 {
        if (!_session || !event) {
                return;
@@ -2461,7 +2570,7 @@ Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_
 }
 
 void
-Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
+Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark)
 {
        if (!_session || _snap_mode == SnapOff) {
                return;
@@ -2471,14 +2580,17 @@ Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
 }
 
 void
-Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
+Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
 {
        const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
        framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
 
        switch (_snap_type) {
        case SnapToTimecodeFrame:
-               if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
+                       /* start is already on a whole timecode frame, do nothing */
+               } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
                        start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
                } else {
                        start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) *  _session->frames_per_timecode_frame());
@@ -2491,7 +2603,10 @@ Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*
                } else {
                        start -= _session->config.get_timecode_offset ();
                }
-               if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   (start % one_timecode_second == 0)) {
+                       /* start is already on a whole second, do nothing */
+               } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
                        start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
                } else {
                        start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
@@ -2510,7 +2625,10 @@ Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*
                } else {
                        start -= _session->config.get_timecode_offset ();
                }
-               if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   (start % one_timecode_minute == 0)) {
+                       /* start is already on a whole minute, do nothing */
+               } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
                        start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
                } else {
                        start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
@@ -2523,12 +2641,12 @@ Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*
                break;
        default:
                fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
-               /*NOTREACHED*/
+               abort(); /*NOTREACHED*/
        }
 }
 
 void
-Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
+Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
 {
        const framepos_t one_second = _session->frame_rate();
        const framepos_t one_minute = _session->frame_rate() * 60;
@@ -2543,7 +2661,10 @@ Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
                return timecode_snap_to_internal (start, direction, for_mark);
 
        case SnapToCDFrame:
-               if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   start % (one_second/75) == 0) {
+                       /* start is already on a whole CD frame, do nothing */
+               } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
                        start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
                } else {
                        start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
@@ -2551,7 +2672,10 @@ Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
                break;
 
        case SnapToSeconds:
-               if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   start % one_second == 0) {
+                       /* start is already on a whole second, do nothing */
+               } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
                        start = (framepos_t) ceil ((double) start / one_second) * one_second;
                } else {
                        start = (framepos_t) floor ((double) start / one_second) * one_second;
@@ -2559,7 +2683,10 @@ Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
                break;
 
        case SnapToMinutes:
-               if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
+               if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
+                   start % one_minute == 0) {
+                       /* start is already on a whole minute, do nothing */
+               } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
                        start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
                } else {
                        start = (framepos_t) floor ((double) start / one_minute) * one_minute;
@@ -2713,26 +2840,43 @@ Editor::setup_toolbar ()
 {
        HBox* mode_box = manage(new HBox);
        mode_box->set_border_width (2);
-       mode_box->set_spacing(4);
+       mode_box->set_spacing(2);
 
        HBox* mouse_mode_box = manage (new HBox);
        HBox* mouse_mode_hbox = manage (new HBox);
        VBox* mouse_mode_vbox = manage (new VBox);
        Alignment* mouse_mode_align = manage (new Alignment);
 
-       Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
-//     mouse_mode_size_group->add_widget (smart_mode_button);
+       Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
+       mouse_mode_size_group->add_widget (smart_mode_button);
        mouse_mode_size_group->add_widget (mouse_move_button);
+       mouse_mode_size_group->add_widget (mouse_cut_button);
        mouse_mode_size_group->add_widget (mouse_select_button);
-       mouse_mode_size_group->add_widget (mouse_zoom_button);
        mouse_mode_size_group->add_widget (mouse_gain_button);
        mouse_mode_size_group->add_widget (mouse_timefx_button);
        mouse_mode_size_group->add_widget (mouse_audition_button);
        mouse_mode_size_group->add_widget (mouse_draw_button);
        mouse_mode_size_group->add_widget (internal_edit_button);
 
-       /* make them just a bit bigger */
-       mouse_move_button.set_size_request (-1, 30);
+       mouse_mode_size_group->add_widget (zoom_in_button);
+       mouse_mode_size_group->add_widget (zoom_out_button);
+       mouse_mode_size_group->add_widget (zoom_preset_selector);
+       mouse_mode_size_group->add_widget (zoom_out_full_button);
+       mouse_mode_size_group->add_widget (zoom_focus_selector);
+
+       mouse_mode_size_group->add_widget (tav_shrink_button);
+       mouse_mode_size_group->add_widget (tav_expand_button);
+       mouse_mode_size_group->add_widget (visible_tracks_selector);
+
+       mouse_mode_size_group->add_widget (snap_type_selector);
+       mouse_mode_size_group->add_widget (snap_mode_selector);
+
+       mouse_mode_size_group->add_widget (edit_point_selector);
+       mouse_mode_size_group->add_widget (edit_mode_selector);
+
+       mouse_mode_size_group->add_widget (*nudge_clock);
+       mouse_mode_size_group->add_widget (nudge_forward_button);
+       mouse_mode_size_group->add_widget (nudge_backward_button);
 
        mouse_mode_hbox->set_spacing (2);
 
@@ -2742,14 +2886,17 @@ Editor::setup_toolbar ()
 
        mouse_mode_hbox->pack_start (mouse_move_button, false, false);
        mouse_mode_hbox->pack_start (mouse_select_button, false, false);
-       mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
 
+       if (!ARDOUR::Profile->get_mixbus()) {
+               mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
+       }
+       
        if (!ARDOUR::Profile->get_trx()) {
                mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
                mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
                mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
                mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
-               mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
+               mouse_mode_hbox->pack_start (internal_edit_button, false, false, 0);
        }
 
        mouse_mode_vbox->pack_start (*mouse_mode_hbox);
@@ -2759,15 +2906,7 @@ Editor::setup_toolbar ()
 
        mouse_mode_box->pack_start (*mouse_mode_align, false, false);
 
-       edit_mode_strings.push_back (edit_mode_to_string (Slide));
-       if (!Profile->get_sae()) {
-               edit_mode_strings.push_back (edit_mode_to_string (Splice));
-       }
-       edit_mode_strings.push_back (edit_mode_to_string (Lock));
-
        edit_mode_selector.set_name ("mouse mode button");
-       edit_mode_selector.set_size_request (65, -1);
-       edit_mode_selector.add_elements (ArdourButton::Inset);
 
        if (!ARDOUR::Profile->get_trx()) {
                mode_box->pack_start (edit_mode_selector, false, false);
@@ -2778,7 +2917,7 @@ Editor::setup_toolbar ()
        _mouse_mode_tearoff->set_name ("MouseModeBase");
        _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
 
-       if (Profile->get_sae()) {
+       if (Profile->get_sae() || Profile->get_mixbus() ) {
                _mouse_mode_tearoff->set_can_be_torn_off (false);
        }
 
@@ -2798,67 +2937,68 @@ Editor::setup_toolbar ()
 
        RefPtr<Action> act;
 
+       zoom_preset_selector.set_name ("zoom button");
+       zoom_preset_selector.set_image(::get_icon ("time_exp"));
+       zoom_preset_selector.set_size_request (42, -1);
+
        zoom_in_button.set_name ("zoom button");
-//     zoom_in_button.add_elements ( ArdourButton::Inset );
-       zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        zoom_in_button.set_image(::get_icon ("zoom_in"));
        act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
        zoom_in_button.set_related_action (act);
 
        zoom_out_button.set_name ("zoom button");
-//     zoom_out_button.add_elements ( ArdourButton::Inset );
-       zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        zoom_out_button.set_image(::get_icon ("zoom_out"));
        act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
        zoom_out_button.set_related_action (act);
 
        zoom_out_full_button.set_name ("zoom button");
-//     zoom_out_full_button.add_elements ( ArdourButton::Inset );
-       zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        zoom_out_full_button.set_image(::get_icon ("zoom_full"));
        act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
        zoom_out_full_button.set_related_action (act);
 
        zoom_focus_selector.set_name ("zoom button");
-       zoom_focus_selector.set_size_request (80, -1);
-//     zoom_focus_selector.add_elements (ArdourButton::Inset);
 
-       if (!ARDOUR::Profile->get_trx()) {
+       if (ARDOUR::Profile->get_mixbus()) {
+               _zoom_box.pack_start (zoom_preset_selector, false, false);
+       } else if (ARDOUR::Profile->get_trx()) {
+               mode_box->pack_start (zoom_out_button, false, false);
+               mode_box->pack_start (zoom_in_button, false, false);
+       } else {
                _zoom_box.pack_start (zoom_out_button, false, false);
                _zoom_box.pack_start (zoom_in_button, false, false);
                _zoom_box.pack_start (zoom_out_full_button, false, false);
                _zoom_box.pack_start (zoom_focus_selector, false, false);
-       } else {
-               mode_box->pack_start (zoom_out_button, false, false);
-               mode_box->pack_start (zoom_in_button, false, false);
        }
 
        /* Track zoom buttons */
        visible_tracks_selector.set_name ("zoom button");
-//     visible_tracks_selector.add_elements ( ArdourButton::Inset );
-       set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
+       if (Profile->get_mixbus()) {
+               visible_tracks_selector.set_image(::get_icon ("tav_exp"));
+               visible_tracks_selector.set_size_request (42, -1);
+       } else {
+               set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
+       }
 
        tav_expand_button.set_name ("zoom button");
-//     tav_expand_button.add_elements ( ArdourButton::FlatFace );
-       tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
-       tav_expand_button.set_size_request (-1, 20);
        tav_expand_button.set_image(::get_icon ("tav_exp"));
        act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
        tav_expand_button.set_related_action (act);
 
        tav_shrink_button.set_name ("zoom button");
-//     tav_shrink_button.add_elements ( ArdourButton::FlatFace );
-       tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
-       tav_shrink_button.set_size_request (-1, 20);
        tav_shrink_button.set_image(::get_icon ("tav_shrink"));
        act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
        tav_shrink_button.set_related_action (act);
 
-       if (!ARDOUR::Profile->get_trx()) {
+       if (ARDOUR::Profile->get_mixbus()) {
+               _zoom_box.pack_start (visible_tracks_selector);
+       } else if (ARDOUR::Profile->get_trx()) {
+               _zoom_box.pack_start (tav_shrink_button);
+               _zoom_box.pack_start (tav_expand_button);
+       } else {
                _zoom_box.pack_start (visible_tracks_selector);
+               _zoom_box.pack_start (tav_shrink_button);
+               _zoom_box.pack_start (tav_expand_button);
        }
-       _zoom_box.pack_start (tav_shrink_button);
-       _zoom_box.pack_start (tav_expand_button);
 
        if (!ARDOUR::Profile->get_trx()) {
                _zoom_tearoff = manage (new TearOff (_zoom_box));
@@ -2873,20 +3013,18 @@ Editor::setup_toolbar ()
                                                            &_zoom_tearoff->tearoff_window(), 0));
        } 
 
+       if (Profile->get_sae() || Profile->get_mixbus() ) {
+               _zoom_tearoff->set_can_be_torn_off (false);
+       }
+
        snap_box.set_spacing (2);
        snap_box.set_border_width (2);
 
        snap_type_selector.set_name ("mouse mode button");
-       snap_type_selector.set_size_request (140, -1);
-       snap_type_selector.add_elements (ArdourButton::Inset);
 
        snap_mode_selector.set_name ("mouse mode button");
-       snap_mode_selector.set_size_request (85, -1);
-       snap_mode_selector.add_elements (ArdourButton::Inset);
 
        edit_point_selector.set_name ("mouse mode button");
-       edit_point_selector.set_size_request (85, -1);
-       edit_point_selector.add_elements (ArdourButton::Inset);
 
        snap_box.pack_start (snap_mode_selector, false, false);
        snap_box.pack_start (snap_type_selector, false, false);
@@ -2901,9 +3039,6 @@ Editor::setup_toolbar ()
        nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
        nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
 
-       nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
-       nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
-
        nudge_box->pack_start (nudge_backward_button, false, false);
        nudge_box->pack_start (nudge_forward_button, false, false);
        nudge_box->pack_start (*nudge_clock, false, false);
@@ -2912,13 +3047,13 @@ Editor::setup_toolbar ()
        /* Pack everything in... */
 
        HBox* hbox = manage (new HBox);
-       hbox->set_spacing(10);
+       hbox->set_spacing(2);
 
        _tools_tearoff = manage (new TearOff (*hbox));
        _tools_tearoff->set_name ("MouseModeBase");
        _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
 
-       if (Profile->get_sae()) {
+       if (Profile->get_sae() || Profile->get_mixbus()) {
                _tools_tearoff->set_can_be_torn_off (false);
        }
 
@@ -2931,7 +3066,7 @@ Editor::setup_toolbar ()
        _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                                     &_tools_tearoff->tearoff_window(), 0));
 
-       toolbar_hbox.set_spacing (10);
+       toolbar_hbox.set_spacing (2);
        toolbar_hbox.set_border_width (1);
 
        toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
@@ -2942,7 +3077,7 @@ Editor::setup_toolbar ()
 
        if (!ARDOUR::Profile->get_trx()) {
                hbox->pack_start (snap_box, false, false);
-               if (!Profile->get_small_screen()) {
+               if ( !Profile->get_small_screen() || Profile->get_mixbus() ) {
                        hbox->pack_start (*nudge_box, false, false);
                } else {
                        ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
@@ -2970,18 +3105,24 @@ Editor::build_edit_point_menu ()
        using namespace Menu_Helpers;
 
        edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
-       edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
+       if(!Profile->get_mixbus())
+               edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
        edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
+
+       set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
 }
 
 void
 Editor::build_edit_mode_menu ()
 {
        using namespace Menu_Helpers;
+       
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
+//     edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
 
-       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
-       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
-       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
+       set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
 }
 
 void
@@ -2992,6 +3133,8 @@ Editor::build_snap_mode_menu ()
        snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
        snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
        snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
+
+       set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
 }
 
 void
@@ -3029,6 +3172,9 @@ Editor::build_snap_type_menu ()
        snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
        snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
        snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
+
+       set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
+
 }
 
 void
@@ -3036,10 +3182,10 @@ Editor::setup_tooltips ()
 {
        ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
        ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
+       ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
        ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
        ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
        ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
-       ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
        ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
        ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
        ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
@@ -3048,6 +3194,7 @@ Editor::setup_tooltips ()
        ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
        ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
        ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
+       ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
        ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
        ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
        ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
@@ -3292,10 +3439,11 @@ Editor::cycle_edit_mode ()
                if (Profile->get_sae()) {
                        Config->set_edit_mode (Lock);
                } else {
-                       Config->set_edit_mode (Splice);
+                       Config->set_edit_mode (Ripple);
                }
                break;
        case Splice:
+       case Ripple:
                Config->set_edit_mode (Lock);
                break;
        case Lock:
@@ -3332,6 +3480,9 @@ Editor::snap_mode_selection_done (SnapMode mode)
 void
 Editor::cycle_edit_point (bool with_marker)
 {
+       if(Profile->get_mixbus())
+               with_marker = false;
+
        switch (_edit_point) {
        case EditAtMouse:
                set_edit_point_preference (EditAtPlayhead);
@@ -3366,6 +3517,8 @@ Editor::build_zoom_focus_menu ()
        zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
        zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
        zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
+
+       set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
 }
 
 void
@@ -3382,18 +3535,56 @@ Editor::build_track_count_menu ()
 {
        using namespace Menu_Helpers;
 
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
-       visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
-       visible_tracks_selector.AddMenuElem (MenuElem (_("all"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
+       if (!Profile->get_mixbus()) {
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
+               visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
+       } else {
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
+               visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selected tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
+
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
+               zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
+       }
+}
+
+void
+Editor::set_zoom_preset (int64_t ms)
+{
+       if ( ms <= 0 ) {
+               temporal_zoom_session();
+               return;
+       }
+       
+       ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
+       temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
 }
 
 void
@@ -3413,15 +3604,21 @@ Editor::set_visible_track_count (int32_t n)
 
        int h;
        string str;
-
+       
        if (_visible_track_count > 0) {
-               h = _visible_canvas_height / _visible_track_count;
+               h = trackviews_height() / _visible_track_count;
                std::ostringstream s;
                s << _visible_track_count;
                str = s.str();
        } else if (_visible_track_count == 0) {
-               h = _visible_canvas_height / track_views.size();
-               str = _("all");
+               uint32_t n = 0;
+               for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+                       if ((*i)->marked_for_display()) {
+                               ++n;
+                       }
+               }
+               h = trackviews_height() / n;
+               str = _("All");
        } else {
                /* negative value means that the visible track count has 
                   been overridden by explicit track height changes.
@@ -3442,7 +3639,8 @@ Editor::set_visible_track_count (int32_t n)
 void
 Editor::override_visible_track_count ()
 {
-       _visible_track_count = -_visible_track_count;
+       _visible_track_count = -1;
+       visible_tracks_selector.set_text ( _("*") );
 }
 
 bool
@@ -3677,6 +3875,25 @@ Editor::playlist_selector () const
        return *_playlist_selector;
 }
 
+framecnt_t
+Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
+{
+       if (paste_count == 0) {
+               /* don't bother calculating an offset that will be zero anyway */
+               return 0;
+       }
+
+       /* calculate basic unsnapped multi-paste offset */
+       framecnt_t offset = paste_count * duration;
+
+       /* snap offset so pos + offset is aligned to the grid */
+       framepos_t offset_pos = pos + offset;
+       snap_to(offset_pos, RoundUpMaybe);
+       offset = offset_pos - pos;
+
+       return offset;
+}
+
 Evoral::MusicalTime
 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
 {
@@ -3684,64 +3901,64 @@ Editor::get_grid_type_as_beats (bool& success, framepos_t position)
 
        switch (_snap_type) {
        case SnapToBeat:
-               return 1.0;
+               return Evoral::MusicalTime(1.0);
                break;
 
        case SnapToBeatDiv128:
-               return 1.0/128.0;
+               return Evoral::MusicalTime(1.0/128.0);
                break;
        case SnapToBeatDiv64:
-               return 1.0/64.0;
+               return Evoral::MusicalTime(1.0/64.0);
                break;
        case SnapToBeatDiv32:
-               return 1.0/32.0;
+               return Evoral::MusicalTime(1.0/32.0);
                break;
        case SnapToBeatDiv28:
-               return 1.0/28.0;
+               return Evoral::MusicalTime(1.0/28.0);
                break;
        case SnapToBeatDiv24:
-               return 1.0/24.0;
+               return Evoral::MusicalTime(1.0/24.0);
                break;
        case SnapToBeatDiv20:
-               return 1.0/20.0;
+               return Evoral::MusicalTime(1.0/20.0);
                break;
        case SnapToBeatDiv16:
-               return 1.0/16.0;
+               return Evoral::MusicalTime(1.0/16.0);
                break;
        case SnapToBeatDiv14:
-               return 1.0/14.0;
+               return Evoral::MusicalTime(1.0/14.0);
                break;
        case SnapToBeatDiv12:
-               return 1.0/12.0;
+               return Evoral::MusicalTime(1.0/12.0);
                break;
        case SnapToBeatDiv10:
-               return 1.0/10.0;
+               return Evoral::MusicalTime(1.0/10.0);
                break;
        case SnapToBeatDiv8:
-               return 1.0/8.0;
+               return Evoral::MusicalTime(1.0/8.0);
                break;
        case SnapToBeatDiv7:
-               return 1.0/7.0;
+               return Evoral::MusicalTime(1.0/7.0);
                break;
        case SnapToBeatDiv6:
-               return 1.0/6.0;
+               return Evoral::MusicalTime(1.0/6.0);
                break;
        case SnapToBeatDiv5:
-               return 1.0/5.0;
+               return Evoral::MusicalTime(1.0/5.0);
                break;
        case SnapToBeatDiv4:
-               return 1.0/4.0;
+               return Evoral::MusicalTime(1.0/4.0);
                break;
        case SnapToBeatDiv3:
-               return 1.0/3.0;
+               return Evoral::MusicalTime(1.0/3.0);
                break;
        case SnapToBeatDiv2:
-               return 1.0/2.0;
+               return Evoral::MusicalTime(1.0/2.0);
                break;
 
        case SnapToBar:
                if (_session) {
-                       return _session->tempo_map().meter_at (position).divisions_per_bar();
+                       return Evoral::MusicalTime(_session->tempo_map().meter_at (position).divisions_per_bar());
                }
                break;
 
@@ -3760,7 +3977,7 @@ Editor::get_grid_type_as_beats (bool& success, framepos_t position)
                break;
        }
 
-       return 0.0;
+       return Evoral::MusicalTime();
 }
 
 framecnt_t
@@ -3891,6 +4108,14 @@ Editor::update_tearoff_visibility()
        }
 }
 
+void
+Editor::reattach_all_tearoffs ()
+{
+       if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
+       if (_tools_tearoff) _tools_tearoff->put_it_back ();
+       if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
+}
+
 void
 Editor::maximise_editing_space ()
 {
@@ -4015,8 +4240,6 @@ Editor::reset_y_origin (double y)
 void
 Editor::reset_zoom (framecnt_t spp)
 {
-       clamp_samples_per_pixel (spp);
-
        if (spp == samples_per_pixel) {
                return;
        }
@@ -4076,7 +4299,9 @@ Editor::undo_visual_state ()
 
        redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
 
-       use_visual_state (*vs);
+       if (vs) {
+               use_visual_state (*vs);
+       }
 }
 
 void
@@ -4089,9 +4314,13 @@ Editor::redo_visual_state ()
        VisualState* vs = redo_visual_stack.back();
        redo_visual_stack.pop_back();
 
-       undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
+       // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
+       // why do we check here?
+       undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
 
-       use_visual_state (*vs);
+       if (vs) {
+               use_visual_state (*vs);
+       }
 }
 
 void
@@ -4108,8 +4337,7 @@ void
 Editor::use_visual_state (VisualState& vs)
 {
        PBD::Unwinder<bool> nsv (no_save_visual, true);
-
-       _routes->suspend_redisplay ();
+       DisplaySuspender ds;
 
        vertical_adjustment.set_value (vs.y_position);
 
@@ -4125,29 +4353,34 @@ Editor::use_visual_state (VisualState& vs)
        }
 
        _routes->update_visibility ();
-       _routes->resume_redisplay ();
 }
 
 /** This is the core function that controls the zoom level of the canvas. It is called
  *  whenever one or more calls are made to reset_zoom().  It executes in an idle handler.
- *  @param fpu New frames per unit; should already have been clamped so that it is sensible.
+ *  @param spp new number of samples per pixel
  */
 void
 Editor::set_samples_per_pixel (framecnt_t spp)
 {
-       clamp_samples_per_pixel (spp);
-       samples_per_pixel = spp;
-
-       if (tempo_lines) {
-               tempo_lines->tempo_map_changed();
+       if (spp < 1) {
+               return;
        }
 
-       /* convert fpu to frame count */
+       const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
+       const framecnt_t lots_of_pixels = 4000;
 
-       framepos_t frames = samples_per_pixel * _visible_canvas_width;
+       /* if the zoom level is greater than what you'd get trying to display 3
+        * days of audio on a really big screen, then it's too big.
+        */
+
+       if (spp * lots_of_pixels > three_days) {
+               return;
+       }
+
+       samples_per_pixel = spp;
 
-       if (samples_per_pixel != zoom_range_clock->current_duration()) {
-               zoom_range_clock->set (frames);
+       if (tempo_lines) {
+               tempo_lines->tempo_map_changed();
        }
 
        bool const showing_time_selection = selection->time.length() > 0;
@@ -4196,7 +4429,8 @@ void
 Editor::ensure_visual_change_idle_handler ()
 {
        if (pending_visual_change.idle_handler_id < 0) {
-               pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
+               // see comment in add_to_idle_resize above.
+               pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
                pending_visual_change.being_handled = false;
        }
 }
@@ -4297,6 +4531,10 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
        framepos_t where = 0;
        EditPoint ep = _edit_point;
 
+       if(Profile->get_mixbus())
+               if (ep == EditAtSelectedMarker)
+                       ep=EditAtPlayhead;
+               
        if (from_context_menu && (ep == EditAtMouse)) {
                return  canvas_event_sample (&context_click_event, 0, 0);
        }
@@ -4478,22 +4716,14 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie
 
 /** Get regions using the following method:
  *
- *  Make a region list using the selected regions, unless
- *  the edit point is `mouse' and the mouse is over an unselected
- *  region.  In this case, use just that region.
+ *  Make a region list using:
+ *   (a) any selected regions
+ *   (b) the intersection of any selected tracks and the edit point(*)
+ *   (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
  *
- *  If the edit point is not 'mouse', and there are no regions selected,
- *  search the list of selected tracks and return regions that are under
- *  the edit point on these tracks. If there are no selected tracks and
- *  'No Selection = All Tracks' is active, search all tracks,
+ *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
  *
- *  The rationale here is that the mouse edit point is special in that
- *  its position describes both a time and a track; the other edit
- *  modes only describe a time.  Hence if the edit point is `mouse' we
- *  ignore selected tracks, as we assume the user means something by
- *  pointing at a particular track.  Also in this case we take note of
- *  the region directly under the edit point, as there is always just one
- *  (rather than possibly several with non-mouse edit points).
+ *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
  */
 
 RegionSelection
@@ -4501,23 +4731,15 @@ Editor::get_regions_from_selection_and_edit_point ()
 {
        RegionSelection regions;
 
-       if (_edit_point == EditAtMouse && entered_regionview && !selection->regions.contains (entered_regionview)) {
+       if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
                regions.add (entered_regionview);
        } else {
                regions = selection->regions;
        }
 
-
-       if (regions.empty() && _edit_point != EditAtMouse) {
+       if ( regions.empty() ) {
                TrackViewList tracks = selection->tracks;
 
-               if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
-                       /* tracks is empty (no track selected), and 'No Selection = All Tracks'
-                        * is enabled, so consider all tracks
-                        */
-                       tracks = track_views; 
-               }
-
                if (!tracks.empty()) {
                        /* no region selected or entered, but some selected tracks:
                         * act on all regions on the selected tracks at the edit point
@@ -4526,6 +4748,43 @@ Editor::get_regions_from_selection_and_edit_point ()
                        get_regions_at(regions, where, tracks);
                }
        }
+
+       return regions;
+}
+
+/** Get regions using the following method:
+ *
+ *  Make a region list using:
+ *   (a) any selected regions
+ *   (b) the intersection of any selected tracks and the edit point(*)
+ *   (c) if neither exists, then whatever region is under the mouse
+ *
+ *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
+ *
+ *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
+ */
+RegionSelection
+Editor::get_regions_from_selection_and_mouse (framepos_t pos)
+{
+       RegionSelection regions;
+
+       if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
+               regions.add (entered_regionview);
+       } else {
+               regions = selection->regions;
+       }
+
+       if ( regions.empty() ) {
+               TrackViewList tracks = selection->tracks;
+
+               if (!tracks.empty()) {
+                       /* no region selected or entered, but some selected tracks:
+                        * act on all regions on the selected tracks at the edit point
+                        */ 
+                       get_regions_at(regions, pos, tracks);
+               }
+       }
+
        return regions;
 }
 
@@ -4631,7 +4890,11 @@ void
 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
 {
        if (resize_idle_id < 0) {
-               resize_idle_id = g_idle_add (_idle_resize, this);
+               /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
+                * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
+                * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
+                */
+               resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
                _pending_resize_amount = 0;
        }
 
@@ -4703,13 +4966,13 @@ Editor::located ()
 void
 Editor::region_view_added (RegionView *)
 {
-       _summary->set_dirty ();
+       _summary->set_background_dirty ();
 }
 
 void
 Editor::region_view_removed ()
 {
-       _summary->set_dirty ();
+       _summary->set_background_dirty ();
 }
 
 RouteTimeAxisView*
@@ -4743,6 +5006,22 @@ Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
        return t;
 }
 
+void
+Editor::suspend_route_redisplay ()
+{
+       if (_routes) {
+               _routes->suspend_redisplay();
+       }
+}
+
+void
+Editor::resume_route_redisplay ()
+{
+       if (_routes) {
+               _routes->resume_redisplay();
+       }
+}
+
 void
 Editor::add_routes (RouteList& routes)
 {
@@ -4800,6 +5079,10 @@ Editor::add_routes (RouteList& routes)
 void
 Editor::timeaxisview_deleted (TimeAxisView *tv)
 {
+       if (tv == entered_track) {
+               entered_track = 0;
+       }
+
        if (_session && _session->deletion_in_progress()) {
                /* the situation is under control */
                return;
@@ -4811,10 +5094,6 @@ Editor::timeaxisview_deleted (TimeAxisView *tv)
 
        _routes->route_removed (tv);
 
-       if (tv == entered_track) {
-               entered_track = 0;
-       }
-
        TimeAxisView::Children c = tv->get_child_list ();
        for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
                if (entered_track == i->get()) {
@@ -5038,11 +5317,11 @@ Editor::scroll_press (Direction dir)
                break;
 
        case UP:
-               scroll_tracks_up_line ();
+               scroll_up_one_track ();
                break;
 
        case DOWN:
-               scroll_tracks_down_line ();
+               scroll_down_one_track ();
                break;
        }
 
@@ -5246,7 +5525,6 @@ Editor::session_going_away ()
        }
        track_views.clear ();
 
-       zoom_range_clock->set_session (0);
        nudge_clock->set_session (0);
 
        editor_list_button.set_active(false);
@@ -5428,6 +5706,13 @@ void
 Editor::ui_parameter_changed (string parameter)
 {
        if (parameter == "icon-set") {
+               while (!_cursor_stack.empty()) {
+                       _cursor_stack.pop();
+               }
                _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
+       } else if (parameter == "draggable-playhead") {
+               if (_verbose_cursor) {
+                       playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());
+               }
        }
 }