Trim session.h include dependency tree.
[ardour.git] / gtk2_ardour / editor.cc
index f1da5c6dcf4400c2785d043ead2dc262ea34a78a..60d6c9a3a4c18ffc10db70eb30169e81d359cda0 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
-    Copyright (C) 2000-2009 Paul Davis 
+    Copyright (C) 2000-2009 Paul Davis
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -129,9 +129,9 @@ const double Editor::timebar_height = 15.0;
 
 static const gchar *_snap_type_strings[] = {
        N_("CD Frames"),
 
 static const gchar *_snap_type_strings[] = {
        N_("CD Frames"),
-       N_("SMPTE Frames"),
-       N_("SMPTE Seconds"),
-       N_("SMPTE Minutes"),
+       N_("Timecode Frames"),
+       N_("Timecode Seconds"),
+       N_("Timecode Minutes"),
        N_("Seconds"),
        N_("Minutes"),
        N_("Beats/32"),
        N_("Seconds"),
        N_("Minutes"),
        N_("Beats/32"),
@@ -211,50 +211,47 @@ show_me_the_size (Requisition* r, const char* what)
 }
 
 Editor::Editor ()
 }
 
 Editor::Editor ()
-       : 
          /* time display buttons */
          /* time display buttons */
-
-         minsec_label (_("Mins:Secs")),
-         bbt_label (_("Bars:Beats")),
-         smpte_label (_("Timecode")),
-         frame_label (_("Samples")),
-         tempo_label (_("Tempo")),
-         meter_label (_("Meter")),
-         mark_label (_("Location Markers")),
-         range_mark_label (_("Range Markers")),
-         transport_mark_label (_("Loop/Punch Ranges")),
-         cd_mark_label (_("CD Markers")),
-         edit_packer (4, 4, true),
+       : minsec_label (_("Mins:Secs"))
+       , bbt_label (_("Bars:Beats"))
+       , timecode_label (_("Timecode"))
+       , frame_label (_("Samples"))
+       , tempo_label (_("Tempo"))
+       , meter_label (_("Meter"))
+       , mark_label (_("Location Markers"))
+       , range_mark_label (_("Range Markers"))
+       , transport_mark_label (_("Loop/Punch Ranges"))
+       , cd_mark_label (_("CD Markers"))
+       , edit_packer (4, 4, true)
 
          /* the values here don't matter: layout widgets
             reset them as needed.
          */
 
 
          /* the values here don't matter: layout widgets
             reset them as needed.
          */
 
-         vertical_adjustment (0.0, 0.0, 10.0, 400.0),
-         horizontal_adjustment (0.0, 0.0, 20.0, 1200.0),
+       , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
+       , horizontal_adjustment (0.0, 0.0, 20.0, 1200.0)
 
          /* tool bar related */
 
 
          /* tool bar related */
 
-         edit_point_clock (X_("editpoint"), false, X_("EditPointClock"), true),
-         zoom_range_clock (X_("zoomrange"), false, X_("ZoomRangeClock"), true, true),
-         
-         toolbar_selection_clock_table (2,3),
-         
-         automation_mode_button (_("mode")),
-         global_automation_button (_("automation")),
+       , edit_point_clock (X_("editpoint"), false, X_("EditPointClock"), true)
+       , zoom_range_clock (X_("zoomrange"), false, X_("ZoomRangeClock"), true, true)
+
+       , toolbar_selection_clock_table (2,3)
 
 
-         midi_panic_button (_("Panic")),
-         midi_tools_tearoff (0),
+       , automation_mode_button (_("mode"))
+       , global_automation_button (_("automation"))
+
+       , midi_panic_button (_("Panic"))
 
 #ifdef WITH_CMT
 
 #ifdef WITH_CMT
-         image_socket_listener(0),
+       , image_socket_listener(0)
 #endif
 
          /* nudge */
 
 #endif
 
          /* nudge */
 
-         nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true),
-         meters_running(false),
-         _pending_locate_request (false)
+       , nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true)
+       , meters_running(false)
+       , _pending_locate_request (false)
 
 {
        constructed = false;
 
 {
        constructed = false;
@@ -279,7 +276,7 @@ Editor::Editor ()
        current_mixer_strip = 0;
        current_bbt_points = 0;
        tempo_lines = 0;
        current_mixer_strip = 0;
        current_bbt_points = 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);
        snap_type_strings =  I18N (_snap_type_strings);
        snap_mode_strings =  I18N (_snap_mode_strings);
        zoom_focus_strings = I18N (_zoom_focus_strings);
@@ -287,7 +284,7 @@ Editor::Editor ()
 #ifdef USE_RUBBERBAND
        rb_opt_strings = I18N (_rb_opt_strings);
 #endif
 #ifdef USE_RUBBERBAND
        rb_opt_strings = I18N (_rb_opt_strings);
 #endif
-       
+
        snap_threshold = 5.0;
        bbt_beat_subdivision = 4;
        _canvas_width = 0;
        snap_threshold = 5.0;
        bbt_beat_subdivision = 4;
        _canvas_width = 0;
@@ -328,8 +325,6 @@ Editor::Editor ()
        region_edit_menu_split_item = 0;
        temp_location = 0;
        leftmost_frame = 0;
        region_edit_menu_split_item = 0;
        temp_location = 0;
        leftmost_frame = 0;
-       ignore_mouse_mode_toggle = false;
-       ignore_midi_edit_mode_toggle = false;
        current_stepping_trackview = 0;
        entered_track = 0;
        entered_regionview = 0;
        current_stepping_trackview = 0;
        entered_track = 0;
        entered_regionview = 0;
@@ -343,7 +338,6 @@ Editor::Editor ()
        _dragging_edit_point = false;
        _dragging_hscrollbar = false;
        select_new_marker = false;
        _dragging_edit_point = false;
        _dragging_hscrollbar = false;
        select_new_marker = false;
-       zoomed_to_region = false;
        rhythm_ferret = 0;
        _bundle_manager = 0;
        for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
        rhythm_ferret = 0;
        _bundle_manager = 0;
        for (ARDOUR::DataType::iterator i = ARDOUR::DataType::begin(); i != ARDOUR::DataType::end(); ++i) {
@@ -363,13 +357,13 @@ Editor::Editor ()
        location_loop_color = ARDOUR_UI::config()->canvasvar_LocationLoop.get();
        location_punch_color = ARDOUR_UI::config()->canvasvar_LocationPunch.get();
 
        location_loop_color = ARDOUR_UI::config()->canvasvar_LocationLoop.get();
        location_punch_color = ARDOUR_UI::config()->canvasvar_LocationPunch.get();
 
-       set_midi_edit_mode (MidiEditPencil, true);
        _edit_point = EditAtMouse;
        _edit_point = EditAtMouse;
-       set_mouse_mode (MouseObject, true);
+       _internal_editing = false;
+       current_canvas_cursor = 0;
 
        frames_per_unit = 2048; /* too early to use reset_zoom () */
        reset_hscrollbar_stepping ();
 
        frames_per_unit = 2048; /* too early to use reset_zoom () */
        reset_hscrollbar_stepping ();
-       
+
        zoom_focus = ZoomFocusLeft;
        set_zoom_focus (ZoomFocusLeft);
        zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
        zoom_focus = ZoomFocusLeft;
        set_zoom_focus (ZoomFocusLeft);
        zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
@@ -386,12 +380,12 @@ Editor::Editor ()
        minsec_label.set_padding (5,0);
        minsec_label.hide ();
        minsec_label.set_no_show_all();
        minsec_label.set_padding (5,0);
        minsec_label.hide ();
        minsec_label.set_no_show_all();
-       smpte_label.set_name ("EditorTimeButton");
-       smpte_label.set_size_request (-1, (int)timebar_height);
-       smpte_label.set_alignment (1.0, 0.5);
-       smpte_label.set_padding (5,0);
-       smpte_label.hide ();
-       smpte_label.set_no_show_all();
+       timecode_label.set_name ("EditorTimeButton");
+       timecode_label.set_size_request (-1, (int)timebar_height);
+       timecode_label.set_alignment (1.0, 0.5);
+       timecode_label.set_padding (5,0);
+       timecode_label.hide ();
+       timecode_label.set_no_show_all();
        frame_label.set_name ("EditorTimeButton");
        frame_label.set_size_request (-1, (int)timebar_height);
        frame_label.set_alignment (1.0, 0.5);
        frame_label.set_name ("EditorTimeButton");
        frame_label.set_size_request (-1, (int)timebar_height);
        frame_label.set_alignment (1.0, 0.5);
@@ -456,11 +450,11 @@ Editor::Editor ()
        h->pack_start (*_group_tabs, PACK_SHRINK);
        h->pack_start (edit_controls_vbox);
        controls_layout.add (*h);
        h->pack_start (*_group_tabs, PACK_SHRINK);
        h->pack_start (edit_controls_vbox);
        controls_layout.add (*h);
-       
+
        controls_layout.set_name ("EditControlsBase");
        controls_layout.add_events (Gdk::SCROLL_MASK);
        controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false);
        controls_layout.set_name ("EditControlsBase");
        controls_layout.add_events (Gdk::SCROLL_MASK);
        controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false);
-       
+
        controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
        controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
        controls_layout_size_request_connection = controls_layout.signal_size_request().connect (mem_fun (*this, &Editor::controls_layout_size_request));
        controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
        controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
        controls_layout_size_request_connection = controls_layout.signal_size_request().connect (mem_fun (*this, &Editor::controls_layout_size_request));
@@ -475,11 +469,9 @@ Editor::Editor ()
        edit_hscrollbar.set_name ("EditorHScrollbar");
 
        build_cursors ();
        edit_hscrollbar.set_name ("EditorHScrollbar");
 
        build_cursors ();
-       setup_toolbar ();
-       setup_midi_toolbar ();
 
        edit_point_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_point_clock_changed));
 
        edit_point_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_point_clock_changed));
-       
+
        ArdourCanvas::Canvas* time_pad = manage(new ArdourCanvas::Canvas());
        ArdourCanvas::SimpleLine* pad_line_1 = manage(new ArdourCanvas::SimpleLine(*time_pad->root(),
                        0.0, 1.0, 100.0, 1.0));
        ArdourCanvas::Canvas* time_pad = manage(new ArdourCanvas::Canvas());
        ArdourCanvas::SimpleLine* pad_line_1 = manage(new ArdourCanvas::SimpleLine(*time_pad->root(),
                        0.0, 1.0, 100.0, 1.0));
@@ -490,7 +482,7 @@ Editor::Editor ()
        time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2);
        time_canvas_vbox.set_size_request (-1, -1);
 
        time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2);
        time_canvas_vbox.set_size_request (-1, -1);
 
-       ruler_label_event_box.add (ruler_label_vbox);   
+       ruler_label_event_box.add (ruler_label_vbox);
        ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
        ruler_label_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
        ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
        ruler_label_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
@@ -498,7 +490,7 @@ Editor::Editor ()
        time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
        time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
        time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
        time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
 
-       /* these enable us to have a dedicated window (for cursor setting, etc.) 
+       /* these enable us to have a dedicated window (for cursor setting, etc.)
           for the canvas areas.
        */
 
           for the canvas areas.
        */
 
@@ -542,7 +534,7 @@ Editor::Editor ()
        named_selection_display.set_headers_visible (false);
        named_selection_display.set_size_request (100, -1);
        named_selection_display.set_name ("NamedSelectionDisplay");
        named_selection_display.set_headers_visible (false);
        named_selection_display.set_size_request (100, -1);
        named_selection_display.set_name ("NamedSelectionDisplay");
-       
+
        named_selection_display.get_selection()->set_mode (SELECTION_SINGLE);
        named_selection_display.set_size_request (100, -1);
        named_selection_display.signal_button_release_event().connect (mem_fun(*this, &Editor::named_selection_display_button_release), false);
        named_selection_display.get_selection()->set_mode (SELECTION_SINGLE);
        named_selection_display.set_size_request (100, -1);
        named_selection_display.signal_button_release_event().connect (mem_fun(*this, &Editor::named_selection_display_button_release), false);
@@ -563,7 +555,7 @@ Editor::Editor ()
        nlabel = manage (new Label (_("Route Groups")));
        nlabel->set_angle (-90);
        the_notebook.append_page (_route_groups->widget (), *nlabel);
        nlabel = manage (new Label (_("Route Groups")));
        nlabel->set_angle (-90);
        the_notebook.append_page (_route_groups->widget (), *nlabel);
-       
+
        if (!Profile->get_sae()) {
                nlabel = manage (new Label (_("Chunks")));
                nlabel->set_angle (-90);
        if (!Profile->get_sae()) {
                nlabel = manage (new Label (_("Chunks")));
                nlabel->set_angle (-90);
@@ -585,11 +577,10 @@ Editor::Editor ()
 
        edit_pane.pack1 (*editor_summary_pane, true, true);
        edit_pane.pack2 (the_notebook, false, true);
 
        edit_pane.pack1 (*editor_summary_pane, true, true);
        edit_pane.pack2 (the_notebook, false, true);
-       
+
        edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
 
        top_hbox.pack_start (toolbar_frame, false, true);
        edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
 
        top_hbox.pack_start (toolbar_frame, false, true);
-       top_hbox.pack_start (midi_toolbar_frame, false, true);
 
        HBox *hbox = manage (new HBox);
        hbox->pack_start (edit_pane, true, true);
 
        HBox *hbox = manage (new HBox);
        hbox->pack_start (edit_pane, true, true);
@@ -608,17 +599,21 @@ Editor::Editor ()
        vpacker.pack_end (global_hpacker, true, true);
 
        /* register actions now so that set_state() can find them and set toggles/checks etc */
        vpacker.pack_end (global_hpacker, true, true);
 
        /* register actions now so that set_state() can find them and set toggles/checks etc */
-       
+
        register_actions ();
 
        register_actions ();
 
-       snap_type = SnapToBeat;
-       set_snap_to (snap_type);
-       snap_mode = SnapOff;
-       set_snap_mode (snap_mode);
+       setup_toolbar ();
+       setup_midi_toolbar ();
+
+       _snap_type = SnapToBeat;
+       set_snap_to (_snap_type);
+       _snap_mode = SnapOff;
+       set_snap_mode (_snap_mode);
+       set_mouse_mode (MouseObject, true);
        set_edit_point_preference (EditAtMouse, true);
 
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
        set_edit_point_preference (EditAtMouse, true);
 
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
-       set_state (*node);
+       set_state (*node, Stateful::loading_state_version);
 
        _playlist_selector = new PlaylistSelector();
        _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
 
        _playlist_selector = new PlaylistSelector();
        _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
@@ -695,7 +690,7 @@ Editor::~Editor()
                {
                        image_socket_listener->close_connection() ;
                }
                {
                        image_socket_listener->close_connection() ;
                }
-               
+
                delete image_socket_listener ;
                image_socket_listener = 0 ;
        }
                delete image_socket_listener ;
                image_socket_listener = 0 ;
        }
@@ -783,7 +778,7 @@ Editor::show_window ()
                */
 
                TimeAxisView *tv;
                */
 
                TimeAxisView *tv;
-       
+
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        tv = (static_cast<TimeAxisView*>(*i));
                        tv->reset_height ();
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        tv = (static_cast<TimeAxisView*>(*i));
                        tv->reset_height ();
@@ -844,7 +839,7 @@ Editor::zoom_adjustment_changed ()
                fpu = session->current_end_frame() / _canvas_width;
                zoom_range_clock.set ((nframes64_t) floor (fpu * _canvas_width));
        }
                fpu = session->current_end_frame() / _canvas_width;
                zoom_range_clock.set ((nframes64_t) floor (fpu * _canvas_width));
        }
-       
+
        temporal_zoom (fpu);
 }
 
        temporal_zoom (fpu);
 }
 
@@ -861,7 +856,7 @@ Editor::control_scroll (float fraction)
 
        /*
                _control_scroll_target is an optional<T>
 
        /*
                _control_scroll_target is an optional<T>
-       
+
                it acts like a pointer to an nframes64_t, with
                a operator conversion to boolean to check
                that it has a value could possibly use
                it acts like a pointer to an nframes64_t, with
                a operator conversion to boolean to check
                that it has a value could possibly use
@@ -887,7 +882,7 @@ Editor::control_scroll (float fraction)
 
        playhead_cursor->set_position (*_control_scroll_target);
        UpdateAllTransportClocks (*_control_scroll_target);
 
        playhead_cursor->set_position (*_control_scroll_target);
        UpdateAllTransportClocks (*_control_scroll_target);
-       
+
        if (*_control_scroll_target > (current_page_frames() / 2)) {
                /* try to center PH in window */
                reset_x_origin (*_control_scroll_target - (current_page_frames()/2));
        if (*_control_scroll_target > (current_page_frames() / 2)) {
                /* try to center PH in window */
                reset_x_origin (*_control_scroll_target - (current_page_frames()/2));
@@ -935,7 +930,7 @@ Editor::access_action (std::string action_group, std::string action_item)
        if (act) {
                act->activate();
        }
        if (act) {
                act->activate();
        }
-               
+
 
 }
 
 
 }
 
@@ -949,7 +944,7 @@ Editor::on_realize ()
 void
 Editor::start_scrolling ()
 {
 void
 Editor::start_scrolling ()
 {
-       scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect 
+       scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
                (mem_fun(*this, &Editor::update_current_screen));
 
 }
                (mem_fun(*this, &Editor::update_current_screen));
 
 }
@@ -971,7 +966,7 @@ Editor::map_position_change (nframes64_t frame)
 
        center_screen (frame);
        playhead_cursor->set_position (frame);
 
        center_screen (frame);
        playhead_cursor->set_position (frame);
-}      
+}
 
 void
 Editor::center_screen (nframes64_t frame)
 
 void
 Editor::center_screen (nframes64_t frame)
@@ -980,7 +975,7 @@ Editor::center_screen (nframes64_t frame)
 
        /* if we're off the page, then scroll.
         */
 
        /* if we're off the page, then scroll.
         */
-       
+
        if (frame < leftmost_frame || frame >= leftmost_frame + page) {
                center_screen_internal (frame, page);
        }
        if (frame < leftmost_frame || frame >= leftmost_frame + page) {
                center_screen_internal (frame, page);
        }
@@ -990,7 +985,7 @@ void
 Editor::center_screen_internal (nframes64_t frame, float page)
 {
        page /= 2;
 Editor::center_screen_internal (nframes64_t frame, float page)
 {
        page /= 2;
-               
+
        if (frame > page) {
                frame -= (nframes64_t) page;
        } else {
        if (frame > page) {
                frame -= (nframes64_t) page;
        } else {
@@ -1023,7 +1018,7 @@ void
 Editor::update_title_s (const string & snap_name)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
 Editor::update_title_s (const string & snap_name)
 {
        ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
-       
+
        update_title ();
 }
 
        update_title ();
 }
 
@@ -1065,7 +1060,7 @@ Editor::connect_to_session (Session *t)
        sensitize_the_right_region_actions (false);
 
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
        sensitize_the_right_region_actions (false);
 
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
-       set_state (*node);
+       set_state (*node, Stateful::loading_state_version);
 
        /* catch up with the playhead */
 
 
        /* catch up with the playhead */
 
@@ -1091,7 +1086,7 @@ Editor::connect_to_session (Session *t)
        session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
        session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
 
        session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
        session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
 
-       session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
+       session_connections.push_back (session->TimecodeOffsetChanged.connect (mem_fun(*this, &Editor::update_just_timecode)));
 
        session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
 
 
        session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
 
@@ -1111,9 +1106,9 @@ Editor::connect_to_session (Session *t)
                nframes_t pos = session->tempo_map().bbt_duration_at (0, bbt, 1);
                nudge_clock.set_mode(AudioClock::BBT);
                nudge_clock.set (pos, true, 0, AudioClock::BBT);
                nframes_t pos = session->tempo_map().bbt_duration_at (0, bbt, 1);
                nudge_clock.set_mode(AudioClock::BBT);
                nudge_clock.set (pos, true, 0, AudioClock::BBT);
-               
+
        } else {
        } else {
-               nudge_clock.set (session->frame_rate() * 5, true, 0, AudioClock::SMPTE); // default of 5 seconds
+               nudge_clock.set (session->frame_rate() * 5, true, 0, AudioClock::Timecode); // default of 5 seconds
        }
 
        playhead_cursor->canvas_item.show ();
        }
 
        playhead_cursor->canvas_item.show ();
@@ -1137,7 +1132,7 @@ Editor::connect_to_session (Session *t)
                // force name
                loc->set_name (_("Loop"));
        }
                // force name
                loc->set_name (_("Loop"));
        }
-       
+
        loc = session->locations()->auto_punch_location();
        if (loc == 0) {
                loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
        loc = session->locations()->auto_punch_location();
        if (loc == 0) {
                loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
@@ -1153,9 +1148,9 @@ Editor::connect_to_session (Session *t)
 
        Config->map_parameters (mem_fun (*this, &Editor::parameter_changed));
        session->config.map_parameters (mem_fun (*this, &Editor::parameter_changed));
 
        Config->map_parameters (mem_fun (*this, &Editor::parameter_changed));
        session->config.map_parameters (mem_fun (*this, &Editor::parameter_changed));
-       
+
        session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved));
        session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved));
-       
+
        refresh_location_display ();
        session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
        session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
        refresh_location_display ();
        session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
        session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
@@ -1181,7 +1176,7 @@ Editor::connect_to_session (Session *t)
 
        start_scrolling ();
 
 
        start_scrolling ();
 
-       switch (snap_type) {
+       switch (_snap_type) {
        case SnapToRegionStart:
        case SnapToRegionEnd:
        case SnapToRegionSync:
        case SnapToRegionStart:
        case SnapToRegionEnd:
        case SnapToRegionSync:
@@ -1202,7 +1197,7 @@ Editor::connect_to_session (Session *t)
        _regions->connect_to_session (session);
        _snapshots->connect_to_session (session);
        _routes->connect_to_session (session);
        _regions->connect_to_session (session);
        _snapshots->connect_to_session (session);
        _routes->connect_to_session (session);
-       
+
        start_updating ();
 }
 
        start_updating ();
 }
 
@@ -1210,7 +1205,7 @@ void
 Editor::build_cursors ()
 {
        using namespace Gdk;
 Editor::build_cursors ()
 {
        using namespace Gdk;
-       
+
        Gdk::Color mbg ("#000000" ); /* Black */
        Gdk::Color mfg ("#0000ff" ); /* Blue. */
 
        Gdk::Color mbg ("#000000" ); /* Black */
        Gdk::Color mfg ("#0000ff" ); /* Blue. */
 
@@ -1223,23 +1218,23 @@ Editor::build_cursors ()
 
        Gdk::Color fbg ("#ffffff" );
        Gdk::Color ffg  ("#000000" );
 
        Gdk::Color fbg ("#ffffff" );
        Gdk::Color ffg  ("#000000" );
-       
+
        {
                RefPtr<Bitmap> source, mask;
        {
                RefPtr<Bitmap> source, mask;
-               
+
                source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
                mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
                fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
        }
                source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
                mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
                fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
        }
-       
-       { 
+
+       {
                RefPtr<Bitmap> source, mask;
                source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
                mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
                speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
        }
                RefPtr<Bitmap> source, mask;
                source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
                mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
                speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
        }
-       
-       { 
+
+       {
                RefPtr<Bitmap> bits;
                char pix[4] = { 0, 0, 0, 0 };
                bits = Bitmap::create (pix, 2, 2);
                RefPtr<Bitmap> bits;
                char pix[4] = { 0, 0, 0, 0 };
                bits = Bitmap::create (pix, 2, 2);
@@ -1247,17 +1242,17 @@ Editor::build_cursors ()
                transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
        }
 
                transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
        }
 
-       { 
+       {
                RefPtr<Bitmap> bits;
                char pix[4] = { 0, 0, 0, 0 };
                bits = Bitmap::create (pix, 2, 2);
                Gdk::Color c;
                transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
        }
                RefPtr<Bitmap> bits;
                char pix[4] = { 0, 0, 0, 0 };
                bits = Bitmap::create (pix, 2, 2);
                Gdk::Color c;
                transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
        }
-       
+
 
        grabber_cursor = new Gdk::Cursor (HAND2);
 
        grabber_cursor = new Gdk::Cursor (HAND2);
-       
+
        {
                Glib::RefPtr<Gdk::Pixbuf> grabber_edit_point_pixbuf (::get_icon ("grabber_edit_point"));
                grabber_edit_point_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_edit_point_pixbuf, 5, 17);
        {
                Glib::RefPtr<Gdk::Pixbuf> grabber_edit_point_pixbuf (::get_icon ("grabber_edit_point"));
                grabber_edit_point_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_edit_point_pixbuf, 5, 17);
@@ -1299,7 +1294,7 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
                } else {
                        items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_in_active), true)));
                }
                } else {
                        items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_in_active), true)));
                }
-               
+
                items.push_back (SeparatorElem());
 
                if (Profile->get_sae()) {
                items.push_back (SeparatorElem());
 
                if (Profile->get_sae()) {
@@ -1322,9 +1317,9 @@ Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* i
                } else {
                        items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_out_active), true)));
                }
                } else {
                        items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_out_active), true)));
                }
-               
+
                items.push_back (SeparatorElem());
                items.push_back (SeparatorElem());
-               
+
                if (Profile->get_sae()) {
                        items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
                        items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
                if (Profile->get_sae()) {
                        items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
                        items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
@@ -1393,7 +1388,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
 
        menu = (this->*build_menu_function)(frame);
        menu->set_name ("ArdourContextMenu");
 
        menu = (this->*build_menu_function)(frame);
        menu->set_name ("ArdourContextMenu");
-       
+
        /* now handle specific situations */
 
        switch (item_type) {
        /* now handle specific situations */
 
        switch (item_type) {
@@ -1438,10 +1433,10 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
        if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
 
                /* Bounce to disk */
        if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
 
                /* Bounce to disk */
-               
+
                using namespace Menu_Helpers;
                MenuList& edit_items  = menu->items();
                using namespace Menu_Helpers;
                MenuList& edit_items  = menu->items();
-               
+
                edit_items.push_back (SeparatorElem());
 
                switch (clicked_routeview->audio_track()->freeze_state()) {
                edit_items.push_back (SeparatorElem());
 
                switch (clicked_routeview->audio_track()->freeze_state()) {
@@ -1452,7 +1447,7 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
                case AudioTrack::Frozen:
                        edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
                        break;
                case AudioTrack::Frozen:
                        edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
                        break;
-                       
+
                case AudioTrack::UnFrozen:
                        edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
                        break;
                case AudioTrack::UnFrozen:
                        edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
                        break;
@@ -1503,16 +1498,16 @@ Editor::build_track_region_context_menu (nframes64_t frame)
        if (rtv) {
                boost::shared_ptr<Diskstream> ds;
                boost::shared_ptr<Playlist> pl;
        if (rtv) {
                boost::shared_ptr<Diskstream> ds;
                boost::shared_ptr<Playlist> pl;
-               
+
                if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
                        Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * ds->speed()));
 
                        if (selection->regions.size() > 1) {
                if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
                        Playlist::RegionList* regions = pl->regions_at ((nframes64_t) floor ( (double)frame * ds->speed()));
 
                        if (selection->regions.size() > 1) {
-                               // there's already a multiple selection: just add a 
-                               // single region context menu that will act on all 
+                               // there's already a multiple selection: just add a
+                               // single region context menu that will act on all
                                // selected regions
                                // selected regions
-                               boost::shared_ptr<Region> dummy_region; // = NULL               
-                               add_region_context_items (rtv->view(), dummy_region, edit_items);                       
+                               boost::shared_ptr<Region> dummy_region; // = NULL
+                               add_region_context_items (rtv->view(), dummy_region, edit_items);
                        } else {
                                for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
                                        add_region_context_items (rtv->view(), (*i), edit_items);
                        } else {
                                for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
                                        add_region_context_items (rtv->view(), (*i), edit_items);
@@ -1556,11 +1551,11 @@ Editor::build_track_crossfade_context_menu (nframes64_t frame)
                        }
 
                        if (selection->regions.size() > 1) {
                        }
 
                        if (selection->regions.size() > 1) {
-                               // there's already a multiple selection: just add a 
-                               // single region context menu that will act on all 
+                               // there's already a multiple selection: just add a
+                               // single region context menu that will act on all
                                // selected regions
                                // selected regions
-                               boost::shared_ptr<Region> dummy_region; // = NULL               
-                               add_region_context_items (atv->audio_view(), dummy_region, edit_items);                 
+                               boost::shared_ptr<Region> dummy_region; // = NULL
+                               add_region_context_items (atv->audio_view(), dummy_region, edit_items);
                        } else {
                                for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
                                        add_region_context_items (atv->audio_view(), (*i), edit_items);
                        } else {
                                for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
                                        add_region_context_items (atv->audio_view(), (*i), edit_items);
@@ -1589,7 +1584,7 @@ Editor::analyze_region_selection()
 
        analysis_window->set_regionmode();
        analysis_window->analyze();
 
        analysis_window->set_regionmode();
        analysis_window->analyze();
-       
+
        analysis_window->present();
 }
 
        analysis_window->present();
 }
 
@@ -1607,7 +1602,7 @@ Editor::analyze_range_selection()
 
        analysis_window->set_rangemode();
        analysis_window->analyze();
 
        analysis_window->set_rangemode();
        analysis_window->analyze();
-       
+
        analysis_window->present();
 }
 
        analysis_window->present();
 }
 
@@ -1639,7 +1634,7 @@ Editor::add_crossfade_context_items (AudioStreamView* /*view*/, boost::shared_pt
 
        if (xfade->active()) {
                str = _("Mute");
 
        if (xfade->active()) {
                str = _("Mute");
-       } else { 
+       } else {
                str = _("Unmute");
        }
 
                str = _("Unmute");
        }
 
@@ -1701,21 +1696,28 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                ar = boost::dynamic_pointer_cast<AudioRegion> (region);
                mr = boost::dynamic_pointer_cast<MidiRegion> (region);
 
                ar = boost::dynamic_pointer_cast<AudioRegion> (region);
                mr = boost::dynamic_pointer_cast<MidiRegion> (region);
 
-               /* when this particular menu pops up, make the relevant region 
+               /* when this particular menu pops up, make the relevant region
                   become selected.
                */
 
                region_menu->signal_map_event().connect (
                        bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
                   become selected.
                */
 
                region_menu->signal_map_event().connect (
                        bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
-               
+
                items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
                items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
-               items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
+               if (mr && internal_editing()) {
+                       items.push_back (MenuElem (_("List editor..."), mem_fun(*this, &Editor::show_midi_list_editor)));
+               } else {
+                       items.push_back (MenuElem (_("Region editor"), mem_fun(*this, &Editor::edit_region)));
+               }
        }
 
        items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
        items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun  (*this, &Editor::lower_region_to_bottom)));
        items.push_back (SeparatorElem());
        items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
        }
 
        items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
        items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun  (*this, &Editor::lower_region_to_bottom)));
        items.push_back (SeparatorElem());
        items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
+       if (_edit_point == EditAtMouse) {
+               items.back ().set_sensitive (false);
+       }
        items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
        items.push_back (SeparatorElem());
 
        items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
        items.push_back (SeparatorElem());
 
@@ -1744,10 +1746,10 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                region_lock_item->set_active();
        }
        region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
                region_lock_item->set_active();
        }
        region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
-       
+
        items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
        CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
        items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
        CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
-       
+
        switch (region_to_check->positional_lock_style()) {
        case Region::MusicTime:
                bbt_glue_item->set_active (true);
        switch (region_to_check->positional_lock_style()) {
        case Region::MusicTime:
                bbt_glue_item->set_active (true);
@@ -1756,9 +1758,9 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                bbt_glue_item->set_active (false);
                break;
        }
                bbt_glue_item->set_active (false);
                break;
        }
-       
+
        bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
        bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
-       
+
        items.push_back (CheckMenuElem (_("Mute")));
        CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
        fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
        items.push_back (CheckMenuElem (_("Mute")));
        CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
        fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
@@ -1767,7 +1769,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                region_mute_item->set_active();
                fooc.block (false);
        }
                region_mute_item->set_active();
                fooc.block (false);
        }
-       
+
        if (!Profile->get_sae()) {
                items.push_back (CheckMenuElem (_("Opaque")));
                CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
        if (!Profile->get_sae()) {
                items.push_back (CheckMenuElem (_("Opaque")));
                CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
@@ -1778,19 +1780,19 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                        fooc.block (false);
                }
        }
                        fooc.block (false);
                }
        }
-       
+
        items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
        if (region_to_check->at_natural_position()) {
                items.back().set_sensitive (false);
        }
        items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
        if (region_to_check->at_natural_position()) {
                items.back().set_sensitive (false);
        }
-       
+
        items.push_back (SeparatorElem());
        items.push_back (SeparatorElem());
-       
+
        if (ar) {
        if (ar) {
-               
+
                RegionView* rv = sv->find_view (ar);
                AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
                RegionView* rv = sv->find_view (ar);
                AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
-               
+
                if (!Profile->get_sae()) {
                        items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
 
                if (!Profile->get_sae()) {
                        items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
 
@@ -1802,11 +1804,11 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                                region_envelope_visible_item->set_active (true);
                                fooc.block (false);
                        }
                                region_envelope_visible_item->set_active (true);
                                fooc.block (false);
                        }
-               
+
                        items.push_back (CheckMenuElem (_("Envelope Active")));
                        CheckMenuItem* region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
                        fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
                        items.push_back (CheckMenuElem (_("Envelope Active")));
                        CheckMenuItem* region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
                        fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
-                       
+
                        if (ar->envelope_active()) {
                                fooc.block (true);
                                region_envelope_active_item->set_active (true);
                        if (ar->envelope_active()) {
                                fooc.block (true);
                                region_envelope_active_item->set_active (true);
@@ -1816,10 +1818,9 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                        items.push_back (SeparatorElem());
                }
 
                        items.push_back (SeparatorElem());
                }
 
-               if (ar->scale_amplitude() != 1.0f) {
-                       items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
-               } else {
-                       items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
+               items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
+               if (ar->scale_amplitude() != 1) {
+                       items.push_back (MenuElem (_("Reset Gain"), mem_fun(*this, &Editor::reset_region_scale_amplitude)));
                }
 
        } else if (mr) {
                }
 
        } else if (mr) {
@@ -1827,7 +1828,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                items.push_back (SeparatorElem());
        }
 
                items.push_back (SeparatorElem());
        }
 
-       items.push_back (MenuElem (_("Strip silence..."), mem_fun (*this, &Editor::strip_region_silence)));
+       items.push_back (MenuElem (_("Strip Silence..."), mem_fun (*this, &Editor::strip_region_silence)));
        items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
        items.push_back (SeparatorElem());
 
        items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
        items.push_back (SeparatorElem());
 
@@ -1841,13 +1842,13 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
 
        items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_region)));
        items.push_back (SeparatorElem());
 
        items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_region)));
        items.push_back (SeparatorElem());
-                        
+
        /* Nudge region */
 
        Menu *nudge_menu = manage (new Menu());
        MenuList& nudge_items = nudge_menu->items();
        nudge_menu->set_name ("ArdourContextMenu");
        /* Nudge region */
 
        Menu *nudge_menu = manage (new Menu());
        MenuList& nudge_items = nudge_menu->items();
        nudge_menu->set_name ("ArdourContextMenu");
-       
+
        nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false, false))));
        nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false, false))));
        nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
        nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false, false))));
        nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false, false))));
        nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
@@ -1859,7 +1860,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
        Menu *trim_menu = manage (new Menu);
        MenuList& trim_items = trim_menu->items();
        trim_menu->set_name ("ArdourContextMenu");
        Menu *trim_menu = manage (new Menu);
        MenuList& trim_items = trim_menu->items();
        trim_menu->set_name ("ArdourContextMenu");
-       
+
        trim_items.push_back (MenuElem (_("Start to edit point"), mem_fun(*this, &Editor::trim_region_from_edit_point)));
        foo_item = &trim_items.back();
        if (_edit_point == EditAtMouse) {
        trim_items.push_back (MenuElem (_("Start to edit point"), mem_fun(*this, &Editor::trim_region_from_edit_point)));
        foo_item = &trim_items.back();
        if (_edit_point == EditAtMouse) {
@@ -1872,13 +1873,13 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
        }
        trim_items.push_back (MenuElem (_("Trim To Loop"), mem_fun(*this, &Editor::trim_region_to_loop)));
        trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch)));
        }
        trim_items.push_back (MenuElem (_("Trim To Loop"), mem_fun(*this, &Editor::trim_region_to_loop)));
        trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch)));
-                            
+
        items.push_back (MenuElem (_("Trim"), *trim_menu));
        items.push_back (SeparatorElem());
 
        items.push_back (MenuElem (_("Trim"), *trim_menu));
        items.push_back (SeparatorElem());
 
-       items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
+       items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split))));
        region_edit_menu_split_item = &items.back();
        region_edit_menu_split_item = &items.back();
-       
+
        if (_edit_point == EditAtMouse) {
                region_edit_menu_split_item->set_sensitive (false);
        }
        if (_edit_point == EditAtMouse) {
                region_edit_menu_split_item->set_sensitive (false);
        }
@@ -1907,7 +1908,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                menu_item_name.replace (pos, 1, "__");
                pos += 2;
        }
                menu_item_name.replace (pos, 1, "__");
                pos += 2;
        }
-       
+
        edit_items.push_back (MenuElem (menu_item_name, *region_menu));
        edit_items.push_back (SeparatorElem());
 }
        edit_items.push_back (MenuElem (menu_item_name, *region_menu));
        edit_items.push_back (SeparatorElem());
 }
@@ -1935,23 +1936,23 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Silence Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
        edit_items.push_back (MenuElem (_("Convert to Region in Region List"), mem_fun(*this, &Editor::new_region_from_selection)));
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Silence Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
        edit_items.push_back (MenuElem (_("Convert to Region in Region List"), mem_fun(*this, &Editor::new_region_from_selection)));
-       
+
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
 
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Set Loop from Range"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
        edit_items.push_back (MenuElem (_("Set Punch from Range"), mem_fun(*this, &Editor::set_punch_from_selection)));
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Select All in Range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
 
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Set Loop from Range"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
        edit_items.push_back (MenuElem (_("Set Punch from Range"), mem_fun(*this, &Editor::set_punch_from_selection)));
-       
+
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection)));
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection)));
-       
+
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Crop Region to Range"), mem_fun(*this, &Editor::crop_region_to_selection)));
        edit_items.push_back (MenuElem (_("Fill Range with Region"), mem_fun(*this, &Editor::region_fill_selection)));
        edit_items.push_back (MenuElem (_("Duplicate Range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
        edit_items.push_back (MenuElem (_("Create Chunk from Range"), mem_fun(*this, &Editor::create_named_selection)));
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Crop Region to Range"), mem_fun(*this, &Editor::crop_region_to_selection)));
        edit_items.push_back (MenuElem (_("Fill Range with Region"), mem_fun(*this, &Editor::region_fill_selection)));
        edit_items.push_back (MenuElem (_("Duplicate Range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
        edit_items.push_back (MenuElem (_("Create Chunk from Range"), mem_fun(*this, &Editor::create_named_selection)));
-       
+
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Consolidate Range"), bind (mem_fun(*this, &Editor::bounce_range_selection), true, false)));
        edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), bind (mem_fun(*this, &Editor::bounce_range_selection), true, true)));
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Consolidate Range"), bind (mem_fun(*this, &Editor::bounce_range_selection), true, false)));
        edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), bind (mem_fun(*this, &Editor::bounce_range_selection), true, true)));
@@ -1960,7 +1961,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
        edit_items.push_back (MenuElem (_("Export Range"), mem_fun(*this, &Editor::export_range)));
 }
 
        edit_items.push_back (MenuElem (_("Export Range"), mem_fun(*this, &Editor::export_range)));
 }
 
-       
+
 void
 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
 {
 void
 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
 {
@@ -1971,13 +1972,13 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *play_menu = manage (new Menu);
        MenuList& play_items = play_menu->items();
        play_menu->set_name ("ArdourContextMenu");
        Menu *play_menu = manage (new Menu);
        MenuList& play_items = play_menu->items();
        play_menu->set_name ("ArdourContextMenu");
-       
+
        play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
        play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
        play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
        play_items.push_back (SeparatorElem());
        play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
        play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
        play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
        play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
        play_items.push_back (SeparatorElem());
        play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
-       
+
        edit_items.push_back (MenuElem (_("Play"), *play_menu));
 
        /* Selection */
        edit_items.push_back (MenuElem (_("Play"), *play_menu));
 
        /* Selection */
@@ -1985,7 +1986,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *select_menu = manage (new Menu);
        MenuList& select_items = select_menu->items();
        select_menu->set_name ("ArdourContextMenu");
        Menu *select_menu = manage (new Menu);
        MenuList& select_items = select_menu->items();
        select_menu->set_name ("ArdourContextMenu");
-       
+
        select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
        select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
        select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
        select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
@@ -2002,8 +2003,6 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        select_items.push_back (MenuElem (_("Select All Within Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), true)));
        select_items.push_back (MenuElem (_("Select Range Between Playhead & Edit Point"), mem_fun(*this, &Editor::select_range_between)));
 
        select_items.push_back (MenuElem (_("Select All Within Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), true)));
        select_items.push_back (MenuElem (_("Select Range Between Playhead & Edit Point"), mem_fun(*this, &Editor::select_range_between)));
 
-       select_items.push_back (SeparatorElem());
-
        edit_items.push_back (MenuElem (_("Select"), *select_menu));
 
        /* Cut-n-Paste */
        edit_items.push_back (MenuElem (_("Select"), *select_menu));
 
        /* Cut-n-Paste */
@@ -2011,7 +2010,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *cutnpaste_menu = manage (new Menu);
        MenuList& cutnpaste_items = cutnpaste_menu->items();
        cutnpaste_menu->set_name ("ArdourContextMenu");
        Menu *cutnpaste_menu = manage (new Menu);
        MenuList& cutnpaste_items = cutnpaste_menu->items();
        cutnpaste_menu->set_name ("ArdourContextMenu");
-       
+
        cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
        cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
        cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
        cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
        cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
        cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
@@ -2028,7 +2027,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
 
        /* Adding new material */
        edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
 
        /* Adding new material */
-       
+
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
        edit_items.push_back (MenuElem (_("Insert Existing Media"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
        edit_items.push_back (SeparatorElem());
        edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
        edit_items.push_back (MenuElem (_("Insert Existing Media"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
@@ -2038,7 +2037,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *nudge_menu = manage (new Menu());
        MenuList& nudge_items = nudge_menu->items();
        nudge_menu->set_name ("ArdourContextMenu");
        Menu *nudge_menu = manage (new Menu());
        MenuList& nudge_items = nudge_menu->items();
        nudge_menu->set_name ("ArdourContextMenu");
-       
+
        edit_items.push_back (SeparatorElem());
        nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
        nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
        edit_items.push_back (SeparatorElem());
        nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
        nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
@@ -2058,7 +2057,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *play_menu = manage (new Menu);
        MenuList& play_items = play_menu->items();
        play_menu->set_name ("ArdourContextMenu");
        Menu *play_menu = manage (new Menu);
        MenuList& play_items = play_menu->items();
        play_menu->set_name ("ArdourContextMenu");
-       
+
        play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
        play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
        edit_items.push_back (MenuElem (_("Play"), *play_menu));
        play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
        play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
        edit_items.push_back (MenuElem (_("Play"), *play_menu));
@@ -2068,7 +2067,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *select_menu = manage (new Menu);
        MenuList& select_items = select_menu->items();
        select_menu->set_name ("ArdourContextMenu");
        Menu *select_menu = manage (new Menu);
        MenuList& select_items = select_menu->items();
        select_menu->set_name ("ArdourContextMenu");
-       
+
        select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
        select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
        select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
        select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
@@ -2086,7 +2085,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *cutnpaste_menu = manage (new Menu);
        MenuList& cutnpaste_items = cutnpaste_menu->items();
        cutnpaste_menu->set_name ("ArdourContextMenu");
        Menu *cutnpaste_menu = manage (new Menu);
        MenuList& cutnpaste_items = cutnpaste_menu->items();
        cutnpaste_menu->set_name ("ArdourContextMenu");
-       
+
        cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
        cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
        cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
        cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
        cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
        cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
@@ -2094,7 +2093,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        Menu *nudge_menu = manage (new Menu());
        MenuList& nudge_items = nudge_menu->items();
        nudge_menu->set_name ("ArdourContextMenu");
        Menu *nudge_menu = manage (new Menu());
        MenuList& nudge_items = nudge_menu->items();
        nudge_menu->set_name ("ArdourContextMenu");
-       
+
        edit_items.push_back (SeparatorElem());
        nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
        nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
        edit_items.push_back (SeparatorElem());
        nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
        nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
@@ -2104,18 +2103,30 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
 }
 
        edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
 }
 
+SnapType
+Editor::snap_type() const
+{
+       return _snap_type;
+}
+
+SnapMode
+Editor::snap_mode() const
+{
+       return _snap_mode;
+}
+
 void
 Editor::set_snap_to (SnapType st)
 {
        unsigned int snap_ind = (unsigned int)st;
 
 void
 Editor::set_snap_to (SnapType st)
 {
        unsigned int snap_ind = (unsigned int)st;
 
-       snap_type = st;
-       
+       _snap_type = st;
+
        if (snap_ind > snap_type_strings.size() - 1) {
                snap_ind = 0;
        if (snap_ind > snap_type_strings.size() - 1) {
                snap_ind = 0;
-               snap_type = (SnapType)snap_ind;
+               _snap_type = (SnapType)snap_ind;
        }
        }
-       
+
        string str = snap_type_strings[snap_ind];
 
        if (str != snap_type_selector.get_active_text()) {
        string str = snap_type_strings[snap_ind];
 
        if (str != snap_type_selector.get_active_text()) {
@@ -2124,7 +2135,7 @@ Editor::set_snap_to (SnapType st)
 
        instant_save ();
 
 
        instant_save ();
 
-       switch (snap_type) {
+       switch (_snap_type) {
        case SnapToAThirtysecondBeat:
        case SnapToASixteenthBeat:
        case SnapToAEighthBeat:
        case SnapToAThirtysecondBeat:
        case SnapToASixteenthBeat:
        case SnapToAEighthBeat:
@@ -2150,7 +2161,7 @@ Editor::set_snap_to (SnapType st)
 void
 Editor::set_snap_mode (SnapMode mode)
 {
 void
 Editor::set_snap_mode (SnapMode mode)
 {
-       snap_mode = mode;
+       _snap_mode = mode;
        string str = snap_mode_strings[(int)mode];
 
        if (str != snap_mode_selector.get_active_text ()) {
        string str = snap_mode_strings[(int)mode];
 
        if (str != snap_mode_selector.get_active_text ()) {
@@ -2229,7 +2240,7 @@ Editor::set_edit_point_preference (EditPoint ep, bool force)
 }
 
 int
 }
 
 int
-Editor::set_state (const XMLNode& node)
+Editor::set_state (const XMLNode& node, int /*version*/)
 {
        const XMLProperty* prop;
        XMLNode* geometry;
 {
        const XMLProperty* prop;
        XMLNode* geometry;
@@ -2305,7 +2316,7 @@ Editor::set_state (const XMLNode& node)
                   position may be zero already, and it does nothing in such
                   circumstances.
                */
                   position may be zero already, and it does nothing in such
                   circumstances.
                */
-               
+
                leftmost_frame = 0;
                horizontal_adjustment.set_value (0);
        }
                leftmost_frame = 0;
                horizontal_adjustment.set_value (0);
        }
@@ -2330,10 +2341,6 @@ Editor::set_state (const XMLNode& node)
                set_snap_mode ((SnapMode) atoi (prop->value()));
        }
 
                set_snap_mode ((SnapMode) atoi (prop->value()));
        }
 
-       if ((prop = node.property ("edit-point"))) {
-               set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
-       }
-
        if ((prop = node.property ("mouse-mode"))) {
                MouseMode m = str2mousemode(prop->value());
                mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
        if ((prop = node.property ("mouse-mode"))) {
                MouseMode m = str2mousemode(prop->value());
                mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
@@ -2343,8 +2350,22 @@ Editor::set_state (const XMLNode& node)
                set_mouse_mode (MouseObject, true);
        }
 
                set_mouse_mode (MouseObject, true);
        }
 
+       if ((prop = node.property ("internal-edit"))) {
+               bool yn = string_is_affirmative (prop->value());
+               RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
+               if (act) {
+                       RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
+                       tact->set_active (!yn);
+                       tact->set_active (yn);
+               }
+       }
+
+       if ((prop = node.property ("edit-point"))) {
+               set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
+       }
+
        if ((prop = node.property ("show-waveforms-recording"))) {
        if ((prop = node.property ("show-waveforms-recording"))) {
-               bool yn = (prop->value() == "yes");
+               bool yn = string_is_affirmative (prop->value());
                _show_waveforms_recording = !yn;
                RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformsWhileRecording"));
                if (act) {
                _show_waveforms_recording = !yn;
                RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformsWhileRecording"));
                if (act) {
@@ -2354,9 +2375,9 @@ Editor::set_state (const XMLNode& node)
                        tact->set_active (yn);
                }
        }
                        tact->set_active (yn);
                }
        }
-       
+
        if ((prop = node.property ("show-measures"))) {
        if ((prop = node.property ("show-measures"))) {
-               bool yn = (prop->value() == "yes");
+               bool yn = string_is_affirmative (prop->value());
                _show_measures = !yn;
                RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
                if (act) {
                _show_measures = !yn;
                RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
                if (act) {
@@ -2368,7 +2389,7 @@ Editor::set_state (const XMLNode& node)
        }
 
        if ((prop = node.property ("follow-playhead"))) {
        }
 
        if ((prop = node.property ("follow-playhead"))) {
-               bool yn = (prop->value() == "yes");
+               bool yn = string_is_affirmative (prop->value());
                set_follow_playhead (yn);
                RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
                if (act) {
                set_follow_playhead (yn);
                RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
                if (act) {
@@ -2384,7 +2405,7 @@ Editor::set_state (const XMLNode& node)
        }
 
        if ((prop = node.property ("xfades-visible"))) {
        }
 
        if ((prop = node.property ("xfades-visible"))) {
-               bool yn = (prop->value() == "yes");
+               bool yn = string_is_affirmative (prop->value());
                _xfade_visibility = !yn;
                // set_xfade_visibility (yn);
        }
                _xfade_visibility = !yn;
                // set_xfade_visibility (yn);
        }
@@ -2395,15 +2416,15 @@ Editor::set_state (const XMLNode& node)
                if (act) {
 
                        Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
                if (act) {
 
                        Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-                       bool yn = (prop->value() == X_("yes"));
+                       bool yn = string_is_affirmative (prop->value());
 
                        /* do it twice to force the change */
 
                        /* do it twice to force the change */
-                       
+
                        tact->set_active (!yn);
                        tact->set_active (yn);
                }
        }
                        tact->set_active (!yn);
                        tact->set_active (yn);
                }
        }
-       
+
        if ((prop = node.property ("show-editor-list"))) {
 
                Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
        if ((prop = node.property ("show-editor-list"))) {
 
                Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
@@ -2411,10 +2432,10 @@ Editor::set_state (const XMLNode& node)
                if (act) {
 
                        Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
                if (act) {
 
                        Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
-                       bool yn = (prop->value() == X_("yes"));
+                       bool yn = string_is_affirmative (prop->value());
 
                        /* do it twice to force the change */
 
                        /* do it twice to force the change */
-                       
+
                        tact->set_active (!yn);
                        tact->set_active (yn);
                }
                        tact->set_active (!yn);
                        tact->set_active (yn);
                }
@@ -2432,15 +2453,15 @@ Editor::get_state ()
 
        _id.print (buf, sizeof (buf));
        node->add_property ("id", buf);
 
        _id.print (buf, sizeof (buf));
        node->add_property ("id", buf);
-       
+
        if (is_realized()) {
                Glib::RefPtr<Gdk::Window> win = get_window();
        if (is_realized()) {
                Glib::RefPtr<Gdk::Window> win = get_window();
-               
+
                int x, y, xoff, yoff, width, height;
                win->get_root_origin(x, y);
                win->get_position(xoff, yoff);
                win->get_size(width, height);
                int x, y, xoff, yoff, width, height;
                win->get_root_origin(x, y);
                win->get_position(xoff, yoff);
                win->get_size(width, height);
-               
+
                XMLNode* geometry = new XMLNode ("geometry");
 
                snprintf(buf, sizeof(buf), "%d", width);
                XMLNode* geometry = new XMLNode ("geometry");
 
                snprintf(buf, sizeof(buf), "%d", width);
@@ -2462,14 +2483,14 @@ Editor::get_state ()
        }
 
        maybe_add_mixer_strip_width (*node);
        }
 
        maybe_add_mixer_strip_width (*node);
-       
+
        snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
        node->add_property ("zoom-focus", buf);
        snprintf (buf, sizeof(buf), "%f", frames_per_unit);
        node->add_property ("zoom", buf);
        snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
        node->add_property ("zoom-focus", buf);
        snprintf (buf, sizeof(buf), "%f", frames_per_unit);
        node->add_property ("zoom", buf);
-       snprintf (buf, sizeof(buf), "%d", (int) snap_type);
+       snprintf (buf, sizeof(buf), "%d", (int) _snap_type);
        node->add_property ("snap-to", buf);
        node->add_property ("snap-to", buf);
-       snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
+       snprintf (buf, sizeof(buf), "%d", (int) _snap_mode);
        node->add_property ("snap-mode", buf);
 
        node->add_property ("edit-point", enum_2_string (_edit_point));
        node->add_property ("snap-mode", buf);
 
        node->add_property ("edit-point", enum_2_string (_edit_point));
@@ -2483,13 +2504,14 @@ Editor::get_state ()
        node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
        node->add_property ("region-list-sort-type", enum2str (_regions->sort_type ()));
        node->add_property ("mouse-mode", enum2str(mouse_mode));
        node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
        node->add_property ("region-list-sort-type", enum2str (_regions->sort_type ()));
        node->add_property ("mouse-mode", enum2str(mouse_mode));
-       
+       node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
+
        Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
        if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
                node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
        }
        Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
        if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
                node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
        }
-       
+
        act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
        if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
        act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
        if (act) {
                Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
@@ -2520,86 +2542,123 @@ Editor::trackview_by_y_position (double y)
        return std::make_pair ( (TimeAxisView *) 0, 0);
 }
 
        return std::make_pair ( (TimeAxisView *) 0, 0);
 }
 
+/** Snap a position to the grid, if appropriate, taking into account current
+ *  grid settings and also the state of any snap modifier keys that may be pressed.
+ *  @param start Position to snap.
+ *  @param event Event to get current key modifier information from.
+ */
 void
 void
-Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
+Editor::snap_to_with_modifier (nframes64_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
 {
 {
-       if (!session || snap_mode == SnapOff) {
+       if (!session) {
                return;
        }
 
                return;
        }
 
-       snap_to_internal (start, direction, for_mark);
+       if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
+               if (_snap_mode == SnapOff) {
+                       snap_to_internal (start, direction, for_mark);
+               }
+       } else {
+               if (_snap_mode != SnapOff) {
+                       snap_to_internal (start, direction, for_mark);
+               }
+       }
 }
 
 void
 }
 
 void
-Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
+Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
 {
 {
-       Location* before = 0;
-       Location* after = 0;
+       if (!session || _snap_mode == SnapOff) {
+               return;
+       }
 
 
-       const nframes64_t one_second = session->frame_rate();
-       const nframes64_t one_minute = session->frame_rate() * 60;
-       const nframes64_t one_smpte_second = (nframes64_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame());
-       nframes64_t one_smpte_minute = (nframes64_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame() * 60);
-       nframes64_t presnap = start;
+       snap_to_internal (start, direction, for_mark);
+}
 
 
-       switch (snap_type) {
-       case SnapToCDFrame:
-               if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
-                       start = (nframes64_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
-               } else {
-                       start = (nframes64_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
-               }
-               break;
+void
+Editor::timecode_snap_to_internal (nframes64_t& start, int32_t direction, bool /*for_mark*/)
+{
+       const nframes64_t one_timecode_second = (nframes64_t)(rint(session->timecode_frames_per_second()) * session->frames_per_timecode_frame());
+       nframes64_t one_timecode_minute = (nframes64_t)(rint(session->timecode_frames_per_second()) * session->frames_per_timecode_frame() * 60);
 
 
-       case SnapToSMPTEFrame:
-               if (((direction == 0) && (fmod((double)start, (double)session->frames_per_smpte_frame()) > (session->frames_per_smpte_frame() / 2))) || (direction > 0)) {
-                       start = (nframes64_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
+       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)) {
+                       start = (nframes64_t) (ceil ((double) start / session->frames_per_timecode_frame()) * session->frames_per_timecode_frame());
                } else {
                } else {
-                       start = (nframes64_t) (floor ((double) start / session->frames_per_smpte_frame()) *  session->frames_per_smpte_frame());
+                       start = (nframes64_t) (floor ((double) start / session->frames_per_timecode_frame()) *  session->frames_per_timecode_frame());
                }
                break;
 
                }
                break;
 
-       case SnapToSMPTESeconds:
-               if (session->smpte_offset_negative())
+       case SnapToTimecodeSeconds:
+               if (session->timecode_offset_negative())
                {
                {
-                       start += session->smpte_offset ();
+                       start += session->timecode_offset ();
                } else {
                } else {
-                       start -= session->smpte_offset ();
-               }    
-               if (((direction == 0) && (start % one_smpte_second > one_smpte_second / 2)) || direction > 0) {
-                       start = (nframes64_t) ceil ((double) start / one_smpte_second) * one_smpte_second;
+                       start -= session->timecode_offset ();
+               }
+               if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
+                       start = (nframes64_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
                } else {
                } else {
-                       start = (nframes64_t) floor ((double) start / one_smpte_second) * one_smpte_second;
+                       start = (nframes64_t) floor ((double) start / one_timecode_second) * one_timecode_second;
                }
                }
-               
-               if (session->smpte_offset_negative())
+
+               if (session->timecode_offset_negative())
                {
                {
-                       start -= session->smpte_offset ();
+                       start -= session->timecode_offset ();
                } else {
                } else {
-                       start += session->smpte_offset ();
+                       start += session->timecode_offset ();
                }
                break;
                }
                break;
-               
-       case SnapToSMPTEMinutes:
-               if (session->smpte_offset_negative())
+
+       case SnapToTimecodeMinutes:
+               if (session->timecode_offset_negative())
                {
                {
-                       start += session->smpte_offset ();
+                       start += session->timecode_offset ();
                } else {
                } else {
-                       start -= session->smpte_offset ();
+                       start -= session->timecode_offset ();
                }
                }
-               if (((direction == 0) && (start % one_smpte_minute > one_smpte_minute / 2)) || direction > 0) {
-                       start = (nframes64_t) ceil ((double) start / one_smpte_minute) * one_smpte_minute;
+               if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
+                       start = (nframes64_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
                } else {
                } else {
-                       start = (nframes64_t) floor ((double) start / one_smpte_minute) * one_smpte_minute;
+                       start = (nframes64_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
                }
                }
-               if (session->smpte_offset_negative())
+               if (session->timecode_offset_negative())
                {
                {
-                       start -= session->smpte_offset ();
+                       start -= session->timecode_offset ();
+               } else {
+                       start += session->timecode_offset ();
+               }
+               break;
+       default:
+               fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
+               /*NOTREACHED*/
+       }
+}
+
+void
+Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
+{
+       const nframes64_t one_second = session->frame_rate();
+       const nframes64_t one_minute = session->frame_rate() * 60;
+       nframes64_t presnap = start;
+       nframes64_t before;
+       nframes64_t after;
+
+       switch (_snap_type) {
+       case SnapToTimecodeFrame:
+       case SnapToTimecodeSeconds:
+       case SnapToTimecodeMinutes:
+               return timecode_snap_to_internal (start, direction, for_mark);
+
+       case SnapToCDFrame:
+               if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
+                       start = (nframes64_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
                } else {
                } else {
-                       start += session->smpte_offset ();
+                       start = (nframes64_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
                }
                break;
                }
                break;
-               
+
        case SnapToSeconds:
                if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
                        start = (nframes64_t) ceil ((double) start / one_second) * one_second;
        case SnapToSeconds:
                if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
                        start = (nframes64_t) ceil ((double) start / one_second) * one_second;
@@ -2607,7 +2666,7 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
                        start = (nframes64_t) floor ((double) start / one_second) * one_second;
                }
                break;
                        start = (nframes64_t) floor ((double) start / one_second) * one_second;
                }
                break;
-               
+
        case SnapToMinutes:
                if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
                        start = (nframes64_t) ceil ((double) start / one_minute) * one_minute;
        case SnapToMinutes:
                if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
                        start = (nframes64_t) ceil ((double) start / one_minute) * one_minute;
@@ -2625,23 +2684,23 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
                break;
 
        case SnapToAThirtysecondBeat:
                break;
 
        case SnapToAThirtysecondBeat:
-               start = session->tempo_map().round_to_beat_subdivision (start, 32);
+               start = session->tempo_map().round_to_beat_subdivision (start, 32, direction);
                break;
 
        case SnapToASixteenthBeat:
                break;
 
        case SnapToASixteenthBeat:
-               start = session->tempo_map().round_to_beat_subdivision (start, 16);
+               start = session->tempo_map().round_to_beat_subdivision (start, 16, direction);
                break;
 
        case SnapToAEighthBeat:
                break;
 
        case SnapToAEighthBeat:
-               start = session->tempo_map().round_to_beat_subdivision (start, 8);
+               start = session->tempo_map().round_to_beat_subdivision (start, 8, direction);
                break;
 
        case SnapToAQuarterBeat:
                break;
 
        case SnapToAQuarterBeat:
-               start = session->tempo_map().round_to_beat_subdivision (start, 4);
+               start = session->tempo_map().round_to_beat_subdivision (start, 4, direction);
                break;
 
        case SnapToAThirdBeat:
                break;
 
        case SnapToAThirdBeat:
-               start = session->tempo_map().round_to_beat_subdivision (start, 3);
+               start = session->tempo_map().round_to_beat_subdivision (start, 3, direction);
                break;
 
        case SnapToMark:
                break;
 
        case SnapToMark:
@@ -2649,39 +2708,21 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
                        return;
                }
 
                        return;
                }
 
-               before = session->locations()->first_location_before (start);
-               after = session->locations()->first_location_after (start);
+               session->locations()->marks_either_side (start, before, after);
 
 
-               if (direction < 0) {
-                       if (before) {
-                               start = before->start();
-                       } else {
-                               start = 0;
-                       }
-               } else if (direction > 0) {
-                       if (after) {
-                               start = after->start();
+               if (before == max_frames) {
+                       start = after;
+               } else if (after == max_frames) {
+                       start = before;
+               } else if (before != max_frames && after != max_frames) {
+                       /* have before and after */
+                       if ((start - before) < (after - start)) {
+                               start = before;
                        } else {
                        } else {
-                               start = session->current_end_frame();
-                       }
-               } else {
-                       if (before) {
-                               if (after) {
-                                       /* find nearest of the two */
-                                       if ((start - before->start()) < (after->start() - start)) {
-                                               start = before->start();
-                                       } else {
-                                               start = after->start();
-                                       }
-                               } else {
-                                       start = before->start();
-                               }
-                       } else if (after) {
-                               start = after->start();
-                       } else {
-                               /* relax */
+                               start = after;
                        }
                }
                        }
                }
+
                break;
 
        case SnapToRegionStart:
                break;
 
        case SnapToRegionStart:
@@ -2689,95 +2730,58 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
        case SnapToRegionSync:
        case SnapToRegionBoundary:
                if (!region_boundary_cache.empty()) {
        case SnapToRegionSync:
        case SnapToRegionBoundary:
                if (!region_boundary_cache.empty()) {
-                       vector<nframes64_t>::iterator i;
+
+                       vector<nframes64_t>::iterator prev = region_boundary_cache.end ();
+                       vector<nframes64_t>::iterator next = region_boundary_cache.end ();
 
                        if (direction > 0) {
 
                        if (direction > 0) {
-                               i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+                               next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
                        } else {
                        } else {
-                               i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
+                               next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
                        }
                        }
-                       
-                       if (i != region_boundary_cache.end()) {
-
-                               /* lower bound doesn't quite to the right thing for our purposes */
 
 
-                               if (direction < 0 && i != region_boundary_cache.begin()) {
-                                       --i;
-                               }
+                       if (next != region_boundary_cache.begin ()) {
+                               prev = next;
+                               prev--;
+                       }
 
 
-                               start = *i;
+                       nframes64_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
+                       nframes64_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
 
 
+                       if (start > (p + n) / 2) {
+                               start = n;
                        } else {
                        } else {
-                               start = region_boundary_cache.back();
+                               start = p;
                        }
                        }
-               } 
+               }
                break;
        }
 
                break;
        }
 
-       switch (snap_mode) {
+       switch (_snap_mode) {
        case SnapNormal:
        case SnapNormal:
-               return;                 
-               
+               return;
+
        case SnapMagnetic:
        case SnapMagnetic:
-               
+
                if (presnap > start) {
                        if (presnap > (start + unit_to_frame(snap_threshold))) {
                                start = presnap;
                        }
                if (presnap > start) {
                        if (presnap > (start + unit_to_frame(snap_threshold))) {
                                start = presnap;
                        }
-                       
+
                } else if (presnap < start) {
                        if (presnap < (start - unit_to_frame(snap_threshold))) {
                                start = presnap;
                        }
                }
                } else if (presnap < start) {
                        if (presnap < (start - unit_to_frame(snap_threshold))) {
                                start = presnap;
                        }
                }
-               
+
        default:
                /* handled at entry */
                return;
        default:
                /* handled at entry */
                return;
-               
-       }
-}
-
-double
-Editor::snap_length_beats (nframes64_t start)
-{
-       if (!session) {
-               return 1.0;
-       }
-
-       /* FIXME: This could/should also work with non-tempo based snap settings (ie seconds) */
 
 
-       switch (snap_type) {
-       case SnapToBar:
-               return session->tempo_map().meter_at(start).beats_per_bar();
-
-       case SnapToBeat:
-               return 1.0;
-
-       case SnapToAThirtysecondBeat:
-               return 1.0 / (double)32.0;
-               break;
-
-       case SnapToASixteenthBeat:
-               return 1.0 / (double)16.0;
-               break;
-
-       case SnapToAEighthBeat:
-               return 1.0 / (double)8.0;
-               break;
-
-       case SnapToAQuarterBeat:
-               return 1.0 / (double)4.0;
-               break;
-
-       case SnapToAThirdBeat:
-               return 1.0 / (double)3.0;
-
-       default:
-               return 1.0;
        }
 }
 
        }
 }
 
+
 void
 Editor::setup_toolbar ()
 {
 void
 Editor::setup_toolbar ()
 {
@@ -2785,36 +2789,13 @@ Editor::setup_toolbar ()
 
        /* Mode Buttons (tool selection) */
 
 
        /* Mode Buttons (tool selection) */
 
-       vector<ToggleButton *> mouse_mode_buttons;
-
-       mouse_move_button.add (*(manage (new Image (::get_icon("tool_object")))));
        mouse_move_button.set_relief(Gtk::RELIEF_NONE);
        mouse_move_button.set_relief(Gtk::RELIEF_NONE);
-       mouse_mode_buttons.push_back (&mouse_move_button);
-
-       if (!Profile->get_sae()) {
-               mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
-               mouse_select_button.set_relief(Gtk::RELIEF_NONE);
-               mouse_mode_buttons.push_back (&mouse_select_button);
-
-               mouse_gain_button.add (*(manage (new Image (::get_icon("tool_gain")))));
-               mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
-               mouse_mode_buttons.push_back (&mouse_gain_button);
-       }
-
-       mouse_zoom_button.add (*(manage (new Image (::get_icon("tool_zoom")))));
+       mouse_select_button.set_relief(Gtk::RELIEF_NONE);
+       mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
        mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
        mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
-       mouse_mode_buttons.push_back (&mouse_zoom_button);
-       mouse_timefx_button.add (*(manage (new Image (::get_icon("tool_stretch")))));
        mouse_timefx_button.set_relief(Gtk::RELIEF_NONE);
        mouse_timefx_button.set_relief(Gtk::RELIEF_NONE);
-       mouse_mode_buttons.push_back (&mouse_timefx_button);
-       mouse_audition_button.add (*(manage (new Image (::get_icon("tool_audition")))));
        mouse_audition_button.set_relief(Gtk::RELIEF_NONE);
        mouse_audition_button.set_relief(Gtk::RELIEF_NONE);
-       mouse_note_button.add (*(manage (new Image (::get_icon("tool_note")))));
-       mouse_note_button.set_relief(Gtk::RELIEF_NONE);
-       mouse_mode_buttons.push_back (&mouse_note_button);
-       mouse_mode_buttons.push_back (&mouse_audition_button);
-       
-       mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
+       // internal_edit_button.set_relief(Gtk::RELIEF_NONE);
 
        HBox* mode_box = manage(new HBox);
        mode_box->set_border_width (2);
 
        HBox* mode_box = manage(new HBox);
        mode_box->set_border_width (2);
@@ -2830,7 +2811,7 @@ Editor::setup_toolbar ()
        }
        mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
        mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
        }
        mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
        mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
-       mouse_mode_button_box.pack_start(mouse_note_button, true, true);
+       mouse_mode_button_box.pack_start(internal_edit_button, true, true);
        mouse_mode_button_box.set_homogeneous(true);
 
        vector<string> edit_mode_strings;
        mouse_mode_button_box.set_homogeneous(true);
 
        vector<string> edit_mode_strings;
@@ -2846,38 +2827,39 @@ Editor::setup_toolbar ()
 
        mode_box->pack_start(edit_mode_selector);
        mode_box->pack_start(mouse_mode_button_box);
 
        mode_box->pack_start(edit_mode_selector);
        mode_box->pack_start(mouse_mode_button_box);
-       
+
        mouse_mode_tearoff = manage (new TearOff (*mode_box));
        mouse_mode_tearoff->set_name ("MouseModeBase");
        mouse_mode_tearoff = manage (new TearOff (*mode_box));
        mouse_mode_tearoff->set_name ("MouseModeBase");
+       mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (bind (sigc::ptr_fun (relay_key_press), &mouse_mode_tearoff->tearoff_window()), false);
 
        if (Profile->get_sae()) {
                mouse_mode_tearoff->set_can_be_torn_off (false);
        }
 
 
        if (Profile->get_sae()) {
                mouse_mode_tearoff->set_can_be_torn_off (false);
        }
 
-       mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+       mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
                                                  &mouse_mode_tearoff->tearoff_window()));
                                                  &mouse_mode_tearoff->tearoff_window()));
-       mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+       mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                                  &mouse_mode_tearoff->tearoff_window(), 1));
                                                  &mouse_mode_tearoff->tearoff_window(), 1));
-       mouse_mode_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+       mouse_mode_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
                                                  &mouse_mode_tearoff->tearoff_window()));
                                                  &mouse_mode_tearoff->tearoff_window()));
-       mouse_mode_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+       mouse_mode_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                                   &mouse_mode_tearoff->tearoff_window(), 1));
 
                                                   &mouse_mode_tearoff->tearoff_window(), 1));
 
+       mouse_move_button.set_mode (false);
+       mouse_select_button.set_mode (false);
+       mouse_gain_button.set_mode (false);
+       mouse_zoom_button.set_mode (false);
+       mouse_timefx_button.set_mode (false);
+       mouse_audition_button.set_mode (false);
+
        mouse_move_button.set_name ("MouseModeButton");
        mouse_select_button.set_name ("MouseModeButton");
        mouse_gain_button.set_name ("MouseModeButton");
        mouse_zoom_button.set_name ("MouseModeButton");
        mouse_timefx_button.set_name ("MouseModeButton");
        mouse_audition_button.set_name ("MouseModeButton");
        mouse_move_button.set_name ("MouseModeButton");
        mouse_select_button.set_name ("MouseModeButton");
        mouse_gain_button.set_name ("MouseModeButton");
        mouse_zoom_button.set_name ("MouseModeButton");
        mouse_timefx_button.set_name ("MouseModeButton");
        mouse_audition_button.set_name ("MouseModeButton");
-       mouse_note_button.set_name ("MouseModeButton");
 
 
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("Draw Gain Automation"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions"));
-       ARDOUR_UI::instance()->tooltips().set_tip (mouse_note_button, _("Edit MIDI Notes"));
+       internal_edit_button.set_name ("MouseModeButton");
 
        mouse_move_button.unset_flags (CAN_FOCUS);
        mouse_select_button.unset_flags (CAN_FOCUS);
 
        mouse_move_button.unset_flags (CAN_FOCUS);
        mouse_select_button.unset_flags (CAN_FOCUS);
@@ -2885,23 +2867,10 @@ Editor::setup_toolbar ()
        mouse_zoom_button.unset_flags (CAN_FOCUS);
        mouse_timefx_button.unset_flags (CAN_FOCUS);
        mouse_audition_button.unset_flags (CAN_FOCUS);
        mouse_zoom_button.unset_flags (CAN_FOCUS);
        mouse_timefx_button.unset_flags (CAN_FOCUS);
        mouse_audition_button.unset_flags (CAN_FOCUS);
-       mouse_note_button.unset_flags (CAN_FOCUS);
-
-       mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
-       mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
-
-       mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
-       mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
-       mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
-       mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
-       mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
-       mouse_note_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseNote));
-
-       // mouse_move_button.set_active (true);
-       
+       internal_edit_button.unset_flags (CAN_FOCUS);
 
        /* Zoom */
 
        /* Zoom */
-       
+
        zoom_box.set_spacing (1);
        zoom_box.set_border_width (0);
 
        zoom_box.set_spacing (1);
        zoom_box.set_border_width (0);
 
@@ -2910,7 +2879,7 @@ Editor::setup_toolbar ()
        zoom_in_button.add (*(manage (new Image (::get_icon("zoom_in")))));
        zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
        ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In"));
        zoom_in_button.add (*(manage (new Image (::get_icon("zoom_in")))));
        zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
        ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In"));
-       
+
        zoom_out_button.set_name ("EditorTimeButton");
        zoom_out_button.set_size_request(-1,16);
        zoom_out_button.add (*(manage (new Image (::get_icon("zoom_out")))));
        zoom_out_button.set_name ("EditorTimeButton");
        zoom_out_button.set_size_request(-1,16);
        zoom_out_button.add (*(manage (new Image (::get_icon("zoom_out")))));
@@ -2932,10 +2901,30 @@ Editor::setup_toolbar ()
        zoom_box.pack_start (zoom_in_button, false, false);
        zoom_box.pack_start (zoom_out_full_button, false, false);
 
        zoom_box.pack_start (zoom_in_button, false, false);
        zoom_box.pack_start (zoom_out_full_button, false, false);
 
+       /* Track zoom buttons */
+       tav_expand_button.set_name ("TrackHeightButton");
+       tav_expand_button.set_size_request(-1,20);
+       tav_expand_button.add (*(manage (new Image (::get_icon("tav_exp")))));
+       tav_expand_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::tav_zoom_step), true));
+       ARDOUR_UI::instance()->tooltips().set_tip (tav_expand_button, _("Expand Tracks"));
+
+       tav_shrink_button.set_name ("TrackHeightButton");
+       tav_shrink_button.set_size_request(-1,20);
+       tav_shrink_button.add (*(manage (new Image (::get_icon("tav_shrink")))));
+       tav_shrink_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::tav_zoom_step), false));
+       ARDOUR_UI::instance()->tooltips().set_tip (tav_shrink_button, _("Shrink Tracks"));
+
+       track_zoom_box.set_spacing (1);
+       track_zoom_box.set_border_width (0);
+
+       track_zoom_box.pack_start (tav_shrink_button, false, false);
+       track_zoom_box.pack_start (tav_expand_button, false, false);
+
        HBox* zbc = manage (new HBox);
        zbc->pack_start (zoom_focus_selector, PACK_SHRINK);
        zoom_vbox.pack_start (*zbc, PACK_SHRINK);
        zoom_vbox.pack_start (zoom_box, PACK_SHRINK);
        HBox* zbc = manage (new HBox);
        zbc->pack_start (zoom_focus_selector, PACK_SHRINK);
        zoom_vbox.pack_start (*zbc, PACK_SHRINK);
        zoom_vbox.pack_start (zoom_box, PACK_SHRINK);
+       zoom_vbox.pack_start (track_zoom_box, PACK_SHRINK);
 
        snap_box.set_spacing (1);
        snap_box.set_border_width (2);
 
        snap_box.set_spacing (1);
        snap_box.set_border_width (2);
@@ -2981,18 +2970,19 @@ Editor::setup_toolbar ()
 
        tools_tearoff = manage (new TearOff (*hbox));
        tools_tearoff->set_name ("MouseModeBase");
 
        tools_tearoff = manage (new TearOff (*hbox));
        tools_tearoff->set_name ("MouseModeBase");
+       tools_tearoff->tearoff_window().signal_key_press_event().connect (bind (sigc::ptr_fun (relay_key_press), &tools_tearoff->tearoff_window()), false);
 
        if (Profile->get_sae()) {
                tools_tearoff->set_can_be_torn_off (false);
        }
 
 
        if (Profile->get_sae()) {
                tools_tearoff->set_can_be_torn_off (false);
        }
 
-       tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+       tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
                                             &tools_tearoff->tearoff_window()));
                                             &tools_tearoff->tearoff_window()));
-       tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+       tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                             &tools_tearoff->tearoff_window(), 0));
                                             &tools_tearoff->tearoff_window(), 0));
-       tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
+       tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
                                             &tools_tearoff->tearoff_window()));
                                             &tools_tearoff->tearoff_window()));
-       tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
+       tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                              &tools_tearoff->tearoff_window(), 0));
 
        toolbar_hbox.set_spacing (10);
                                              &tools_tearoff->tearoff_window(), 0));
 
        toolbar_hbox.set_spacing (10);
@@ -3001,13 +2991,12 @@ Editor::setup_toolbar ()
        toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
        toolbar_hbox.pack_start (*tools_tearoff, false, false);
 
        toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
        toolbar_hbox.pack_start (*tools_tearoff, false, false);
 
-       
        hbox->pack_start (snap_box, false, false);
        hbox->pack_start (snap_box, false, false);
-       // hbox->pack_start (zoom_box, false, false); 
        hbox->pack_start (*nudge_box, false, false);
        hbox->pack_start (*nudge_box, false, false);
+       hbox->pack_start (panic_box, false, false);
 
        hbox->show_all ();
 
        hbox->show_all ();
-       
+
        toolbar_base.set_name ("ToolBarBase");
        toolbar_base.add (toolbar_hbox);
 
        toolbar_base.set_name ("ToolBarBase");
        toolbar_base.add (toolbar_hbox);
 
@@ -3017,8 +3006,10 @@ Editor::setup_toolbar ()
 }
 
 void
 }
 
 void
-Editor::midi_panic_button_pressed ()
+Editor::midi_panic ()
 {
 {
+       cerr << "MIDI panic\n";
+
        if (session) {
                session->midi_panic();
        }
        if (session) {
                session->midi_panic();
        }
@@ -3027,122 +3018,34 @@ Editor::midi_panic_button_pressed ()
 void
 Editor::setup_midi_toolbar ()
 {
 void
 Editor::setup_midi_toolbar ()
 {
-       string pixmap_path;
-
-       /* Mode Buttons (tool selection) */
+       RefPtr<Action> act;
 
 
-       vector<ToggleButton *> midi_tool_buttons;
-
-       midi_tool_pencil_button.add (*(manage (new Image (::get_icon("midi_tool_pencil")))));
-       midi_tool_pencil_button.set_relief(Gtk::RELIEF_NONE);
-       midi_tool_buttons.push_back (&midi_tool_pencil_button);
-       midi_tool_select_button.add (*(manage (new Image (::get_icon("midi_tool_select")))));
-       midi_tool_select_button.set_relief(Gtk::RELIEF_NONE);
-       midi_tool_buttons.push_back (&midi_tool_select_button);
-       midi_tool_resize_button.add (*(manage (new Image (::get_icon("strip_width")))));
-       midi_tool_resize_button.set_relief(Gtk::RELIEF_NONE);
-       midi_tool_buttons.push_back (&midi_tool_resize_button);
-       midi_tool_erase_button.add (*(manage (new Image (::get_icon("midi_tool_erase")))));
-       midi_tool_erase_button.set_relief(Gtk::RELIEF_NONE);
-       midi_tool_buttons.push_back (&midi_tool_erase_button);
-
-       midi_tool_pencil_button.set_active(true);
-       
-       midi_tool_button_set = new GroupedButtons (midi_tool_buttons);
-
-       midi_tool_button_box.set_border_width (2);
-       midi_tool_button_box.set_spacing(1);
-       midi_tool_button_box.pack_start(midi_tool_pencil_button, true, true);
-       midi_tool_button_box.pack_start(midi_tool_select_button, true, true);
-       midi_tool_button_box.pack_start(midi_tool_resize_button, true, true);
-       midi_tool_button_box.pack_start(midi_tool_erase_button , true, true);
-       midi_tool_button_box.set_homogeneous(true);
-
-       midi_tool_pencil_button.set_name ("MouseModeButton");
-       midi_tool_select_button.set_name ("MouseModeButton");
-       midi_tool_resize_button.set_name ("MouseModeButton");
-       midi_tool_erase_button .set_name ("MouseModeButton");
-
-       ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_pencil_button, _("Add/Move/Stretch Notes"));
-       ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_select_button, _("Select/Move Notes"));
-       ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_resize_button, _("Resize Notes"));
-       ARDOUR_UI::instance()->tooltips().set_tip (midi_tool_erase_button,  _("Erase Notes"));
-
-       midi_tool_pencil_button.unset_flags (CAN_FOCUS);
-       midi_tool_select_button.unset_flags (CAN_FOCUS);
-       midi_tool_resize_button.unset_flags (CAN_FOCUS);
-       midi_tool_erase_button.unset_flags (CAN_FOCUS);
-       
-       midi_tool_pencil_button.signal_toggled().connect (bind (mem_fun(*this,
-                               &Editor::midi_edit_mode_toggled), Editing::MidiEditPencil));
-       midi_tool_select_button.signal_toggled().connect (bind (mem_fun(*this,
-                               &Editor::midi_edit_mode_toggled), Editing::MidiEditSelect));
-       midi_tool_resize_button.signal_toggled().connect (bind (mem_fun(*this,
-                               &Editor::midi_edit_mode_toggled), Editing::MidiEditResize));
-       midi_tool_erase_button.signal_toggled().connect (bind (mem_fun(*this,
-                               &Editor::midi_edit_mode_toggled), Editing::MidiEditErase));
-
-       
        /* Midi sound notes */
        midi_sound_notes.add (*(manage (new Image (::get_icon("midi_sound_notes")))));
        midi_sound_notes.set_relief(Gtk::RELIEF_NONE);
        ARDOUR_UI::instance()->tooltips().set_tip (midi_sound_notes, _("Sound Notes"));
        midi_sound_notes.unset_flags (CAN_FOCUS);
        /* Midi sound notes */
        midi_sound_notes.add (*(manage (new Image (::get_icon("midi_sound_notes")))));
        midi_sound_notes.set_relief(Gtk::RELIEF_NONE);
        ARDOUR_UI::instance()->tooltips().set_tip (midi_sound_notes, _("Sound Notes"));
        midi_sound_notes.unset_flags (CAN_FOCUS);
-       
-       /* Panic */
-       
-       HBox* panic_box = manage (new HBox);
-       midi_panic_button.set_name("MidiPanicButton");
-       midi_panic_button.signal_pressed().connect (
-                       mem_fun(this, &Editor::midi_panic_button_pressed));
-       panic_box->pack_start (midi_sound_notes , true, true);
-       panic_box->pack_start (midi_panic_button, true, true);
-       
-       /* Pack everything in... */
-
-       midi_tools_tearoff = manage (new TearOff (midi_tool_button_box));
-       midi_tools_tearoff->set_name ("MouseModeBase");
-
-       /*
-       midi_tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox), 
-                                            &midi_tools_tearoff->tearoff_window()));
-       midi_tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox), 
-                                            &midi_tools_tearoff->tearoff_window(), 0));
-       midi_tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&midi_toolbar_hbox), 
-                                            &midi_tools_tearoff->tearoff_window()));
-       midi_tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&midi_toolbar_hbox), 
-                                             &midi_tools_tearoff->tearoff_window(), 0));
-       */
-
-       midi_toolbar_hbox.set_spacing (10);
-       midi_toolbar_hbox.set_border_width (1);
 
 
-       midi_toolbar_hbox.pack_start (*midi_tools_tearoff, false, true);
-       
-       midi_toolbar_hbox.pack_start(*panic_box, false, true, 4);
+       /* Panic */
 
 
-       midi_tool_button_box.show_all ();
-       midi_toolbar_hbox.show_all();
-       midi_tools_tearoff->show_all();
-       
-       midi_toolbar_base.set_name ("ToolBarBase");
-       midi_toolbar_base.add (midi_toolbar_hbox);
+       act = ActionManager::get_action (X_("MIDI"), X_("panic"));
+       midi_panic_button.set_name("MidiPanicButton");
+       act->connect_proxy (midi_panic_button);
 
 
-       midi_toolbar_frame.set_shadow_type (SHADOW_OUT);
-       midi_toolbar_frame.set_name ("BaseFrame");
-       midi_toolbar_frame.add (midi_toolbar_base);
+       panic_box.pack_start (midi_sound_notes , true, true);
+       panic_box.pack_start (midi_panic_button, true, true);
 }
 
 int
 Editor::convert_drop_to_paths (
 }
 
 int
 Editor::convert_drop_to_paths (
-               vector<ustring>&                paths, 
+               vector<ustring>&                paths,
                const RefPtr<Gdk::DragContext>& /*context*/,
                gint                            /*x*/,
                gint                            /*y*/,
                const SelectionData&            data,
                guint                           /*info*/,
                guint                           /*time*/)
                const RefPtr<Gdk::DragContext>& /*context*/,
                gint                            /*x*/,
                gint                            /*y*/,
                const SelectionData&            data,
                guint                           /*info*/,
                guint                           /*time*/)
-{      
+{
        if (session == 0) {
                return -1;
        }
        if (session == 0) {
                return -1;
        }
@@ -3158,8 +3061,8 @@ Editor::convert_drop_to_paths (
                if (data.get_target() != "text/plain") {
                        return -1;
                }
                if (data.get_target() != "text/plain") {
                        return -1;
                }
-  
-               /* Parse the "uri-list" format that Nautilus provides, 
+
+               /* Parse the "uri-list" format that Nautilus provides,
                   where each pathname is delimited by \r\n.
 
                   THERE MAY BE NO NULL TERMINATING CHAR!!!
                   where each pathname is delimited by \r\n.
 
                   THERE MAY BE NO NULL TERMINATING CHAR!!!
@@ -3179,18 +3082,18 @@ Editor::convert_drop_to_paths (
                        {
                                while (g_ascii_isspace (*p))
                                        p++;
                        {
                                while (g_ascii_isspace (*p))
                                        p++;
-                               
+
                                q = p;
                                while (*q && (*q != '\n') && (*q != '\r')) {
                                        q++;
                                }
                                q = p;
                                while (*q && (*q != '\n') && (*q != '\r')) {
                                        q++;
                                }
-                               
+
                                if (q > p)
                                {
                                        q--;
                                        while (q > p && g_ascii_isspace (*q))
                                                q--;
                                if (q > p)
                                {
                                        q--;
                                        while (q > p && g_ascii_isspace (*q))
                                                q--;
-                                       
+
                                        if (q > p)
                                        {
                                                uris.push_back (ustring (p, q - p + 1));
                                        if (q > p)
                                        {
                                                uris.push_back (ustring (p, q - p + 1));
@@ -3203,21 +3106,21 @@ Editor::convert_drop_to_paths (
                }
 
                free ((void*)p);
                }
 
                free ((void*)p);
-               
+
                if (uris.empty()) {
                        return -1;
                }
        }
                if (uris.empty()) {
                        return -1;
                }
        }
-       
+
        for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
 
                if ((*i).substr (0,7) == "file://") {
        for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
 
                if ((*i).substr (0,7) == "file://") {
-                       
+
                        ustring p = *i;
                        PBD::url_decode (p);
 
                        // scan forward past three slashes
                        ustring p = *i;
                        PBD::url_decode (p);
 
                        // scan forward past three slashes
-                       
+
                        ustring::size_type slashcnt = 0;
                        ustring::size_type n = 0;
                        ustring::iterator x = p.begin();
                        ustring::size_type slashcnt = 0;
                        ustring::size_type n = 0;
                        ustring::iterator x = p.begin();
@@ -3334,7 +3237,7 @@ Editor::set_route_group_mute (Route& route, bool yn)
                route.set_mute (yn, this);
        }
 }
                route.set_mute (yn, this);
        }
 }
-               
+
 void
 Editor::history_changed ()
 {
 void
 Editor::history_changed ()
 {
@@ -3372,7 +3275,7 @@ Editor::duplicate_dialog (bool with_dialog)
 
        RegionSelection rs;
        get_regions_for_action (rs);
 
        RegionSelection rs;
        get_regions_for_action (rs);
-       
+
        if (mouse_mode != MouseRange) {
 
                if (rs.empty()) {
        if (mouse_mode != MouseRange) {
 
                if (rs.empty()) {
@@ -3382,21 +3285,21 @@ Editor::duplicate_dialog (bool with_dialog)
 
        if (with_dialog) {
 
 
        if (with_dialog) {
 
-               ArdourDialog win ("Duplication Dialog");
+               ArdourDialog win ("Duplicate");
                Label  label (_("Number of Duplications:"));
                Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
                SpinButton spinner (adjustment, 0.0, 1);
                HBox hbox;
                Label  label (_("Number of Duplications:"));
                Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
                SpinButton spinner (adjustment, 0.0, 1);
                HBox hbox;
-               
+
                win.get_vbox()->set_spacing (12);
                win.get_vbox()->pack_start (hbox);
                hbox.set_border_width (6);
                hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
                win.get_vbox()->set_spacing (12);
                win.get_vbox()->pack_start (hbox);
                hbox.set_border_width (6);
                hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
-               
+
                /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
                   place, visually. so do this by hand.
                */
                /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
                   place, visually. so do this by hand.
                */
-               
+
                hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
                spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
                spinner.grab_focus();
                hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
                spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
                spinner.grab_focus();
@@ -3404,22 +3307,22 @@ Editor::duplicate_dialog (bool with_dialog)
                hbox.show ();
                label.show ();
                spinner.show ();
                hbox.show ();
                label.show ();
                spinner.show ();
-               
+
                win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
                win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
                win.set_default_response (RESPONSE_ACCEPT);
                win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
                win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
                win.set_default_response (RESPONSE_ACCEPT);
-               
+
                win.set_position (WIN_POS_MOUSE);
                win.set_position (WIN_POS_MOUSE);
-               
+
                spinner.grab_focus ();
                spinner.grab_focus ();
-               
+
                switch (win.run ()) {
                case RESPONSE_ACCEPT:
                        break;
                default:
                        return;
                }
                switch (win.run ()) {
                case RESPONSE_ACCEPT:
                        break;
                default:
                        return;
                }
-               
+
                times = adjustment.get_value();
        }
 
                times = adjustment.get_value();
        }
 
@@ -3467,6 +3370,31 @@ Editor::clamp_verbose_cursor_y (double y)
        return y;
 }
 
        return y;
 }
 
+void
+Editor::show_verbose_canvas_cursor_with (const string & txt)
+{
+       verbose_canvas_cursor->property_text() = txt.c_str();
+
+       int x, y;
+       double wx, wy;
+
+       track_canvas->get_pointer (x, y);
+       track_canvas->window_to_world (x, y, wx, wy);
+
+       /* move it away from the mouse pointer to avoid an
+          infinite loop of enter/leave events.
+       */
+
+       wx += 20;
+       wy += 20;
+
+       /* don't get too close to the edge */
+       verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (wx);
+       verbose_canvas_cursor->property_y() = clamp_verbose_cursor_y (wy);
+
+       show_verbose_canvas_cursor ();
+}
+
 void
 Editor::set_verbose_canvas_cursor (const string & txt, double x, double y)
 {
 void
 Editor::set_verbose_canvas_cursor (const string & txt, double x, double y)
 {
@@ -3527,7 +3455,7 @@ Editor::edit_mode_selection_done ()
        }
 
        Config->set_edit_mode (mode);
        }
 
        Config->set_edit_mode (mode);
-}      
+}
 
 void
 Editor::snap_type_selection_done ()
 
 void
 Editor::snap_type_selection_done ()
@@ -3561,12 +3489,12 @@ Editor::snap_type_selection_done ()
                snaptype = SnapToRegionSync;
        } else if (choice == _("CD Frames")) {
                snaptype = SnapToCDFrame;
                snaptype = SnapToRegionSync;
        } else if (choice == _("CD Frames")) {
                snaptype = SnapToCDFrame;
-       } else if (choice == _("SMPTE Frames")) {
-               snaptype = SnapToSMPTEFrame;
-       } else if (choice == _("SMPTE Seconds")) {
-               snaptype = SnapToSMPTESeconds;
-       } else if (choice == _("SMPTE Minutes")) {
-               snaptype = SnapToSMPTEMinutes;
+       } else if (choice == _("Timecode Frames")) {
+               snaptype = SnapToTimecodeFrame;
+       } else if (choice == _("Timecode Seconds")) {
+               snaptype = SnapToTimecodeSeconds;
+       } else if (choice == _("Timecode Minutes")) {
+               snaptype = SnapToTimecodeMinutes;
        } else if (choice == _("Seconds")) {
                snaptype = SnapToSeconds;
        } else if (choice == _("Minutes")) {
        } else if (choice == _("Seconds")) {
                snaptype = SnapToSeconds;
        } else if (choice == _("Minutes")) {
@@ -3577,7 +3505,7 @@ Editor::snap_type_selection_done ()
        if (ract) {
                ract->set_active ();
        }
        if (ract) {
                ract->set_active ();
        }
-}      
+}
 
 void
 Editor::snap_mode_selection_done ()
 
 void
 Editor::snap_mode_selection_done ()
@@ -3663,14 +3591,14 @@ Editor::zoom_focus_selection_done ()
                focus_type = ZoomFocusEdit;
        } else {
                focus_type = ZoomFocusMouse;
                focus_type = ZoomFocusEdit;
        } else {
                focus_type = ZoomFocusMouse;
-       } 
-       
+       }
+
        RefPtr<RadioAction> ract = zoom_focus_action (focus_type);
 
        if (ract) {
                ract->set_active ();
        }
        RefPtr<RadioAction> ract = zoom_focus_action (focus_type);
 
        if (ract) {
                ract->set_active ();
        }
-}      
+}
 
 gint
 Editor::edit_controls_button_release (GdkEventButton* ev)
 
 gint
 Editor::edit_controls_button_release (GdkEventButton* ev)
@@ -3709,16 +3637,16 @@ Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
                }
 
        } else if ((track != 0 && group == 0) || (track != 0 && group != 0 && !group->active_property (RouteGroup::Select))) {
                }
 
        } else if ((track != 0 && group == 0) || (track != 0 && group != 0 && !group->active_property (RouteGroup::Select))) {
-               
+
                /* just the view for this track
                 */
 
                v->push_back (track);
 
        } else {
                /* just the view for this track
                 */
 
                v->push_back (track);
 
        } else {
-               
+
                /* views for all tracks in the route group */
                /* views for all tracks in the route group */
-               
+
                for (i = track_views.begin(); i != track_views.end (); ++i) {
 
                        if (group == 0 || ((*i)->route_group() == group && group->active_property (RouteGroup::Select))) {
                for (i = track_views.begin(); i != track_views.end (); ++i) {
 
                        if (group == 0 || ((*i)->route_group() == group && group->active_property (RouteGroup::Select))) {
@@ -3726,7 +3654,7 @@ Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
                        }
                }
        }
                        }
                }
        }
-       
+
        return v;
 }
 
        return v;
 }
 
@@ -3738,7 +3666,7 @@ Editor::set_zoom_focus (ZoomFocus f)
        if (str != zoom_focus_selector.get_active_text()) {
                zoom_focus_selector.set_active_text (str);
        }
        if (str != zoom_focus_selector.get_active_text()) {
                zoom_focus_selector.set_active_text (str);
        }
-       
+
        if (zoom_focus != f) {
                zoom_focus = f;
 
        if (zoom_focus != f) {
                zoom_focus = f;
 
@@ -3754,7 +3682,7 @@ Editor::ensure_float (Window& win)
        win.set_transient_for (*this);
 }
 
        win.set_transient_for (*this);
 }
 
-void 
+void
 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 {
        /* recover or initialize pane positions. do this here rather than earlier because
 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 {
        /* recover or initialize pane positions. do this here rather than earlier because
@@ -3812,7 +3740,9 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 void
 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
 {
 void
 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
 {
-       if (tools_tearoff->torn_off() && 
+       cerr << "remove tearoff\n";
+
+       if (tools_tearoff->torn_off() &&
            mouse_mode_tearoff->torn_off()) {
                top_hbox.remove (toolbar_frame);
        }
            mouse_mode_tearoff->torn_off()) {
                top_hbox.remove (toolbar_frame);
        }
@@ -3821,6 +3751,7 @@ Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
 void
 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
 {
 void
 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
 {
+       cerr << "reattach tearoff\n";
        if (toolbar_frame.get_parent() == 0) {
                top_hbox.pack_end (toolbar_frame);
        }
        if (toolbar_frame.get_parent() == 0) {
                top_hbox.pack_end (toolbar_frame);
        }
@@ -3891,16 +3822,16 @@ Editor::edit_xfade (boost::weak_ptr<Crossfade> wxfade)
        }
 
        CrossfadeEditor cew (*session, xfade, xfade->fade_in().get_min_y(), 1.0);
        }
 
        CrossfadeEditor cew (*session, xfade, xfade->fade_in().get_min_y(), 1.0);
-               
+
        ensure_float (cew);
        ensure_float (cew);
-       
+
        switch (cew.run ()) {
        case RESPONSE_ACCEPT:
                break;
        default:
                return;
        }
        switch (cew.run ()) {
        case RESPONSE_ACCEPT:
                break;
        default:
                return;
        }
-       
+
        cew.apply ();
        xfade->StateChanged (Change (~0));
 }
        cew.apply ();
        xfade->StateChanged (Change (~0));
 }
@@ -3911,6 +3842,60 @@ Editor::playlist_selector () const
        return *_playlist_selector;
 }
 
        return *_playlist_selector;
 }
 
+Evoral::MusicalTime
+Editor::get_grid_type_as_beats (bool& success, nframes64_t position)
+{
+       success = true;
+
+       switch (_snap_type) {
+       case SnapToBeat:
+               return 1.0;
+               break;
+
+       case SnapToAThirtysecondBeat:
+               return 1.0/32.0;
+               break;
+
+       case SnapToASixteenthBeat:
+               return 1.0/16.0;
+               break;
+
+       case SnapToAEighthBeat:
+               return 1.0/8.0;
+               break;
+
+       case SnapToAQuarterBeat:
+               return 1.0/4.0;
+               break;
+
+       case SnapToAThirdBeat:
+               return 1.0/3.0;
+               break;
+
+       case SnapToBar:
+               if (session) {
+                       return session->tempo_map().meter_at (position).beats_per_bar();
+               }
+               break;
+
+       case SnapToCDFrame:
+       case SnapToTimecodeFrame:
+       case SnapToTimecodeSeconds:
+       case SnapToTimecodeMinutes:
+       case SnapToSeconds:
+       case SnapToMinutes:
+       case SnapToRegionStart:
+       case SnapToRegionEnd:
+       case SnapToRegionSync:
+       case SnapToRegionBoundary:
+       default:
+               success = false;
+               break;
+       }
+
+       return 0.0;
+}
+
 nframes64_t
 Editor::get_nudge_distance (nframes64_t pos, nframes64_t& next)
 {
 nframes64_t
 Editor::get_nudge_distance (nframes64_t pos, nframes64_t& next)
 {
@@ -3939,7 +3924,7 @@ Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
                                        "If left alone, no audio files used by it will be cleaned.\n"
                                        "If deleted, audio files used by it alone by will cleaned."),
                                      pl->name()));
                                        "If left alone, no audio files used by it will be cleaned.\n"
                                        "If deleted, audio files used by it alone by will cleaned."),
                                      pl->name()));
-       
+
        dialog.set_position (WIN_POS_CENTER);
        dialog.get_vbox()->pack_start (label);
 
        dialog.set_position (WIN_POS_CENTER);
        dialog.get_vbox()->pack_start (label);
 
@@ -4029,7 +4014,7 @@ Editor::control_layout_scroll (GdkEventScroll* ev)
        case GDK_SCROLL_DOWN:
                scroll_tracks_down_line ();
                return true;
        case GDK_SCROLL_DOWN:
                scroll_tracks_down_line ();
                return true;
-               
+
        default:
                /* no left/right handling yet */
                break;
        default:
                /* no left/right handling yet */
                break;
@@ -4042,7 +4027,7 @@ void
 Editor::session_state_saved (string snap_name)
 {
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::session_state_saved), snap_name));
 Editor::session_state_saved (string snap_name)
 {
        ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::session_state_saved), snap_name));
-       
+
        _snapshots->redisplay ();
 }
 
        _snapshots->redisplay ();
 }
 
@@ -4062,7 +4047,7 @@ Editor::maximise_editing_space ()
        fullscreen();
 
        if(post_maximal_editor_width) {
        fullscreen();
 
        if(post_maximal_editor_width) {
-               edit_pane.set_position (post_maximal_pane_position - 
+               edit_pane.set_position (post_maximal_pane_position -
                        abs(post_maximal_editor_width - pre_maximal_editor_width));
        } else {
                edit_pane.set_position (post_maximal_pane_position);
                        abs(post_maximal_editor_width - pre_maximal_editor_width));
        } else {
                edit_pane.set_position (post_maximal_pane_position);
@@ -4093,7 +4078,7 @@ Editor::restore_editing_space ()
  *  @param v Track.
  */
 
  *  @param v Track.
  */
 
-void 
+void
 Editor::new_playlists (TimeAxisView* v)
 {
        begin_reversible_command (_("new playlists"));
 Editor::new_playlists (TimeAxisView* v)
 {
        begin_reversible_command (_("new playlists"));
@@ -4124,7 +4109,7 @@ Editor::copy_playlists (TimeAxisView* v)
  *  @param v Track.
  */
 
  *  @param v Track.
  */
 
-void 
+void
 Editor::clear_playlists (TimeAxisView* v)
 {
        begin_reversible_command (_("clear playlists"));
 Editor::clear_playlists (TimeAxisView* v)
 {
        begin_reversible_command (_("clear playlists"));
@@ -4134,7 +4119,7 @@ Editor::clear_playlists (TimeAxisView* v)
        commit_reversible_command ();
 }
 
        commit_reversible_command ();
 }
 
-void 
+void
 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
 {
        atv.use_new_playlist (sz > 1 ? false : true, playlists);
 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
 {
        atv.use_new_playlist (sz > 1 ? false : true, playlists);
@@ -4146,7 +4131,7 @@ Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<bo
        atv.use_copy_playlist (sz > 1 ? false : true, playlists);
 }
 
        atv.use_copy_playlist (sz > 1 ? false : true, playlists);
 }
 
-void 
+void
 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
 {
        atv.clear_playlist ();
 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
 {
        atv.clear_playlist ();
@@ -4204,14 +4189,13 @@ Editor::current_visual_state (bool with_tracks)
        vs->frames_per_unit = frames_per_unit;
        vs->leftmost_frame = leftmost_frame;
        vs->zoom_focus = zoom_focus;
        vs->frames_per_unit = frames_per_unit;
        vs->leftmost_frame = leftmost_frame;
        vs->zoom_focus = zoom_focus;
-       vs->zoomed_to_region = zoomed_to_region;
 
        if (with_tracks) {
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        vs->track_states.push_back (TAVState ((*i), &(*i)->get_state()));
                }
        }
 
        if (with_tracks) {
                for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
                        vs->track_states.push_back (TAVState ((*i), &(*i)->get_state()));
                }
        }
-       
+
        return vs;
 }
 
        return vs;
 }
 
@@ -4262,22 +4246,21 @@ Editor::use_visual_state (VisualState& vs)
 
        set_zoom_focus (vs.zoom_focus);
        reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit);
 
        set_zoom_focus (vs.zoom_focus);
        reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit);
-       zoomed_to_region = vs.zoomed_to_region;
-       
+
        for (list<TAVState>::iterator i = vs.track_states.begin(); i != vs.track_states.end(); ++i) {
                TrackViewList::iterator t;
 
                /* check if the track still exists - it could have been deleted */
 
                if ((t = find (track_views.begin(), track_views.end(), i->first)) != track_views.end()) {
        for (list<TAVState>::iterator i = vs.track_states.begin(); i != vs.track_states.end(); ++i) {
                TrackViewList::iterator t;
 
                /* check if the track still exists - it could have been deleted */
 
                if ((t = find (track_views.begin(), track_views.end(), i->first)) != track_views.end()) {
-                       (*t)->set_state (*(i->second));
+                       (*t)->set_state (*(i->second), Stateful::loading_state_version);
                }
        }
 
 
        if (!vs.track_states.empty()) {
                _routes->update_visibility ();
                }
        }
 
 
        if (!vs.track_states.empty()) {
                _routes->update_visibility ();
-       } 
+       }
 
        _routes->resume_redisplay ();
 
 
        _routes->resume_redisplay ();
 
@@ -4299,7 +4282,7 @@ Editor::set_frames_per_unit (double fpu)
                fpu = 2.0;
        }
 
                fpu = 2.0;
        }
 
-       
+
        /* don't allow zooms that fit more than the maximum number
           of frames into an 800 pixel wide space.
        */
        /* don't allow zooms that fit more than the maximum number
           of frames into an 800 pixel wide space.
        */
@@ -4307,7 +4290,7 @@ Editor::set_frames_per_unit (double fpu)
        if (max_frames / fpu < 800.0) {
                return;
        }
        if (max_frames / fpu < 800.0) {
                return;
        }
-       
+
        if (tempo_lines)
                tempo_lines->tempo_map_changed();
 
        if (tempo_lines)
                tempo_lines->tempo_map_changed();
 
@@ -4367,17 +4350,17 @@ void
 Editor::queue_visual_change (nframes64_t where)
 {
        pending_visual_change.add (VisualChange::TimeOrigin);
 Editor::queue_visual_change (nframes64_t where)
 {
        pending_visual_change.add (VisualChange::TimeOrigin);
-       
+
        /* if we're moving beyond the end, make sure the upper limit of the horizontal adjustment
           can reach.
        */
        /* if we're moving beyond the end, make sure the upper limit of the horizontal adjustment
           can reach.
        */
-       
+
        if (where > session->current_end_frame()) {
                horizontal_adjustment.set_upper ((where + current_page_frames()) / frames_per_unit);
        }
        if (where > session->current_end_frame()) {
                horizontal_adjustment.set_upper ((where + current_page_frames()) / frames_per_unit);
        }
-       
+
        pending_visual_change.time_origin = where;
        pending_visual_change.time_origin = where;
-       
+
        ensure_visual_change_idle_handler ();
 }
 
        ensure_visual_change_idle_handler ();
 }
 
@@ -4388,7 +4371,7 @@ Editor::queue_visual_change (double fpu)
        pending_visual_change.frames_per_unit = fpu;
 
        ensure_visual_change_idle_handler ();
        pending_visual_change.frames_per_unit = fpu;
 
        ensure_visual_change_idle_handler ();
-       
+
 }
 
 void
 }
 
 void
@@ -4438,15 +4421,15 @@ Editor::idle_visual_changer ()
        if (p & VisualChange::YOrigin) {
                vertical_adjustment.set_value (pending_visual_change.y_origin);
        }
        if (p & VisualChange::YOrigin) {
                vertical_adjustment.set_value (pending_visual_change.y_origin);
        }
-       
+
        nframes64_t csf=0, cef=0;
        nframes64_t current_time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
        nframes64_t csf=0, cef=0;
        nframes64_t current_time_origin = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-       
+
        if (session) {
                csf = session->current_start_frame();
                cef = session->current_end_frame();
        }
        if (session) {
                csf = session->current_start_frame();
                cef = session->current_end_frame();
        }
-       
+
        /* if we seek beyond the current end of the canvas, move the end */
 
 #ifdef FIX_THIS_FOR_V3
        /* if we seek beyond the current end of the canvas, move the end */
 
 #ifdef FIX_THIS_FOR_V3
@@ -4456,7 +4439,7 @@ Editor::idle_visual_changer ()
                redisplay_tempo (true);
        }
 #endif
                redisplay_tempo (true);
        }
 #endif
-       
+
        if (current_time_origin != pending_visual_change.time_origin) {
                cef += current_page_frames() / 10; // Add a little extra so we can see the end marker
                horizontal_adjustment.set_upper (cef / frames_per_unit);
        if (current_time_origin != pending_visual_change.time_origin) {
                cef += current_page_frames() / 10; // Add a little extra so we can see the end marker
                horizontal_adjustment.set_upper (cef / frames_per_unit);
@@ -4467,7 +4450,7 @@ Editor::idle_visual_changer ()
        }
 
        _summary->set_overlays_dirty ();
        }
 
        _summary->set_overlays_dirty ();
-       
+
        //cerr << "Editor::idle_visual_changer () called ha v:l:u:ps:fpu = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << frames_per_unit << endl;//DEBUG
        pending_visual_change.idle_handler_id = -1;
        return 0; /* this is always a one-shot call */
        //cerr << "Editor::idle_visual_changer () called ha v:l:u:ps:fpu = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << frames_per_unit << endl;//DEBUG
        pending_visual_change.idle_handler_id = -1;
        return 0; /* this is always a one-shot call */
@@ -4478,7 +4461,7 @@ struct EditorOrderTimeAxisSorter {
            return a->order () < b->order ();
     }
 };
            return a->order () < b->order ();
     }
 };
-       
+
 void
 Editor::sort_track_selection (TrackSelection* sel)
 {
 void
 Editor::sort_track_selection (TrackSelection* sel)
 {
@@ -4510,7 +4493,7 @@ Editor::get_preferred_edit_position (bool ignore_playhead)
        case EditAtPlayhead:
                where = session->audible_frame();
                break;
        case EditAtPlayhead:
                where = session->audible_frame();
                break;
-               
+
        case EditAtSelectedMarker:
                if (!selection->markers.empty()) {
                        bool is_start;
        case EditAtSelectedMarker:
                if (!selection->markers.empty()) {
                        bool is_start;
@@ -4523,9 +4506,9 @@ Editor::get_preferred_edit_position (bool ignore_playhead)
                                }
                                break;
                        }
                                }
                                break;
                        }
-               } 
+               }
                /* fallthru */
                /* fallthru */
-               
+
        default:
        case EditAtMouse:
                if (!mouse_frame (where, ignored)) {
        default:
        case EditAtMouse:
                if (!mouse_frame (where, ignored)) {
@@ -4545,7 +4528,7 @@ Editor::set_loop_range (nframes64_t start, nframes64_t end, string cmd)
        if (!session) return;
 
        begin_reversible_command (cmd);
        if (!session) return;
 
        begin_reversible_command (cmd);
-       
+
        Location* tll;
 
        if ((tll = transport_loop_location()) == 0) {
        Location* tll;
 
        if ((tll = transport_loop_location()) == 0) {
@@ -4562,7 +4545,7 @@ Editor::set_loop_range (nframes64_t start, nframes64_t end, string cmd)
                XMLNode &after = tll->get_state();
                session->add_command (new MementoCommand<Location>(*tll, &before, &after));
        }
                XMLNode &after = tll->get_state();
                session->add_command (new MementoCommand<Location>(*tll, &before, &after));
        }
-       
+
        commit_reversible_command ();
 }
 
        commit_reversible_command ();
 }
 
@@ -4572,7 +4555,7 @@ Editor::set_punch_range (nframes64_t start, nframes64_t end, string cmd)
        if (!session) return;
 
        begin_reversible_command (cmd);
        if (!session) return;
 
        begin_reversible_command (cmd);
-       
+
        Location* tpl;
 
        if ((tpl = transport_punch_location()) == 0) {
        Location* tpl;
 
        if ((tpl = transport_punch_location()) == 0) {
@@ -4590,7 +4573,7 @@ Editor::set_punch_range (nframes64_t start, nframes64_t end, string cmd)
                XMLNode &after = tpl->get_state();
                session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
        }
                XMLNode &after = tpl->get_state();
                session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
        }
-       
+
        commit_reversible_command ();
 }
 
        commit_reversible_command ();
 }
 
@@ -4615,7 +4598,7 @@ Editor::get_regions_at (RegionSelection& rs, nframes64_t where, const TrackSelec
                if (rtv) {
                        boost::shared_ptr<Diskstream> ds;
                        boost::shared_ptr<Playlist> pl;
                if (rtv) {
                        boost::shared_ptr<Diskstream> ds;
                        boost::shared_ptr<Playlist> pl;
-                       
+
                        if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
 
                                Playlist::RegionList* regions = pl->regions_at (
                        if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
 
                                Playlist::RegionList* regions = pl->regions_at (
@@ -4650,7 +4633,7 @@ Editor::get_regions_after (RegionSelection& rs, nframes64_t where, const TrackSe
                if (rtv) {
                        boost::shared_ptr<Diskstream> ds;
                        boost::shared_ptr<Playlist> pl;
                if (rtv) {
                        boost::shared_ptr<Diskstream> ds;
                        boost::shared_ptr<Playlist> pl;
-                       
+
                        if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
 
                                Playlist::RegionList* regions = pl->regions_touched (
                        if ((ds = rtv->get_diskstream()) && ((pl = ds->playlist()))) {
 
                                Playlist::RegionList* regions = pl->regions_touched (
@@ -4675,12 +4658,12 @@ Editor::get_regions_after (RegionSelection& rs, nframes64_t where, const TrackSe
  *      - selected or
  *      - the entered_regionview (if allow_entered == true) or
  *      - under the preferred edit position AND on a selected track, or on a track
  *      - selected or
  *      - the entered_regionview (if allow_entered == true) or
  *      - under the preferred edit position AND on a selected track, or on a track
- *        which is in the same active edit-enable route group as a selected region.
+ *        which is in the same active edit-enable route group as a selected region (if allow_edit_position == true)
  *  @param rs Returned region list.
  *  @param allow_entered true to include the entered_regionview in the list.
  */
 void
  *  @param rs Returned region list.
  *  @param allow_entered true to include the entered_regionview in the list.
  */
 void
-Editor::get_regions_for_action (RegionSelection& rs, bool allow_entered)
+Editor::get_regions_for_action (RegionSelection& rs, bool allow_entered, bool allow_edit_position)
 {
        /* Start with selected regions */
        rs = selection->regions;
 {
        /* Start with selected regions */
        rs = selection->regions;
@@ -4690,23 +4673,22 @@ Editor::get_regions_for_action (RegionSelection& rs, bool allow_entered)
                rs.add (entered_regionview);
        }
 
                rs.add (entered_regionview);
        }
 
-       TrackSelection tracks = selection->tracks;
+       if (allow_edit_position) {
 
 
-       RegionSelection to_map = rs;
+               TrackSelection tracks = selection->tracks;
 
 
-       /* tracks is currently the set of selected tracks; add any other tracks that
-        * have regions that are in the same edit-activated route group as one of
-        * our regions */
-       for (RegionSelection::iterator i = to_map.begin (); i != to_map.end(); ++i) {
+               /* tracks is currently the set of selected tracks; add any other tracks that
+                * have regions that are in the same edit-activated route group as one of
+                * our regions */
+               for (RegionSelection::iterator i = rs.begin (); i != rs.end(); ++i) {
 
 
-               RouteGroup* g = (*i)->get_time_axis_view().route_group ();
-               if (g && g->active_property (RouteGroup::Edit)) {
-                       tracks.add (axis_views_from_routes (g->route_list()));
+                       RouteGroup* g = (*i)->get_time_axis_view().route_group ();
+                       if (g && g->active_property (RouteGroup::Edit)) {
+                               tracks.add (axis_views_from_routes (g->route_list()));
+                       }
                }
                }
-       }
 
 
-       /* now find regions that are at the edit position on those tracks */
-       for (RegionSelection::iterator i = to_map.begin (); i != to_map.end(); ++i) {
+               /* now find regions that are at the edit position on those tracks */
                nframes64_t const where = get_preferred_edit_position ();
                get_regions_at (rs, where, tracks);
        }
                nframes64_t const where = get_preferred_edit_position ();
                get_regions_at (rs, where, tracks);
        }
@@ -4716,34 +4698,34 @@ void
 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
 {
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
 {
        for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-               
+
                RouteTimeAxisView* tatv;
                RouteTimeAxisView* tatv;
-               
+
                if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
                if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
-                       
+
                        boost::shared_ptr<Playlist> pl;
                        vector<boost::shared_ptr<Region> > results;
                        RegionView* marv;
                        boost::shared_ptr<Diskstream> ds;
                        boost::shared_ptr<Playlist> pl;
                        vector<boost::shared_ptr<Region> > results;
                        RegionView* marv;
                        boost::shared_ptr<Diskstream> ds;
-                       
+
                        if ((ds = tatv->get_diskstream()) == 0) {
                                /* bus */
                                continue;
                        }
                        if ((ds = tatv->get_diskstream()) == 0) {
                                /* bus */
                                continue;
                        }
-                       
+
                        if ((pl = (ds->playlist())) != 0) {
                                pl->get_region_list_equivalent_regions (region, results);
                        }
                        if ((pl = (ds->playlist())) != 0) {
                                pl->get_region_list_equivalent_regions (region, results);
                        }
-                       
+
                        for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
                                if ((marv = tatv->view()->find_view (*ir)) != 0) {
                                        regions.push_back (marv);
                                }
                        }
                        for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
                                if ((marv = tatv->view()->find_view (*ir)) != 0) {
                                        regions.push_back (marv);
                                }
                        }
-                       
+
                }
        }
                }
        }
-}      
+}
 
 void
 Editor::show_rhythm_ferret ()
 
 void
 Editor::show_rhythm_ferret ()
@@ -4782,8 +4764,8 @@ Editor::first_idle ()
 {
        MessageDialog* dialog = 0;
 
 {
        MessageDialog* dialog = 0;
 
-       if (track_views.size() > 1) { 
-               dialog = new MessageDialog (*this, 
+       if (track_views.size() > 1) {
+               dialog = new MessageDialog (*this,
                                            _("Please wait while Ardour loads visual data"),
                                            true,
                                            Gtk::MESSAGE_INFO,
                                            _("Please wait while Ardour loads visual data"),
                                            true,
                                            Gtk::MESSAGE_INFO,
@@ -4798,7 +4780,7 @@ Editor::first_idle ()
 
        // first idle adds route children (automation tracks), so we need to redisplay here
        _routes->redisplay ();
 
        // first idle adds route children (automation tracks), so we need to redisplay here
        _routes->redisplay ();
-       
+
        delete dialog;
 
        _have_idled = true;
        delete dialog;
 
        _have_idled = true;
@@ -4852,18 +4834,18 @@ Editor::idle_resize ()
 
        if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
            selection->tracks.contains (_pending_resize_view)) {
 
        if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
            selection->tracks.contains (_pending_resize_view)) {
-               
+
                for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
                        if (*i != _pending_resize_view) {
                                (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
                        }
                }
        }
                for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
                        if (*i != _pending_resize_view) {
                                (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
                        }
                }
        }
-       
+
        flush_canvas ();
        _group_tabs->set_dirty ();
        resize_idle_id = -1;
        flush_canvas ();
        _group_tabs->set_dirty ();
        resize_idle_id = -1;
-       
+
        return false;
 }
 
        return false;
 }
 
@@ -4907,7 +4889,7 @@ TrackSelection
 Editor::axis_views_from_routes (list<Route*> r) const
 {
        TrackSelection t;
 Editor::axis_views_from_routes (list<Route*> r) const
 {
        TrackSelection t;
-       
+
        for (list<Route*>::const_iterator i = r.begin(); i != r.end(); ++i) {
                TimeAxisView* tv = axis_view_from_route (*i);
                if (tv) {
        for (list<Route*>::const_iterator i = r.begin(); i != r.end(); ++i) {
                TimeAxisView* tv = axis_view_from_route (*i);
                if (tv) {
@@ -4923,7 +4905,7 @@ void
 Editor::handle_new_route (RouteList& routes)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_route), routes));
 Editor::handle_new_route (RouteList& routes)
 {
        ENSURE_GUI_THREAD (bind (mem_fun (*this, &Editor::handle_new_route), routes));
-       
+
        RouteTimeAxisView *rtv;
        list<RouteTimeAxisView*> new_views;
 
        RouteTimeAxisView *rtv;
        list<RouteTimeAxisView*> new_views;
 
@@ -4946,12 +4928,12 @@ Editor::handle_new_route (RouteList& routes)
 
                new_views.push_back (rtv);
                track_views.push_back (rtv);
 
                new_views.push_back (rtv);
                track_views.push_back (rtv);
-               
+
                rtv->effective_gain_display ();
                rtv->effective_gain_display ();
-               
+
                rtv->view()->RegionViewAdded.connect (mem_fun (*this, &Editor::region_view_added));
                rtv->view()->HeightChanged.connect (mem_fun (*this, &Editor::streamview_height_changed));
                rtv->view()->RegionViewAdded.connect (mem_fun (*this, &Editor::region_view_added));
                rtv->view()->HeightChanged.connect (mem_fun (*this, &Editor::streamview_height_changed));
-               
+
                rtv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), rtv));
        }
 
                rtv->GoingAway.connect (bind (mem_fun(*this, &Editor::remove_route), rtv));
        }
 
@@ -4973,7 +4955,7 @@ Editor::remove_route (TimeAxisView *tv)
 
        TrackViewList::iterator i;
        boost::shared_ptr<Route> route;
 
        TrackViewList::iterator i;
        boost::shared_ptr<Route> route;
-       TimeAxisView* next_tv;
+       TimeAxisView* next_tv = 0;
 
        if (tv == entered_track) {
                entered_track = 0;
 
        if (tv == entered_track) {
                entered_track = 0;
@@ -4991,7 +4973,7 @@ Editor::remove_route (TimeAxisView *tv)
                       next_tv = (*i);
                }
        }
                       next_tv = (*i);
                }
        }
-       
+
        if (current_mixer_strip && current_mixer_strip->route() == route) {
 
                if (next_tv) {
        if (current_mixer_strip && current_mixer_strip->route() == route) {
 
                if (next_tv) {
@@ -5003,7 +4985,7 @@ Editor::remove_route (TimeAxisView *tv)
 
                        ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
                }
 
                        ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
                }
-       } 
+       }
 }
 
 void
 }
 
 void
@@ -5023,10 +5005,10 @@ bool
 Editor::sync_track_view_list_and_routes ()
 {
        track_views = TrackSelection (_routes->views ());
 Editor::sync_track_view_list_and_routes ()
 {
        track_views = TrackSelection (_routes->views ());
-       
+
        _summary->set_dirty ();
        _group_tabs->set_dirty ();
        _summary->set_dirty ();
        _group_tabs->set_dirty ();
-       
+
        return false; // do not call again (until needed)
 }
 
        return false; // do not call again (until needed)
 }
 
@@ -5107,3 +5089,27 @@ Editor::hide_region_from_region_list ()
        _regions->selection_mapover (mem_fun (*this, &Editor::hide_a_region));
 }
 
        _regions->selection_mapover (mem_fun (*this, &Editor::hide_a_region));
 }
 
+void
+Editor::start_step_editing ()
+{
+       step_edit_connection = Glib::signal_timeout().connect (mem_fun (*this, &Editor::check_step_edit), 20);
+}
+
+void
+Editor::stop_step_editing ()
+{
+       step_edit_connection.disconnect ();
+}
+
+bool
+Editor::check_step_edit ()
+{
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
+               if (mtv) {
+                       mtv->check_step_edit ();
+               }
+       }
+
+       return true; // do it again, till we stop
+}