Make MIDI region `automation' respect the automation mode so that it is
[ardour.git] / gtk2_ardour / editor.cc
index 98480743e04388141e5e3e0491f82585afc347da..0b6929e86ccdea07b372408c4d701fb4dac304eb 100644 (file)
 #include "editor_regions.h"
 #include "editor_locations.h"
 #include "editor_snapshots.h"
+#include "editor_summary.h"
 
 #include "i18n.h"
 
@@ -145,10 +146,19 @@ static const gchar *_snap_type_strings[] = {
        N_("Seconds"),
        N_("Minutes"),
        N_("Beats/32"),
+       N_("Beats/28"),
+       N_("Beats/24"),
        N_("Beats/16"),
+       N_("Beats/14"),
+       N_("Beats/12"),
+       N_("Beats/10"),
        N_("Beats/8"),
+       N_("Beats/7"),
+       N_("Beats/6"),
+       N_("Beats/5"),
        N_("Beats/4"),
        N_("Beats/3"),
+       N_("Beats/2"),
        N_("Beats"),
        N_("Bars"),
        N_("Marks"),
@@ -200,6 +210,10 @@ static const gchar *_rb_opt_strings[] = {
 Gdk::Cursor* Editor::cross_hair_cursor = 0;
 Gdk::Cursor* Editor::selector_cursor = 0;
 Gdk::Cursor* Editor::trimmer_cursor = 0;
+Gdk::Cursor* Editor::left_side_trim_cursor = 0;
+Gdk::Cursor* Editor::right_side_trim_cursor = 0;
+Gdk::Cursor* Editor::fade_in_cursor = 0;
+Gdk::Cursor* Editor::fade_out_cursor = 0;
 Gdk::Cursor* Editor::grabber_cursor = 0;
 Gdk::Cursor* Editor::grabber_edit_point_cursor = 0;
 Gdk::Cursor* Editor::zoom_cursor = 0;
@@ -262,7 +276,6 @@ Editor::Editor ()
          */
 
        , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
-       , horizontal_adjustment (0.0, 0.0, 20.0, 1200.0)
 
          /* tool bar related */
 
@@ -391,6 +404,8 @@ Editor::Editor ()
 
        frames_per_unit = 2048; /* too early to use reset_zoom () */
 
+       _scroll_callbacks = 0;
+
        zoom_focus = ZoomFocusLeft;
        set_zoom_focus (ZoomFocusLeft);
        zoom_range_clock.ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
@@ -468,7 +483,6 @@ Editor::Editor ()
        selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
 
        edit_controls_vbox.set_spacing (0);
-       horizontal_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::scroll_canvas_horizontally), false);
        vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
        track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
 
@@ -547,7 +561,7 @@ Editor::Editor ()
        nlabel = manage (new Label (_("Regions")));
        nlabel->set_angle (-90);
        the_notebook.append_page (_regions->widget (), *nlabel);
-       nlabel = manage (new Label (_("Tracks/Busses")));
+       nlabel = manage (new Label (_("Tracks & Busses")));
        nlabel->set_angle (-90);
        the_notebook.append_page (_routes->widget (), *nlabel);
        nlabel = manage (new Label (_("Snapshots")));
@@ -567,27 +581,32 @@ Editor::Editor ()
        the_notebook.show_all ();
        
        post_maximal_editor_width = 0;
-       post_maximal_pane_position = 0;
+       post_maximal_horizontal_pane_position = 0;
+       post_maximal_editor_height = 0;
+       post_maximal_vertical_pane_position = 0;
 
-       VPaned *editor_summary_pane = manage(new VPaned());
-       editor_summary_pane->pack1(edit_packer);
+       editor_summary_pane.pack1(edit_packer);
 
        Button* summary_arrows_left_left = manage (new Button);
        summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
-       summary_arrows_left_left->signal_clicked().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left));
+       summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_press)));
+       summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_release));
        Button* summary_arrows_left_right = manage (new Button);
        summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
-       summary_arrows_left_right->signal_clicked().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right));
+       summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_press)));
+       summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_release));
        VBox* summary_arrows_left = manage (new VBox);
        summary_arrows_left->pack_start (*summary_arrows_left_left);
        summary_arrows_left->pack_start (*summary_arrows_left_right);
 
        Button* summary_arrows_right_left = manage (new Button);
        summary_arrows_right_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
-       summary_arrows_right_left->signal_clicked().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left));
+       summary_arrows_right_left->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_press)));
+       summary_arrows_right_left->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_release));
        Button* summary_arrows_right_right = manage (new Button);
        summary_arrows_right_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
-       summary_arrows_right_right->signal_clicked().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right));
+       summary_arrows_right_right->signal_pressed().connect (sigc::hide_return (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_press)));
+       summary_arrows_right_right->signal_released().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_release));
        VBox* summary_arrows_right = manage (new VBox);
        summary_arrows_right->pack_start (*summary_arrows_right_left);
        summary_arrows_right->pack_start (*summary_arrows_right_right);
@@ -601,11 +620,15 @@ Editor::Editor ()
        _summary_hbox.pack_start (*summary_frame, true, true);
        _summary_hbox.pack_start (*summary_arrows_right, false, false);
        
-       editor_summary_pane->pack2 (_summary_hbox);
+       editor_summary_pane.pack2 (_summary_hbox);
 
-       edit_pane.pack1 (*editor_summary_pane, true, true);
+       edit_pane.pack1 (editor_summary_pane, true, true);
        edit_pane.pack2 (the_notebook, false, true);
 
+       editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
+
+       /* XXX: editor_summary_pane might need similar special OS X treatment to the edit_pane */
+
        edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
 #ifdef GTKOSX
         Glib::PropertyProxy<int> proxy = edit_pane.property_position();
@@ -992,24 +1015,6 @@ Editor::center_screen_internal (nframes64_t frame, float page)
        reset_x_origin (frame);
 }
 
-void
-Editor::handle_new_duration ()
-{
-       if (!_session) {
-               return;
-       }
-
-       ENSURE_GUI_THREAD (*this, &Editor::handle_new_duration)
-       nframes64_t new_end = _session->current_end_frame() + (nframes64_t) floorf (current_page_frames() * 0.10f);
-
-       horizontal_adjustment.set_upper (new_end / frames_per_unit);
-       horizontal_adjustment.set_page_size (current_page_frames()/frames_per_unit);
-
-       if (horizontal_adjustment.get_value() + _canvas_width > horizontal_adjustment.get_upper()) {
-               horizontal_adjustment.set_value (horizontal_adjustment.get_upper() - _canvas_width);
-       }
-       //cerr << "Editor::handle_new_duration () called ha v:l:u:ps:lcf = " << horizontal_adjustment.get_value() << ":" << horizontal_adjustment.get_lower() << ":" << horizontal_adjustment.get_upper() << ":" << horizontal_adjustment.get_page_size() << ":" << endl;//DEBUG
-}
 
 void
 Editor::update_title ()
@@ -1092,7 +1097,6 @@ Editor::set_session (Session *t)
        _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
        _session->PositionChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::map_position_change, this, _1), gui_context());
        _session->RouteAdded.connect (_session_connections, invalidator (*this), ui_bind (&Editor::handle_new_route, this, _1), gui_context());
-       _session->DurationChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::handle_new_duration, this), gui_context());
        _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
        _session->TimecodeOffsetChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_just_timecode, this), gui_context());
        _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::tempo_map_changed, this, _1), gui_context());
@@ -1103,7 +1107,6 @@ Editor::set_session (Session *t)
        _session->locations()->removed.connect (_session_connections, invalidator (*this), ui_bind (&Editor::location_gone, this, _1), gui_context());
        _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
        _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), ui_bind (&Editor::refresh_location_display_s, this, _1), gui_context());
-       _session->locations()->session_range_location()->changed.connect (_session_connections, invalidator (*this), ui_bind (&Editor::session_range_location_changed, this, _1), gui_context());
        _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
 
        if (Profile->get_sae()) {
@@ -1152,7 +1155,6 @@ Editor::set_session (Session *t)
        _session->config.map_parameters (pc);
 
        refresh_location_display ();
-       handle_new_duration ();
 
        restore_ruler_visibility ();
        //tempo_map_changed (PropertyChange (0));
@@ -1243,6 +1245,27 @@ Editor::build_cursors ()
 
        cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
        trimmer_cursor =  new Gdk::Cursor (SB_H_DOUBLE_ARROW);
+
+       {
+               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("trim_left_cursor"));
+               left_side_trim_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 5, 11);
+       }
+
+       {
+               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("trim_right_cursor"));
+               right_side_trim_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 23, 11);
+       }
+
+       {
+               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("fade_in_cursor"));
+               fade_in_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 0, 40);
+       }
+
+       {
+               Glib::RefPtr<Gdk::Pixbuf> apixbuf (::get_icon ("fade_out_cursor"));
+               fade_out_cursor = new Gdk::Cursor (Gdk::Display::get_default(), apixbuf, 27, 40);
+       }
+
        selector_cursor = new Gdk::Cursor (XTERM);
        time_fx_cursor = new Gdk::Cursor (SIZING);
        wait_cursor = new Gdk::Cursor  (WATCH);
@@ -1337,6 +1360,8 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
        case RegionItem:
        case RegionViewName:
        case RegionViewNameHighlight:
+       case LeftFrameHandle:
+       case RightFrameHandle:
                if (with_selection) {
                        build_menu_function = &Editor::build_track_selection_context_menu;
                } else {
@@ -1378,6 +1403,8 @@ Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type,
        case RegionItem:
        case RegionViewName:
        case RegionViewNameHighlight:
+        case LeftFrameHandle:
+        case RightFrameHandle:
                if (!with_selection) {
                        if (region_edit_menu_split_item) {
                                if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
@@ -1684,11 +1711,10 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
                        sigc::bind (sigc::mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
 
                items.push_back (MenuElem (_("Rename..."), sigc::mem_fun(*this, &Editor::rename_region)));
-               if (mr && internal_editing()) {
-                       items.push_back (MenuElem (_("List editor..."), sigc::mem_fun(*this, &Editor::show_midi_list_editor)));
-               } else {
-                       items.push_back (MenuElem (_("Region Properties..."), sigc::mem_fun(*this, &Editor::edit_region)));
+               if (mr) {
+                       items.push_back (MenuElem (_("List Editor..."), sigc::mem_fun(*this, &Editor::show_midi_list_editor)));
                }
+               items.push_back (MenuElem (_("Region Properties..."), sigc::mem_fun(*this, &Editor::edit_region)));
        }
 
        items.push_back (MenuElem (_("Raise to Top Layer"), sigc::mem_fun(*this, &Editor::raise_region_to_top)));
@@ -1807,6 +1833,7 @@ Editor::add_region_context_items (StreamView* sv, boost::shared_ptr<Region> regi
 
        } else if (mr) {
                items.push_back (MenuElem (_("Quantize"), sigc::mem_fun(*this, &Editor::quantize_region)));
+               items.push_back (MenuElem (_("Fork"), sigc::mem_fun(*this, &Editor::fork_region)));
                items.push_back (SeparatorElem());
        }
 
@@ -1939,7 +1966,7 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
        edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
        edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
        edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
-       edit_items.push_back (MenuElem (_("Export Range"), sigc::mem_fun(*this, &Editor::export_range)));
+       edit_items.push_back (MenuElem (_("Export Range"), sigc::mem_fun(*this, &Editor::export_selection)));
 }
 
 
@@ -2113,11 +2140,20 @@ Editor::set_snap_to (SnapType st)
        instant_save ();
 
        switch (_snap_type) {
-       case SnapToAThirtysecondBeat:
-       case SnapToASixteenthBeat:
-       case SnapToAEighthBeat:
-       case SnapToAQuarterBeat:
-       case SnapToAThirdBeat:
+       case SnapToBeatDiv32:
+       case SnapToBeatDiv28:
+       case SnapToBeatDiv24:
+       case SnapToBeatDiv16:
+       case SnapToBeatDiv14:
+       case SnapToBeatDiv12:
+       case SnapToBeatDiv10:
+       case SnapToBeatDiv8:
+       case SnapToBeatDiv7:
+       case SnapToBeatDiv6:
+       case SnapToBeatDiv5:
+       case SnapToBeatDiv4:
+       case SnapToBeatDiv3:
+       case SnapToBeatDiv2:
                compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_frames());
                update_tempo_based_rulers ();
                break;
@@ -2132,7 +2168,9 @@ Editor::set_snap_to (SnapType st)
        default:
                /* relax */
                break;
-    }
+       }
+
+       SnapChanged (); /* EMIT SIGNAL */
 }
 
 void
@@ -2409,10 +2447,6 @@ Editor::set_state (const XMLNode& node, int /*version*/)
                the_notebook.set_current_page (atoi (prop->value ()));
        }
 
-       if ((prop = node.property (X_("editor-pane-position")))) {
-               edit_pane.set_position (atoi (prop->value ()));
-       }
-
        return 0;
 }
 
@@ -2448,7 +2482,9 @@ Editor::get_state ()
                snprintf(buf, sizeof(buf), "%d", yoff);
                geometry->add_property("y-off", string(buf));
                snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
-               geometry->add_property("edit_pane_pos", string(buf));
+               geometry->add_property("edit-horizontal-pane-pos", string(buf));
+               snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
+               geometry->add_property("edit-vertical-pane-pos", string(buf));
 
                node->add_child_nocopy (*geometry);
        }
@@ -2497,9 +2533,6 @@ Editor::get_state ()
        snprintf (buf, sizeof (buf), "%d", the_notebook.get_current_page ());
        node->add_property (X_("editor-list-page"), buf);
 
-       snprintf (buf, sizeof (buf), "%d", edit_pane.get_position ());
-       node->add_property (X_("editor-pane-position"), buf);
-
        return *node;
 }
 
@@ -2665,25 +2698,48 @@ Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
                start = _session->tempo_map().round_to_beat (start, direction);
                break;
 
-       case SnapToAThirtysecondBeat:
+       case SnapToBeatDiv32:
                start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
                break;
-
-       case SnapToASixteenthBeat:
+       case SnapToBeatDiv28:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
+               break;
+       case SnapToBeatDiv24:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
+               break;
+       case SnapToBeatDiv16:
                start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
                break;
-
-       case SnapToAEighthBeat:
+       case SnapToBeatDiv14:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
+               break;
+       case SnapToBeatDiv12:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
+               break;
+       case SnapToBeatDiv10:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
+               break;
+       case SnapToBeatDiv8:
                start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
                break;
-
-       case SnapToAQuarterBeat:
+       case SnapToBeatDiv7:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
+               break;
+       case SnapToBeatDiv6:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
+               break;
+       case SnapToBeatDiv5:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
+               break;
+       case SnapToBeatDiv4:
                start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
                break;
-
-       case SnapToAThirdBeat:
+       case SnapToBeatDiv3:
                start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
                break;
+       case SnapToBeatDiv2:
+               start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
+               break;
 
        case SnapToMark:
                if (for_mark) {
@@ -2990,7 +3046,6 @@ void
 Editor::setup_tooltips ()
 {
        ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Select/Move Objects"));
-       ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Select/Move Ranges"));
        ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Gain Automation"));
        ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
        ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions"));
@@ -3442,16 +3497,34 @@ Editor::snap_type_selection_done ()
        string choice = snap_type_selector.get_active_text();
        SnapType snaptype = SnapToBeat;
 
-       if (choice == _("Beats/3")) {
-               snaptype = SnapToAThirdBeat;
+       if (choice == _("Beats/2")) {
+               snaptype = SnapToBeatDiv2;
+       } else if (choice == _("Beats/3")) {
+               snaptype = SnapToBeatDiv3;
        } else if (choice == _("Beats/4")) {
-               snaptype = SnapToAQuarterBeat;
+               snaptype = SnapToBeatDiv4;
+       } else if (choice == _("Beats/5")) {
+               snaptype = SnapToBeatDiv5;
+       } else if (choice == _("Beats/6")) {
+               snaptype = SnapToBeatDiv6;
+       } else if (choice == _("Beats/7")) {
+               snaptype = SnapToBeatDiv7;
        } else if (choice == _("Beats/8")) {
-               snaptype = SnapToAEighthBeat;
+               snaptype = SnapToBeatDiv8;
+       } else if (choice == _("Beats/10")) {
+               snaptype = SnapToBeatDiv10;
+       } else if (choice == _("Beats/12")) {
+               snaptype = SnapToBeatDiv12;
+       } else if (choice == _("Beats/14")) {
+               snaptype = SnapToBeatDiv14;
        } else if (choice == _("Beats/16")) {
-               snaptype = SnapToASixteenthBeat;
+               snaptype = SnapToBeatDiv16;
+       } else if (choice == _("Beats/24")) {
+               snaptype = SnapToBeatDiv24;
+       } else if (choice == _("Beats/28")) {
+               snaptype = SnapToBeatDiv28;
        } else if (choice == _("Beats/32")) {
-               snaptype = SnapToAThirtysecondBeat;
+               snaptype = SnapToBeatDiv32;
        } else if (choice == _("Beats")) {
                snaptype = SnapToBeat;
        } else if (choice == _("Bars")) {
@@ -3632,7 +3705,14 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
        char buf[32];
        XMLNode* node = ARDOUR_UI::instance()->editor_settings();
        int width, height;
-       static int32_t done;
+
+       enum Pane {
+               Horizontal = 0x1,
+               Vertical = 0x2
+       };
+
+       static Pane done;
+       
        XMLNode* geometry;
 
        width = default_width;
@@ -3640,15 +3720,11 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 
        if ((geometry = find_named_node (*node, "geometry")) != 0) {
 
-               if ((prop = geometry->property ("x_size")) == 0) {
-                       prop = geometry->property ("x-size");
-               }
+               prop = geometry->property ("x-size");
                if (prop) {
                        width = atoi (prop->value());
                }
-               if ((prop = geometry->property ("y_size")) == 0) {
-                       prop = geometry->property ("y-size");
-               }
+               prop = geometry->property ("y-size");
                if (prop) {
                        height = atoi (prop->value());
                }
@@ -3656,11 +3732,11 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
 
        if (which == static_cast<Paned*> (&edit_pane)) {
 
-               if (done) {
+               if (done & Horizontal) {
                        return;
                }
 
-               if (!geometry || (prop = geometry->property ("edit-pane-pos")) == 0) {
+               if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
                        /* initial allocation is 90% to canvas, 10% to notebook */
                        pos = (int) floor (alloc.get_width() * 0.90f);
                        snprintf (buf, sizeof(buf), "%d", pos);
@@ -3668,10 +3744,33 @@ Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
                        pos = atoi (prop->value());
                }
 
-               if ((done = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
+               if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
                        edit_pane.set_position (pos);
-                       pre_maximal_pane_position = pos;
+                       pre_maximal_horizontal_pane_position = pos;
+               }
+
+               done = (Pane) (done | Horizontal);
+               
+       } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
+
+               if (done & Vertical) {
+                       return;
+               }
+
+               if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
+                       /* initial allocation is 90% to canvas, 10% to summary */
+                       pos = (int) floor (alloc.get_height() * 0.90f);
+                       snprintf (buf, sizeof(buf), "%d", pos);
+               } else {
+                       pos = atoi (prop->value());
                }
+
+               if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
+                       editor_summary_pane.set_position (pos);
+                       pre_maximal_vertical_pane_position = pos;
+               }
+
+               done = (Pane) (done | Vertical);
        }
 }
 
@@ -3812,25 +3911,48 @@ Editor::get_grid_type_as_beats (bool& success, nframes64_t position)
                return 1.0;
                break;
 
-       case SnapToAThirtysecondBeat:
+       case SnapToBeatDiv32:
                return 1.0/32.0;
                break;
-
-       case SnapToASixteenthBeat:
+       case SnapToBeatDiv28:
+               return 1.0/28.0;
+               break;
+       case SnapToBeatDiv24:
+               return 1.0/24.0;
+               break;
+       case SnapToBeatDiv16:
                return 1.0/16.0;
                break;
-
-       case SnapToAEighthBeat:
+       case SnapToBeatDiv14:
+               return 1.0/14.0;
+               break;
+       case SnapToBeatDiv12:
+               return 1.0/12.0;
+               break;
+       case SnapToBeatDiv10:
+               return 1.0/10.0;
+               break;
+       case SnapToBeatDiv8:
                return 1.0/8.0;
                break;
-
-       case SnapToAQuarterBeat:
+       case SnapToBeatDiv7:
+               return 1.0/7.0;
+               break;
+       case SnapToBeatDiv6:
+               return 1.0/6.0;
+               break;
+       case SnapToBeatDiv5:
+               return 1.0/5.0;
+               break;
+       case SnapToBeatDiv4:
                return 1.0/4.0;
                break;
-
-       case SnapToAThirdBeat:
+       case SnapToBeatDiv3:
                return 1.0/3.0;
                break;
+       case SnapToBeatDiv2:
+               return 1.0/2.0;
+               break;
 
        case SnapToBar:
                if (_session) {
@@ -3867,19 +3989,10 @@ Editor::get_nudge_distance (nframes64_t pos, nframes64_t& next)
        return ret;
 }
 
-void
-Editor::session_range_location_changed (Location* location)
-{
-       ENSURE_GUI_THREAD (*this, &Editor::session_range_location_changed, location)
-       //reset_scrolling_region ();
-       nframes64_t const session_span = location->end() + (nframes64_t) floorf (current_page_frames() * 0.10f);
-       horizontal_adjustment.set_upper (session_span / frames_per_unit);
-}
-
 int
 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
 {
-       ArdourDialog dialog ("playlist deletion dialog");
+       ArdourDialog dialog (_("Playlist Deletion"));
        Label  label (string_compose (_("Playlist %1 is currently unused.\n"
                                        "If left alone, no audio files used by it will be cleaned.\n"
                                        "If deleted, audio files used by it alone by will cleaned."),
@@ -4002,39 +4115,58 @@ Editor::maximise_editing_space ()
        _mouse_mode_tearoff->set_visible (false);
        _tools_tearoff->set_visible (false);
 
-       pre_maximal_pane_position = edit_pane.get_position();
-       pre_maximal_editor_width = this->get_width();
+       pre_maximal_horizontal_pane_position = edit_pane.get_position ();
+       pre_maximal_vertical_pane_position = editor_summary_pane.get_position ();
+       pre_maximal_editor_width = this->get_width ();
+       pre_maximal_editor_height = this->get_height ();
 
-       if(post_maximal_pane_position == 0) {
-               post_maximal_pane_position = edit_pane.get_width();
+       if (post_maximal_horizontal_pane_position == 0) {
+               post_maximal_horizontal_pane_position = edit_pane.get_width();
        }
 
-       fullscreen();
+       if (post_maximal_vertical_pane_position == 0) {
+               post_maximal_vertical_pane_position = editor_summary_pane.get_height();
+       }
+       
+       fullscreen ();
 
-       if(post_maximal_editor_width) {
-               edit_pane.set_position (post_maximal_pane_position -
+       if (post_maximal_editor_width) {
+               edit_pane.set_position (post_maximal_horizontal_pane_position -
                        abs(post_maximal_editor_width - pre_maximal_editor_width));
        } else {
-               edit_pane.set_position (post_maximal_pane_position);
+               edit_pane.set_position (post_maximal_horizontal_pane_position);
+       }
+
+       if (post_maximal_editor_height) {
+               editor_summary_pane.set_position (post_maximal_vertical_pane_position -
+                       abs(post_maximal_editor_height - pre_maximal_editor_height));
+       } else {
+               editor_summary_pane.set_position (post_maximal_vertical_pane_position);
        }
 }
 
 void
 Editor::restore_editing_space ()
 {
-       // user changed width of pane during fullscreen
+       // user changed width/height of panes during fullscreen
 
-       if(post_maximal_pane_position != edit_pane.get_position()) {
-               post_maximal_pane_position = edit_pane.get_position();
+       if (post_maximal_horizontal_pane_position != edit_pane.get_position()) {
+               post_maximal_horizontal_pane_position = edit_pane.get_position();
        }
 
+       if (post_maximal_vertical_pane_position != editor_summary_pane.get_position()) {
+               post_maximal_vertical_pane_position = editor_summary_pane.get_position();
+       }
+       
        unfullscreen();
 
        _mouse_mode_tearoff->set_visible (true);
        _tools_tearoff->set_visible (true);
        post_maximal_editor_width = this->get_width();
+       post_maximal_editor_height = this->get_height();
 
-       edit_pane.set_position (pre_maximal_pane_position + abs(this->get_width() - pre_maximal_editor_width));
+       edit_pane.set_position (pre_maximal_horizontal_pane_position + abs(this->get_width() - pre_maximal_editor_width));
+       editor_summary_pane.set_position (pre_maximal_vertical_pane_position + abs(this->get_height() - pre_maximal_editor_height));
 }
 
 /**
@@ -4139,7 +4271,6 @@ Editor::reset_zoom (double fpu)
 void
 Editor::reposition_and_zoom (nframes64_t frame, double fpu)
 {
-       //cerr << "Editor::reposition_and_zoom () 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
        reset_x_origin (frame);
        reset_zoom (fpu);
 
@@ -4270,8 +4401,6 @@ Editor::set_frames_per_unit (double fpu)
 void
 Editor::post_zoom ()
 {
-       nframes64_t cef = 0;
-
        // convert fpu to frame count
 
        nframes64_t frames = (nframes64_t) floor (frames_per_unit * _canvas_width);
@@ -4286,15 +4415,8 @@ Editor::post_zoom ()
                }
        }
 
-       leftmost_frame = (nframes64_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
-
        ZoomChanged (); /* EMIT_SIGNAL */
 
-       if (_session) {
-               cef = _session->current_end_frame() + (current_page_frames() / 10);// Add a little extra so we can see the end marker
-       }
-       horizontal_adjustment.set_upper (cef / frames_per_unit);
-
        //reset_scrolling_region ();
 
        if (playhead_cursor) {
@@ -4311,17 +4433,7 @@ void
 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 (_session && (where > _session->current_end_frame())) {
-               horizontal_adjustment.set_upper ((where + current_page_frames()) / frames_per_unit);
-       }
-
        pending_visual_change.time_origin = where;
-
        ensure_visual_change_idle_handler ();
 }
 
@@ -4363,7 +4475,7 @@ Editor::idle_visual_changer ()
        VisualChange::Type p = pending_visual_change.pending;
        pending_visual_change.pending = (VisualChange::Type) 0;
 
-       double last_time_origin = horizontal_adjustment.get_value();
+       double last_time_origin = horizontal_position ();
 
        if (p & VisualChange::ZoomLevel) {
                set_frames_per_unit (pending_visual_change.frames_per_unit);
@@ -4374,13 +4486,13 @@ Editor::idle_visual_changer ()
                update_tempo_based_rulers ();
        }
        if (p & VisualChange::TimeOrigin) {
-               horizontal_adjustment.set_value (pending_visual_change.time_origin / frames_per_unit);
+               set_horizontal_position (pending_visual_change.time_origin / frames_per_unit);
        }
        if (p & VisualChange::YOrigin) {
                vertical_adjustment.set_value (pending_visual_change.y_origin);
        }
 
-       if (last_time_origin == horizontal_adjustment.get_value()) {
+       if (last_time_origin == horizontal_position ()) {
                /* changed signal not emitted */
                update_fixed_rulers ();
                redisplay_tempo (true);
@@ -4388,7 +4500,6 @@ Editor::idle_visual_changer ()
 
        _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 */
 }
@@ -4751,8 +4862,8 @@ Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
        }
 
        /* clamp */
-       if (uint32_t (min_resulting) < TimeAxisView::hSmall) {
-               _pending_resize_amount += TimeAxisView::hSmall - min_resulting;
+       if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
+               _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
        }
 }
 
@@ -4800,12 +4911,6 @@ Editor::region_view_added (RegionView *)
        _summary->set_dirty ();
 }
 
-void
-Editor::streamview_height_changed ()
-{
-       _summary->set_dirty ();
-}
-
 TimeAxisView*
 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
 {
@@ -4869,7 +4974,6 @@ Editor::handle_new_route (RouteList& routes)
                rtv->effective_gain_display ();
 
                rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
-               rtv->view()->HeightChanged.connect (sigc::mem_fun (*this, &Editor::streamview_height_changed));
        }
 
        _routes->routes_added (new_views);
@@ -4943,16 +5047,16 @@ Editor::timeaxisview_deleted (TimeAxisView *tv)
 }
 
 void
-Editor::hide_track_in_display (TimeAxisView& tv, bool /*temponly*/)
+Editor::hide_track_in_display (TimeAxisView* tv, bool /*temponly*/)
 {
-       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (&tv);
+       RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
 
        if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
                // this will hide the mixer strip
-               set_selected_mixer_strip (tv);
+               set_selected_mixer_strip (*tv);
        }
 
-       _routes->hide_track_in_display (tv);
+       _routes->hide_track_in_display (*tv);
 }
 
 bool
@@ -5074,21 +5178,63 @@ Editor::check_step_edit ()
        return true; // do it again, till we stop
 }
 
-void
-Editor::horizontal_scroll_left ()
+bool
+Editor::horizontal_scroll_left_press ()
 {
+       ++_scroll_callbacks;
+       
+       if (_scroll_connection.connected() && _scroll_callbacks < 5) {
+               /* delay the first auto-repeat */
+               return true;
+       }
+               
        double x = leftmost_position() - current_page_frames() / 5;
        if (x < 0) {
                x = 0;
        }
        
        reset_x_origin (x);
+
+       /* do hacky auto-repeat */
+       if (!_scroll_connection.connected ()) {
+               _scroll_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_left_press), 100);
+               _scroll_callbacks = 0;
+       }
+
+       return true;
 }
 
 void
-Editor::horizontal_scroll_right ()
+Editor::horizontal_scroll_left_release ()
 {
+       _scroll_connection.disconnect ();
+}
+
+bool
+Editor::horizontal_scroll_right_press ()
+{
+       ++_scroll_callbacks;
+       
+       if (_scroll_connection.connected() && _scroll_callbacks < 5) {
+               /* delay the first auto-repeat */
+               return true;
+       }
+
        reset_x_origin (leftmost_position() + current_page_frames() / 5);
+
+       /* do hacky auto-repeat */
+       if (!_scroll_connection.connected ()) {
+               _scroll_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::horizontal_scroll_right_press), 100);
+               _scroll_callbacks = 0;
+       }
+
+       return true;
+}
+
+void
+Editor::horizontal_scroll_right_release ()
+{
+       _scroll_connection.disconnect ();
 }
 
 /** Queue a change for the Editor viewport x origin to follow the playhead */
@@ -5209,7 +5355,7 @@ Editor::super_rapid_screen_update ()
                         }
                         
                         current = target;
-                        horizontal_adjustment.set_value (current);
+                        set_horizontal_position (current);
 #endif
                 }