size various ArdourDropdowns according to the pixel width, not character length,...
[ardour.git] / gtk2_ardour / editor.cc
index 57ae65e9a5a410fcd850cf51bcc2ee24535f6f0a..65230bf33396b75f5ad6b6e572aa48e377a2d91a 100644 (file)
 #include "pbd/unknown_type.h"
 #include "pbd/unwind.h"
 #include "pbd/stacktrace.h"
+#include "pbd/timersub.h"
 
 #include <glibmm/miscutils.h>
+#include <glibmm/uriutils.h>
 #include <gtkmm/image.h>
 #include <gdkmm/color.h>
 #include <gdkmm/bitmap.h>
 
+#include <gtkmm/menu.h>
+#include <gtkmm/menuitem.h>
+
 #include "gtkmm2ext/bindings.h"
 #include "gtkmm2ext/grouped_buttons.h"
 #include "gtkmm2ext/gtk_ui.h"
 #include "tempo_lines.h"
 #include "time_axis_view.h"
 #include "utils.h"
+#include "verbose_cursor.h"
 
 #include "i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
+using namespace ARDOUR_UI_UTILS;
 using namespace PBD;
 using namespace Gtk;
 using namespace Glib;
@@ -135,9 +142,9 @@ const double Editor::timebar_height = 15.0;
 
 static const gchar *_snap_type_strings[] = {
        N_("CD Frames"),
-       N_("Timecode Frames"),
-       N_("Timecode Seconds"),
-       N_("Timecode Minutes"),
+       N_("TC Frames"),
+       N_("TC Seconds"),
+       N_("TC Minutes"),
        N_("Seconds"),
        N_("Minutes"),
        N_("Beats/128"),
@@ -181,6 +188,14 @@ static const gchar *_edit_point_strings[] = {
        0
 };
 
+static const gchar *_edit_mode_strings[] = {
+       N_("Slide"),
+       N_("Splice"),
+       N_("Ripple"),
+       N_("Lock"),
+       0
+};
+
 static const gchar *_zoom_focus_strings[] = {
        N_("Left"),
        N_("Right"),
@@ -257,11 +272,11 @@ Editor::Editor ()
 
          /* tool bar related */
 
-       , zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
-
        , toolbar_selection_clock_table (2,3)
-
+       , _mouse_mode_tearoff (0)
        , automation_mode_button (_("mode"))
+       , _zoom_tearoff (0)
+       , _tools_tearoff (0)
 
        , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
 
@@ -285,7 +300,7 @@ Editor::Editor ()
        PublicEditor::_instance = this;
 
        _have_idled = false;
-
+       
        selection = new Selection (this);
        cut_buffer = new Selection (this);
 
@@ -296,26 +311,34 @@ Editor::Editor ()
        last_update_frame = 0;
         pre_press_cursor = 0;
        _drags = new DragManager (this);
+       lock_dialog = 0;
+       ruler_dialog = 0;
        current_mixer_strip = 0;
        tempo_lines = 0;
 
        snap_type_strings =  I18N (_snap_type_strings);
        snap_mode_strings =  I18N (_snap_mode_strings);
        zoom_focus_strings = I18N (_zoom_focus_strings);
+       edit_mode_strings = I18N (_edit_mode_strings);
        edit_point_strings = I18N (_edit_point_strings);
 #ifdef USE_RUBBERBAND
        rb_opt_strings = I18N (_rb_opt_strings);
        rb_current_opt = 4;
 #endif
 
+       build_edit_mode_menu();
+       build_zoom_focus_menu();
+       build_track_count_menu();
+       build_snap_mode_menu();
+       build_snap_type_menu();
+       build_edit_point_menu();
+
        snap_threshold = 5.0;
        bbt_beat_subdivision = 4;
        _visible_canvas_width = 0;
        _visible_canvas_height = 0;
-       last_autoscroll_x = 0;
-       last_autoscroll_y = 0;
-       autoscroll_active = false;
-       autoscroll_timeout_tag = -1;
+       autoscroll_horizontal_allowed = false;
+       autoscroll_vertical_allowed = false;
        logo_item = 0;
 
        analysis_window = 0;
@@ -373,13 +396,12 @@ Editor::Editor ()
        _edit_point = EditAtMouse;
        _internal_editing = false;
        current_canvas_cursor = 0;
+       _visible_track_count = 16;
 
        samples_per_pixel = 2048; /* too early to use reset_zoom () */
 
        _scroll_callbacks = 0;
 
-       zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
-
        bbt_label.set_name ("EditorRulerLabel");
        bbt_label.set_size_request (-1, (int)timebar_height);
        bbt_label.set_alignment (1.0, 0.5);
@@ -419,6 +441,9 @@ Editor::Editor ()
        meter_label.hide();
        meter_label.set_no_show_all();
 
+       if (Profile->get_trx()) {
+               mark_label.set_text (_("Markers"));
+       }
        mark_label.set_name ("EditorRulerLabel");
        mark_label.set_size_request (-1, (int)timebar_height);
        mark_label.set_alignment (1.0, 0.5);
@@ -455,7 +480,6 @@ Editor::Editor ()
        transport_mark_label.hide();
        transport_mark_label.set_no_show_all();
 
-       initialize_rulers ();
        initialize_canvas ();
 
        _summary = new EditorSummary (this);
@@ -474,18 +498,20 @@ Editor::Editor ()
 
        HBox* h = manage (new HBox);
        _group_tabs = new EditorGroupTabs (this);
-       h->pack_start (*_group_tabs, PACK_SHRINK);
+       if (!ARDOUR::Profile->get_trx()) {
+               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 (sigc::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.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
        controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
+       controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
 
        _cursors = new MouseCursors;
+       _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
+       cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
 
        ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
 
@@ -497,38 +523,22 @@ Editor::Editor ()
        // CAIROCANVAS
        time_pad->show();
 
-       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.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       ruler_label_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
-
-       time_bars_event_box.add (time_bars_vbox);
-       time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
-       time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
-
-       time_canvas_event_box.add (time_canvas_vbox);
-       time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
-
        edit_packer.set_col_spacings (0);
        edit_packer.set_row_spacings (0);
        edit_packer.set_homogeneous (false);
        edit_packer.set_border_width (0);
        edit_packer.set_name ("EditorWindow");
 
-       /* labels for the rulers */
-       edit_packer.attach (ruler_label_event_box,   1, 2, 0, 1,    FILL,        SHRINK, 0, 0);
-       /* labels for the marker "tracks" (time bars) */
-       edit_packer.attach (time_bars_event_box,     1, 2, 1, 2,    FILL,        SHRINK, 0, 0);
-       /* the rulers */
-       edit_packer.attach (time_canvas_event_box,   2, 3, 0, 1,    FILL|EXPAND, FILL, 0, 0);
+       time_bars_event_box.add (time_bars_vbox);
+       time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
+       time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
+
+       /* labels for the time bars */
+       edit_packer.attach (time_bars_event_box,     0, 1, 0, 1,    FILL,        SHRINK, 0, 0);
        /* track controls */
-       edit_packer.attach (controls_layout,         0, 2, 2, 3,    FILL,        FILL|EXPAND, 0, 0);
-       /* time bars canvas */
-       edit_packer.attach (*_time_bars_canvas_viewport, 2, 3, 1, 2,    FILL,    FILL, 0, 0);
-       /* track canvas */
-       edit_packer.attach (*_track_canvas_viewport,  2, 3, 2, 3,    FILL|EXPAND, FILL|EXPAND, 0, 0);
+       edit_packer.attach (controls_layout,         0, 1, 1, 2,    FILL,        FILL|EXPAND, 0, 0);
+       /* canvas */
+       edit_packer.attach (*_track_canvas_viewport,  1, 2, 0, 2,    FILL|EXPAND, FILL|EXPAND, 0, 0);
 
        bottom_hbox.set_border_width (2);
        bottom_hbox.set_spacing (3);
@@ -593,10 +603,14 @@ 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);
+       if (!ARDOUR::Profile->get_trx()) {
+               editor_summary_pane.pack2 (_summary_hbox);
+       }
 
        edit_pane.pack1 (editor_summary_pane, true, true);
-       edit_pane.pack2 (_the_notebook, false, true);
+       if (!ARDOUR::Profile->get_trx()) {
+               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)));
 
@@ -636,6 +650,7 @@ Editor::Editor ()
        setup_toolbar ();
 
        set_zoom_focus (zoom_focus);
+       set_visible_track_count (_visible_track_count);
        _snap_type = SnapToBeat;
        set_snap_to (_snap_type);
        _snap_mode = SnapOff;
@@ -655,12 +670,12 @@ Editor::Editor ()
 
        /* nudge stuff */
 
-       nudge_forward_button.set_name ("zoom button");
-       nudge_forward_button.add_elements (ArdourButton::FlatFace);
+       nudge_forward_button.set_name ("nudge button");
+//     nudge_forward_button.add_elements (ArdourButton::Inset);
        nudge_forward_button.set_image(::get_icon("nudge_right"));
 
-       nudge_backward_button.set_name ("zoom button");
-       nudge_backward_button.add_elements (ArdourButton::FlatFace);
+       nudge_backward_button.set_name ("nudge button");
+//     nudge_backward_button.add_elements (ArdourButton::Inset);
        nudge_backward_button.set_image(::get_icon("nudge_left"));
 
        fade_context_menu.set_name ("ArdourContextMenu");
@@ -730,6 +745,7 @@ Editor::Editor ()
        Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
 
        Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
+       ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
 
        TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
 
@@ -737,8 +753,9 @@ Editor::Editor ()
        _last_region_menu_was_main = false;
        _popup_region_menu_item = 0;
 
+       _ignore_follow_edits = false;
+
        _show_marker_lines = false;
-       _over_region_trim_target = false;
 
         /* Button bindings */
 
@@ -752,9 +769,14 @@ Editor::Editor ()
         }
 
        constructed = true;
-       instant_save ();
+
+       /* grab current parameter state */
+       boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
+       ARDOUR_UI::config()->map_parameters (pc);
 
        setup_fade_images ();
+
+       instant_save ();
 }
 
 Editor::~Editor()
@@ -762,7 +784,6 @@ Editor::~Editor()
         delete button_bindings;
        delete _routes;
        delete _route_groups;
-       delete _time_bars_canvas_viewport;
        delete _track_canvas_viewport;
        delete _drags;
 }
@@ -790,7 +811,7 @@ Editor::add_toplevel_controls (Container& cont)
 bool
 Editor::get_smart_mode () const
 {
-       return ( (current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active() );
+       return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
 }
 
 void
@@ -815,8 +836,6 @@ Editor::catch_vanishing_regionview (RegionView *rv)
        if (!_all_region_actions_sensitized) {
                sensitize_all_region_actions (true);
        }
-
-       _over_region_trim_target = false;
 }
 
 void
@@ -830,7 +849,9 @@ Editor::set_entered_regionview (RegionView* rv)
                entered_regionview->exited ();
        }
 
-       if ((entered_regionview = rv) != 0) {
+       entered_regionview = rv;
+
+       if (entered_regionview  != 0) {
                entered_regionview->entered (internal_editing ());
        }
 
@@ -849,7 +870,9 @@ Editor::set_entered_track (TimeAxisView* tav)
                entered_track->exited ();
        }
 
-       if ((entered_track = tav) != 0) {
+       entered_track = tav;
+
+       if (entered_track) {
                entered_track->entered ();
        }
 }
@@ -905,23 +928,6 @@ Editor::instant_save ()
        }
 }
 
-void
-Editor::zoom_adjustment_changed ()
-{
-       if (_session == 0) {
-               return;
-       }
-
-       framecnt_t fpu = llrintf (zoom_range_clock->current_duration() / _visible_canvas_width);
-       bool clamped = clamp_samples_per_pixel (fpu);
-       
-       if (clamped) {
-               zoom_range_clock->set ((framepos_t) floor (fpu * _visible_canvas_width));
-       }
-
-       temporal_zoom (fpu);
-}
-
 void
 Editor::control_vertical_zoom_in_all ()
 {
@@ -1102,6 +1108,60 @@ Editor::on_realize ()
 {
        Window::on_realize ();
        Realized ();
+
+       if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
+               start_lock_event_timing ();
+       }
+
+       signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
+}
+
+void
+Editor::start_lock_event_timing ()
+{
+       /* check if we should lock the GUI every 30 seconds */
+
+       Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
+}
+
+bool
+Editor::generic_event_handler (GdkEvent* ev)
+{
+       switch (ev->type) {
+       case GDK_BUTTON_PRESS:
+       case GDK_BUTTON_RELEASE:
+       case GDK_MOTION_NOTIFY:
+       case GDK_KEY_PRESS:
+       case GDK_KEY_RELEASE:
+               gettimeofday (&last_event_time, 0);
+               break;
+       default:
+               break;
+       }
+       return false;
+}
+
+bool
+Editor::lock_timeout_callback ()
+{
+       struct timeval now, delta;
+
+       gettimeofday (&now, 0);
+
+       timersub (&now, &last_event_time, &delta);
+
+       if (delta.tv_sec > ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
+               lock ();
+               /* don't call again. Returning false will effectively
+                  disconnect us from the timer callback.
+
+                  unlock() will call start_lock_event_timing() to get things
+                  started again.
+               */
+               return false;
+       }
+
+       return true;
 }
 
 void
@@ -1185,7 +1245,6 @@ Editor::set_session (Session *t)
                return;
        }
 
-       zoom_range_clock->set_session (_session);
        _playlist_selector->set_session (_session);
        nudge_clock->set_session (_session);
        _summary->set_session (_session);
@@ -1213,32 +1272,12 @@ Editor::set_session (Session *t)
        /* Make sure we have auto loop and auto punch ranges */
 
        Location* loc = _session->locations()->auto_loop_location();
-       if (loc == 0) {
-               loc = new Location (*_session, 0, _session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
-
-               if (loc->start() == loc->end()) {
-                       loc->set_end (loc->start() + 1);
-               }
-
-               _session->locations()->add (loc, false);
-               _session->set_auto_loop_location (loc);
-       } else {
-               // force name
+       if (loc != 0) {
                loc->set_name (_("Loop"));
        }
 
        loc = _session->locations()->auto_punch_location();
-
-       if (loc == 0) {
-               loc = new Location (*_session, 0, _session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
-
-               if (loc->start() == loc->end()) {
-                       loc->set_end (loc->start() + 1);
-               }
-
-               _session->locations()->add (loc, false);
-               _session->set_auto_punch_location (loc);
-       } else {
+       if (loc != 0) {
                // force name
                loc->set_name (_("Punch"));
        }
@@ -1400,185 +1439,48 @@ Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
 
 /** Pop up a context menu for when the user clicks on a start crossfade */
 void
-Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/)
+Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
 {
        using namespace Menu_Helpers;
+       AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
+       assert(arv);
 
        MenuList& items (xfade_in_context_menu.items());
+       items.clear ();
 
-       if (items.empty()) {
-               fill_xfade_menu (items, true);
+       if (arv->audio_region()->fade_in_active()) {
+               items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
+       } else {
+               items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
        }
 
+       items.push_back (SeparatorElem());
+       fill_xfade_menu (items, true);
+
        xfade_in_context_menu.popup (button, time);
 }
 
 /** Pop up a context menu for when the user clicks on an end crossfade */
 void
-Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/)
-{
-       using namespace Menu_Helpers;
-
-       MenuList& items (xfade_out_context_menu.items());
-
-       if (items.empty()) {
-               fill_xfade_menu (items, false);
-       }
-
-       xfade_out_context_menu.popup (button, time);
-}
-
-
-/** Pop up a context menu for when the user clicks on a fade in or fade out */
-void
-Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
+Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
 {
        using namespace Menu_Helpers;
        AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
+       assert(arv);
 
-       if (arv == 0) {
-               fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
-               /*NOTREACHED*/
-       }
-
-       MenuList& items (fade_context_menu.items());
+       MenuList& items (xfade_out_context_menu.items());
        items.clear ();
 
-       switch (item_type) {
-       case FadeInItem:
-       case FadeInHandleItem:
-               if (arv->audio_region()->fade_in_active()) {
-                       items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
-               } else {
-                       items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
-               }
-               
-               items.push_back (SeparatorElem());
-               
-               if (Profile->get_sae()) {
-                       
-                       items.push_back (MenuElem (_("Linear"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeLinear)));
-                       items.push_back (MenuElem (_("Slowest"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeFast)));
-                       
-               } else {
-                       
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Linear"),
-                                       *_fade_in_images[FadeLinear],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeLinear)
-                                       )
-                               );
-                               
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-                               
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Slow"),
-                                       *_fade_in_images[FadeSlow],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSlow)
-                                       ));
-                               
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-                               
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Fast"),
-                                       *_fade_in_images[FadeFast],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeFast)
-                                       ));
-                               
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-                               
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Symmetric"),
-                                       *_fade_in_images[FadeSymmetric],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSymmetric)
-                                       ));
-                               
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Constant power"),
-                                       *_fade_in_images[FadeConstantPower],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeConstantPower)
-                                       ));
-
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-               }
-
-               break;
-
-       case FadeOutItem:
-       case FadeOutHandleItem:
-               if (arv->audio_region()->fade_out_active()) {
-                       items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
-               } else {
-                       items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
-               }
-
-               items.push_back (SeparatorElem());
-
-               if (Profile->get_sae()) {
-                       items.push_back (MenuElem (_("Linear"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeLinear)));
-                       items.push_back (MenuElem (_("Slowest"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSlow)));
-               } else {
-
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Linear"),
-                                       *_fade_out_images[FadeLinear],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeLinear)
-                                       )
-                               );
-
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Slow"),
-                                       *_fade_out_images[FadeSlow],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSlow)
-                                       ));
-
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Fast"),
-                                       *_fade_out_images[FadeFast],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeFast)
-                                       ));
-
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Symmetric"),
-                                       *_fade_out_images[FadeSymmetric],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSymmetric)
-                                       ));
-
-                       items.push_back (
-                               ImageMenuElem (
-                                       _("Constant power"),
-                                       *_fade_out_images[FadeConstantPower],
-                                       sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeConstantPower)
-                                       ));
-
-                       dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
-               }
-
-               break;
-
-       default:
-               fatal << _("programming error: ")
-                     << X_("non-fade canvas item passed to popup_fade_context_menu()")
-                     << endmsg;
-               /*NOTREACHED*/
+       if (arv->audio_region()->fade_out_active()) {
+               items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
+       } else {
+               items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
        }
 
-       fade_context_menu.popup (button, time);
+       items.push_back (SeparatorElem());
+       fill_xfade_menu (items, false);
+
+       xfade_out_context_menu.popup (button, time);
 }
 
 void
@@ -1945,7 +1847,7 @@ Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
        select_menu->set_name ("ArdourContextMenu");
 
        select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
-       select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
+       select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
        select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
        select_items.push_back (SeparatorElem());
@@ -2022,7 +1924,7 @@ Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
        select_menu->set_name ("ArdourContextMenu");
 
        select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
-       select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
+       select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
        select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
        select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
        select_items.push_back (SeparatorElem());
@@ -2082,8 +1984,8 @@ Editor::set_snap_to (SnapType st)
 
        string str = snap_type_strings[snap_ind];
 
-       if (str != snap_type_selector.get_active_text()) {
-               snap_type_selector.set_active_text (str);
+       if (str != snap_type_selector.get_text()) {
+               snap_type_selector.set_text (str);
        }
 
        instant_save ();
@@ -2145,8 +2047,8 @@ Editor::set_snap_mode (SnapMode mode)
 
        _snap_mode = mode;
 
-       if (str != snap_mode_selector.get_active_text ()) {
-               snap_mode_selector.set_active_text (str);
+       if (str != snap_mode_selector.get_text ()) {
+               snap_mode_selector.set_text (str);
        }
 
        instant_save ();
@@ -2159,11 +2061,11 @@ Editor::set_edit_point_preference (EditPoint ep, bool force)
        _edit_point = ep;
        string str = edit_point_strings[(int)ep];
 
-       if (str != edit_point_selector.get_active_text ()) {
-               edit_point_selector.set_active_text (str);
+       if (str != edit_point_selector.get_text ()) {
+               edit_point_selector.set_text (str);
        }
 
-       set_canvas_cursor ();
+       reset_canvas_cursor ();
 
        if (!force && !changed) {
                return;
@@ -2263,7 +2165,7 @@ Editor::set_state (const XMLNode& node, int /*version*/)
        }
 
        if ((prop = node.property ("zoom-focus"))) {
-               set_zoom_focus ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
+               zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
        }
 
        if ((prop = node.property ("zoom"))) {
@@ -2274,12 +2176,16 @@ Editor::set_state (const XMLNode& node, int /*version*/)
                reset_zoom (samples_per_pixel);
        }
 
+       if ((prop = node.property ("visible-track-count"))) {
+               set_visible_track_count (PBD::atoi (prop->value()));
+       }
+
        if ((prop = node.property ("snap-to"))) {
-               set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
+               snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
        }
 
        if ((prop = node.property ("snap-mode"))) {
-               set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode));
+               snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
        }
 
        if ((prop = node.property ("internal-snap-to"))) {
@@ -2436,7 +2342,11 @@ Editor::set_state (const XMLNode& node, int /*version*/)
 
        if ((prop = node.property ("maximised"))) {
                bool yn = string_is_affirmative (prop->value());
-               if (yn) {
+               Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
+               assert (act);
+               Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
+               bool fs = tact && tact->get_active();
+               if (yn ^ fs) {
                        ActionManager::do_action ("Common", "ToggleMaximalEditor");
                }
        }
@@ -2501,6 +2411,8 @@ Editor::get_state ()
        node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
        node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
        node->add_property ("edit-point", enum_2_string (_edit_point));
+       snprintf (buf, sizeof(buf), "%d", _visible_track_count);
+       node->add_property ("visible-track-count", buf);
 
        snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
        node->add_property ("playhead", buf);
@@ -2550,19 +2462,29 @@ Editor::get_state ()
        return *node;
 }
 
-
-
-/** @param y y offset from the top of all trackviews.
+/** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
+ *  if @param trackview_relative_offset is false, @param y y is a global canvas *  coordinate, in pixel units
+ *
  *  @return pair: TimeAxisView that y is over, layer index.
+ *
  *  TimeAxisView may be 0.  Layer index is the layer number if the TimeAxisView is valid and is
  *  in stacked or expanded region display mode, otherwise 0.
  */
 std::pair<TimeAxisView *, double>
-Editor::trackview_by_y_position (double y)
+Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
 {
-       for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+       if (!trackview_relative_offset) {
+               y -= _trackview_group->canvas_origin().y;
+       }
+
+       if (y < 0) {
+               return std::make_pair ( (TimeAxisView *) 0, 0);
+       }
 
+       for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
+                       
                std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
+                       
                if (r.first) {
                        return r;
                }
@@ -2847,7 +2769,7 @@ Editor::setup_toolbar ()
 {
        HBox* mode_box = manage(new HBox);
        mode_box->set_border_width (2);
-       mode_box->set_spacing(4);
+       mode_box->set_spacing(2);
 
        HBox* mouse_mode_box = manage (new HBox);
        HBox* mouse_mode_hbox = manage (new HBox);
@@ -2855,8 +2777,9 @@ Editor::setup_toolbar ()
        Alignment* mouse_mode_align = manage (new Alignment);
 
        Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
-//     mouse_mode_size_group->add_widget (smart_mode_button);
+       //mouse_mode_size_group->add_widget (smart_mode_button);
        mouse_mode_size_group->add_widget (mouse_move_button);
+       mouse_mode_size_group->add_widget (mouse_cut_button);
        mouse_mode_size_group->add_widget (mouse_select_button);
        mouse_mode_size_group->add_widget (mouse_zoom_button);
        mouse_mode_size_group->add_widget (mouse_gain_button);
@@ -2865,20 +2788,31 @@ Editor::setup_toolbar ()
        mouse_mode_size_group->add_widget (mouse_draw_button);
        mouse_mode_size_group->add_widget (internal_edit_button);
 
-       /* make them just a bit bigger */
-       mouse_move_button.set_size_request (-1, 30);
-
+       if (!ARDOUR::Profile->get_small_screen()) {
+               /* make them just a bit bigger */
+               mouse_move_button.set_size_request (24, 30);
+       } else {
+               /* make them just a bit taller */
+               mouse_move_button.set_size_request (-1, 30);
+       }
        mouse_mode_hbox->set_spacing (2);
 
-       mouse_mode_hbox->pack_start (smart_mode_button, false, false);
+       if (!ARDOUR::Profile->get_trx()) {
+               mouse_mode_hbox->pack_start (smart_mode_button, false, false);
+       }
+
        mouse_mode_hbox->pack_start (mouse_move_button, false, false);
        mouse_mode_hbox->pack_start (mouse_select_button, false, false);
+       mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
        mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
-       mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
-       mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
-       mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
-       mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
-       mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
+
+       if (!ARDOUR::Profile->get_trx()) {
+               mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
+               mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
+               mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
+               mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
+               mouse_mode_hbox->pack_start (internal_edit_button, false, false, 4);
+       }
 
        mouse_mode_vbox->pack_start (*mouse_mode_hbox);
 
@@ -2887,24 +2821,19 @@ Editor::setup_toolbar ()
 
        mouse_mode_box->pack_start (*mouse_mode_align, false, false);
 
-       edit_mode_strings.push_back (edit_mode_to_string (Slide));
-       if (!Profile->get_sae()) {
-               edit_mode_strings.push_back (edit_mode_to_string (Splice));
-       }
-       edit_mode_strings.push_back (edit_mode_to_string (Lock));
-
-       edit_mode_selector.set_name ("EditModeSelector");
-       set_popdown_strings (edit_mode_selector, edit_mode_strings);
-       edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done));
+       edit_mode_selector.set_name ("mouse mode button");
+       edit_mode_selector.add_elements (ArdourButton::Inset);
 
-       mode_box->pack_start (edit_mode_selector, false, false);
+       if (!ARDOUR::Profile->get_trx()) {
+               mode_box->pack_start (edit_mode_selector, false, false);
+       }
        mode_box->pack_start (*mouse_mode_box, false, false);
 
        _mouse_mode_tearoff = manage (new TearOff (*mode_box));
        _mouse_mode_tearoff->set_name ("MouseModeBase");
        _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
 
-       if (Profile->get_sae()) {
+       if (Profile->get_sae() || Profile->get_mixbus() ) {
                _mouse_mode_tearoff->set_can_be_torn_off (false);
        }
 
@@ -2925,39 +2854,50 @@ Editor::setup_toolbar ()
        RefPtr<Action> act;
 
        zoom_in_button.set_name ("zoom button");
-       zoom_in_button.add_elements ( ArdourButton::FlatFace );
+//     zoom_in_button.add_elements ( ArdourButton::Inset );
        zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        zoom_in_button.set_image(::get_icon ("zoom_in"));
        act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
        zoom_in_button.set_related_action (act);
 
        zoom_out_button.set_name ("zoom button");
-       zoom_out_button.add_elements ( ArdourButton::FlatFace );
+//     zoom_out_button.add_elements ( ArdourButton::Inset );
        zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        zoom_out_button.set_image(::get_icon ("zoom_out"));
        act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
        zoom_out_button.set_related_action (act);
 
        zoom_out_full_button.set_name ("zoom button");
-       zoom_out_full_button.add_elements ( ArdourButton::FlatFace );
+//     zoom_out_full_button.add_elements ( ArdourButton::Inset );
        zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        zoom_out_full_button.set_image(::get_icon ("zoom_full"));
        act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
        zoom_out_full_button.set_related_action (act);
 
-       zoom_focus_selector.set_name ("ZoomFocusSelector");
-       set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
-       zoom_focus_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done));
-
-       _zoom_box.pack_start (zoom_out_button, false, false);
-       _zoom_box.pack_start (zoom_in_button, false, false);
-       _zoom_box.pack_start (zoom_out_full_button, false, false);
+       zoom_focus_selector.set_name ("zoom button");
+//     zoom_focus_selector.add_elements (ArdourButton::Inset);
 
-       _zoom_box.pack_start (zoom_focus_selector, false, false);
+       if (ARDOUR::Profile->get_mixbus()) {
+               _zoom_box.pack_start (zoom_out_button, false, false);
+               _zoom_box.pack_start (zoom_in_button, false, false);
+               _zoom_box.pack_start (zoom_out_full_button, false, false);
+       } else if (ARDOUR::Profile->get_trx()) {
+               mode_box->pack_start (zoom_out_button, false, false);
+               mode_box->pack_start (zoom_in_button, false, false);
+       } else {
+               _zoom_box.pack_start (zoom_out_button, false, false);
+               _zoom_box.pack_start (zoom_in_button, false, false);
+               _zoom_box.pack_start (zoom_out_full_button, false, false);
+               _zoom_box.pack_start (zoom_focus_selector, false, false);
+       }
 
        /* Track zoom buttons */
+       visible_tracks_selector.set_name ("zoom button");
+//     visible_tracks_selector.add_elements ( ArdourButton::Inset );
+       set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
+
        tav_expand_button.set_name ("zoom button");
-       tav_expand_button.add_elements ( ArdourButton::FlatFace );
+//     tav_expand_button.add_elements ( ArdourButton::FlatFace );
        tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        tav_expand_button.set_size_request (-1, 20);
        tav_expand_button.set_image(::get_icon ("tav_exp"));
@@ -2965,41 +2905,47 @@ Editor::setup_toolbar ()
        tav_expand_button.set_related_action (act);
 
        tav_shrink_button.set_name ("zoom button");
-       tav_shrink_button.add_elements ( ArdourButton::FlatFace );
+//     tav_shrink_button.add_elements ( ArdourButton::FlatFace );
        tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
        tav_shrink_button.set_size_request (-1, 20);
        tav_shrink_button.set_image(::get_icon ("tav_shrink"));
        act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
        tav_shrink_button.set_related_action (act);
 
+       if (!ARDOUR::Profile->get_trx()) {
+               _zoom_box.pack_start (visible_tracks_selector);
+       }
        _zoom_box.pack_start (tav_shrink_button);
        _zoom_box.pack_start (tav_expand_button);
 
-       _zoom_tearoff = manage (new TearOff (_zoom_box));
+       if (!ARDOUR::Profile->get_trx()) {
+               _zoom_tearoff = manage (new TearOff (_zoom_box));
+               
+               _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
+                                                          &_zoom_tearoff->tearoff_window()));
+               _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
+                                                          &_zoom_tearoff->tearoff_window(), 0));
+               _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
+                                                          &_zoom_tearoff->tearoff_window()));
+               _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
+                                                           &_zoom_tearoff->tearoff_window(), 0));
+       } 
 
-       _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
-                                                  &_zoom_tearoff->tearoff_window()));
-       _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
-                                                  &_zoom_tearoff->tearoff_window(), 0));
-       _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
-                                                  &_zoom_tearoff->tearoff_window()));
-       _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
-                                                   &_zoom_tearoff->tearoff_window(), 0));
+       if (Profile->get_sae() || Profile->get_mixbus() ) {
+               _zoom_tearoff->set_can_be_torn_off (false);
+       }
 
        snap_box.set_spacing (2);
        snap_box.set_border_width (2);
 
-       snap_type_selector.set_name ("SnapTypeSelector");
-       set_popdown_strings (snap_type_selector, snap_type_strings);
-       snap_type_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::snap_type_selection_done));
+       snap_type_selector.set_name ("mouse mode button");
+       snap_type_selector.add_elements (ArdourButton::Inset);
 
-       snap_mode_selector.set_name ("SnapModeSelector");
-       set_popdown_strings (snap_mode_selector, snap_mode_strings);
-       snap_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::snap_mode_selection_done));
+       snap_mode_selector.set_name ("mouse mode button");
+       snap_mode_selector.add_elements (ArdourButton::Inset);
 
-       edit_point_selector.set_name ("EditPointSelector");
-       set_popdown_strings (edit_point_selector, edit_point_strings);
-       edit_point_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_point_selection_done));
+       edit_point_selector.set_name ("mouse mode button");
+       edit_point_selector.add_elements (ArdourButton::Inset);
 
        snap_box.pack_start (snap_mode_selector, false, false);
        snap_box.pack_start (snap_type_selector, false, false);
@@ -3025,13 +2971,13 @@ Editor::setup_toolbar ()
        /* Pack everything in... */
 
        HBox* hbox = manage (new HBox);
-       hbox->set_spacing(10);
+       hbox->set_spacing(2);
 
        _tools_tearoff = manage (new TearOff (*hbox));
        _tools_tearoff->set_name ("MouseModeBase");
        _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
 
-       if (Profile->get_sae()) {
+       if (Profile->get_sae() || Profile->get_mixbus()) {
                _tools_tearoff->set_can_be_torn_off (false);
        }
 
@@ -3044,19 +2990,23 @@ Editor::setup_toolbar ()
        _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
                                                     &_tools_tearoff->tearoff_window(), 0));
 
-       toolbar_hbox.set_spacing (10);
+       toolbar_hbox.set_spacing (2);
        toolbar_hbox.set_border_width (1);
 
        toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
-       toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
-       toolbar_hbox.pack_start (*_tools_tearoff, false, false);
-
-       hbox->pack_start (snap_box, false, false);
-        if (!Profile->get_small_screen()) {
-                hbox->pack_start (*nudge_box, false, false);
-        } else {
-                ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
-        }
+       if (!ARDOUR::Profile->get_trx()) {
+               toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
+               toolbar_hbox.pack_start (*_tools_tearoff, false, false);
+       }
+
+       if (!ARDOUR::Profile->get_trx()) {
+               hbox->pack_start (snap_box, false, false);
+               if (!Profile->get_small_screen()) {
+                       hbox->pack_start (*nudge_box, false, false);
+               } else {
+                       ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
+               }
+       }
        hbox->pack_start (panic_box, false, false);
 
        hbox->show_all ();
@@ -3073,11 +3023,89 @@ Editor::setup_toolbar ()
        toolbar_frame.add (_toolbar_viewport);
 }
 
+void
+Editor::build_edit_point_menu ()
+{
+       using namespace Menu_Helpers;
+
+       edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
+       edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
+       edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
+
+       set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, 30, 2);
+}
+
+void
+Editor::build_edit_mode_menu ()
+{
+       using namespace Menu_Helpers;
+       
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
+//     edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
+
+       set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, 30, 2);
+}
+
+void
+Editor::build_snap_mode_menu ()
+{
+       using namespace Menu_Helpers;
+
+       snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
+       snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
+       snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
+
+       set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, 34, 2);
+}
+
+void
+Editor::build_snap_type_menu ()
+{
+       using namespace Menu_Helpers;
+
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
+       snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
+
+       set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, 34, 2);
+
+}
+
 void
 Editor::setup_tooltips ()
 {
        ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
        ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
+       ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
        ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
        ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
        ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
@@ -3094,6 +3122,7 @@ Editor::setup_tooltips ()
        ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
        ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
        ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
+       ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
        ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
        ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
        ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
@@ -3178,33 +3207,8 @@ Editor::convert_drop_to_paths (
        }
 
        for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
-
                if ((*i).substr (0,7) == "file://") {
-
-                       string const p = PBD::url_decode (*i);
-
-                       // scan forward past three slashes
-
-                       string::size_type slashcnt = 0;
-                       string::size_type n = 0;
-                       string::const_iterator x = p.begin();
-
-                       while (slashcnt < 3 && x != p.end()) {
-                               if ((*x) == '/') {
-                                       slashcnt++;
-                               } else if (slashcnt == 3) {
-                                       break;
-                               }
-                               ++n;
-                               ++x;
-                       }
-
-                       if (slashcnt != 3 || x == p.end()) {
-                               error << _("malformed URL passed to drag-n-drop code") << endmsg;
-                               continue;
-                       }
-
-                       paths.push_back (p.substr (n - 1));
+                       paths.push_back (Glib::filename_from_uri (*i));
                }
        }
 
@@ -3213,7 +3217,6 @@ Editor::convert_drop_to_paths (
 
 void
 Editor::new_tempo_section ()
-
 {
 }
 
@@ -3226,7 +3229,7 @@ Editor::map_transport_state ()
                have_pending_keyboard_selection = false;
        }
 
-       update_loop_range_view (true);
+       update_loop_range_view ();
 }
 
 /* UNDO/REDO */
@@ -3359,10 +3362,11 @@ Editor::cycle_edit_mode ()
                if (Profile->get_sae()) {
                        Config->set_edit_mode (Lock);
                } else {
-                       Config->set_edit_mode (Splice);
+                       Config->set_edit_mode (Ripple);
                }
                break;
        case Splice:
+       case Ripple:
                Config->set_edit_mode (Lock);
                break;
        case Lock:
@@ -3372,83 +3376,14 @@ Editor::cycle_edit_mode ()
 }
 
 void
-Editor::edit_mode_selection_done ()
+Editor::edit_mode_selection_done ( EditMode m )
 {
-        string s = edit_mode_selector.get_active_text ();
-
-        if (!s.empty()) {
-                Config->set_edit_mode (string_to_edit_mode (s));
-        }
+       Config->set_edit_mode ( m );
 }
 
 void
-Editor::snap_type_selection_done ()
-{
-       string choice = snap_type_selector.get_active_text();
-       SnapType snaptype = SnapToBeat;
-
-       if (choice == _("Beats/2")) {
-               snaptype = SnapToBeatDiv2;
-       } else if (choice == _("Beats/3")) {
-               snaptype = SnapToBeatDiv3;
-       } else if (choice == _("Beats/4")) {
-               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 = 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 = SnapToBeatDiv16;
-       } else if (choice == _("Beats/20")) {
-               snaptype = SnapToBeatDiv20;
-       } else if (choice == _("Beats/24")) {
-               snaptype = SnapToBeatDiv24;
-       } else if (choice == _("Beats/28")) {
-               snaptype = SnapToBeatDiv28;
-       } else if (choice == _("Beats/32")) {
-               snaptype = SnapToBeatDiv32;
-       } else if (choice == _("Beats/64")) {
-               snaptype = SnapToBeatDiv64;
-       } else if (choice == _("Beats/128")) {
-               snaptype = SnapToBeatDiv128;
-       } else if (choice == _("Beats")) {
-               snaptype = SnapToBeat;
-       } else if (choice == _("Bars")) {
-               snaptype = SnapToBar;
-       } else if (choice == _("Marks")) {
-               snaptype = SnapToMark;
-       } else if (choice == _("Region starts")) {
-               snaptype = SnapToRegionStart;
-       } else if (choice == _("Region ends")) {
-               snaptype = SnapToRegionEnd;
-       } else if (choice == _("Region bounds")) {
-               snaptype = SnapToRegionBoundary;
-       } else if (choice == _("Region syncs")) {
-               snaptype = SnapToRegionSync;
-       } else if (choice == _("CD Frames")) {
-               snaptype = SnapToCDFrame;
-       } 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")) {
-               snaptype = SnapToMinutes;
-       }
-
+Editor::snap_type_selection_done (SnapType snaptype)
+{
        RefPtr<RadioAction> ract = snap_type_action (snaptype);
        if (ract) {
                ract->set_active ();
@@ -3456,19 +3391,8 @@ Editor::snap_type_selection_done ()
 }
 
 void
-Editor::snap_mode_selection_done ()
+Editor::snap_mode_selection_done (SnapMode mode)
 {
-       string choice = snap_mode_selector.get_active_text();
-       SnapMode mode = SnapNormal;
-
-       if (choice == _("No Grid")) {
-               mode = SnapOff;
-       } else if (choice == _("Grid")) {
-               mode = SnapNormal;
-       } else if (choice == _("Magnetic")) {
-               mode = SnapMagnetic;
-       }
-
        RefPtr<RadioAction> ract = snap_mode_action (mode);
 
        if (ract) {
@@ -3497,53 +3421,103 @@ Editor::cycle_edit_point (bool with_marker)
 }
 
 void
-Editor::edit_point_selection_done ()
+Editor::edit_point_selection_done (EditPoint ep)
 {
-       string choice = edit_point_selector.get_active_text();
-       EditPoint ep = EditAtSelectedMarker;
+       set_edit_point_preference ( ep );
+}
 
-       if (choice == _("Marker")) {
-               set_edit_point_preference (EditAtSelectedMarker);
-       } else if (choice == _("Playhead")) {
-               set_edit_point_preference (EditAtPlayhead);
-       } else {
-               set_edit_point_preference (EditAtMouse);
-       }
+void
+Editor::build_zoom_focus_menu ()
+{
+       using namespace Menu_Helpers;
+
+       zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
+       zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
+       zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
+       zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
+       zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
+       zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
 
-       RefPtr<RadioAction> ract = edit_point_action (ep);
+       set_size_request_to_display_given_text (zoom_focus_selector, longest (zoom_focus_strings), 30, 2);
+}
 
+void
+Editor::zoom_focus_selection_done ( ZoomFocus f )
+{
+       RefPtr<RadioAction> ract = zoom_focus_action (f);
        if (ract) {
-               ract->set_active (true);
+               ract->set_active ();
        }
 }
 
 void
-Editor::zoom_focus_selection_done ()
+Editor::build_track_count_menu ()
 {
-       string choice = zoom_focus_selector.get_active_text();
-       ZoomFocus focus_type = ZoomFocusLeft;
+       using namespace Menu_Helpers;
+
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
+       visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
+       visible_tracks_selector.AddMenuElem (MenuElem (_("all"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
+}
 
-       if (choice == _("Left")) {
-               focus_type = ZoomFocusLeft;
-       } else if (choice == _("Right")) {
-               focus_type = ZoomFocusRight;
-       } else if (choice == _("Center")) {
-               focus_type = ZoomFocusCenter;
-       } else if (choice == _("Playhead")) {
-               focus_type = ZoomFocusPlayhead;
-       } else if (choice == _("Mouse")) {
-               focus_type = ZoomFocusMouse;
-       } else if (choice == _("Edit point")) {
-               focus_type = ZoomFocusEdit;
+void
+Editor::set_visible_track_count (int32_t n)
+{
+       _visible_track_count = n;
+
+       /* if the canvas hasn't really been allocated any size yet, just
+          record the desired number of visible tracks and return. when canvas
+          allocation happens, we will get called again and then we can do the
+          real work.
+       */
+       
+       if (_visible_canvas_height <= 1) {
+               return;
        }
 
-       RefPtr<RadioAction> ract = zoom_focus_action (focus_type);
+       int h;
+       string str;
 
-       if (ract) {
-               ract->set_active ();
+       if (_visible_track_count > 0) {
+               h = _visible_canvas_height / _visible_track_count;
+               std::ostringstream s;
+               s << _visible_track_count;
+               str = s.str();
+       } else if (_visible_track_count == 0) {
+               h = _visible_canvas_height / track_views.size();
+               str = _("all");
+       } else {
+               /* negative value means that the visible track count has 
+                  been overridden by explicit track height changes.
+               */
+               visible_tracks_selector.set_text (X_("*"));
+               return;
+       }
+
+       for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
+               (*i)->set_height (h);
+       }
+       
+       if (str != visible_tracks_selector.get_text()) {
+               visible_tracks_selector.set_text (str);
        }
 }
 
+void
+Editor::override_visible_track_count ()
+{
+       _visible_track_count = -_visible_track_count;
+}
+
 bool
 Editor::edit_controls_button_release (GdkEventButton* ev)
 {
@@ -3573,8 +3547,8 @@ Editor::set_zoom_focus (ZoomFocus f)
 {
        string str = zoom_focus_strings[(int)f];
 
-       if (str != zoom_focus_selector.get_active_text()) {
-               zoom_focus_selector.set_active_text (str);
+       if (str != zoom_focus_selector.get_text()) {
+               zoom_focus_selector.set_text (str);
        }
 
        if (zoom_focus != f) {
@@ -3687,7 +3661,7 @@ Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
 {
        if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) && 
            (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) && 
-           (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible())) {
+           (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
                top_hbox.remove (toolbar_frame);
        }
 }
@@ -3962,26 +3936,14 @@ Editor::transport_punch_location()
 bool
 Editor::control_layout_scroll (GdkEventScroll* ev)
 {
-       if (Keyboard::some_magic_widget_has_focus()) {
-               return false;
-       }
+       /* Just forward to the normal canvas scroll method. The coordinate
+          systems are different but since the canvas is always larger than the
+          track headers, and aligned with the trackview area, this will work.
 
-       switch (ev->direction) {
-       case GDK_SCROLL_UP:
-               scroll_tracks_up_line ();
-               return true;
-               break;
-
-       case GDK_SCROLL_DOWN:
-               scroll_tracks_down_line ();
-               return true;
-
-       default:
-               /* no left/right handling yet */
-               break;
-       }
-
-       return false;
+          In the not too distant future this layout is going away anyway and
+          headers will be on the canvas.
+       */
+       return canvas_scroll_event (ev, false);
 }
 
 void
@@ -3997,7 +3959,9 @@ Editor::update_tearoff_visibility()
        bool visible = Config->get_keep_tearoffs();
        _mouse_mode_tearoff->set_visible (visible);
        _tools_tearoff->set_visible (visible);
-       _zoom_tearoff->set_visible (visible);
+       if (_zoom_tearoff) {
+               _zoom_tearoff->set_visible (visible);
+       }
 }
 
 void
@@ -4124,8 +4088,6 @@ Editor::reset_y_origin (double y)
 void
 Editor::reset_zoom (framecnt_t spp)
 {
-       clamp_samples_per_pixel (spp);
-
        if (spp == samples_per_pixel) {
                return;
        }
@@ -4217,8 +4179,7 @@ void
 Editor::use_visual_state (VisualState& vs)
 {
        PBD::Unwinder<bool> nsv (no_save_visual, true);
-
-       _routes->suspend_redisplay ();
+       DisplaySuspender ds;
 
        vertical_adjustment.set_value (vs.y_position);
 
@@ -4234,29 +4195,34 @@ Editor::use_visual_state (VisualState& vs)
        }
 
        _routes->update_visibility ();
-       _routes->resume_redisplay ();
 }
 
 /** This is the core function that controls the zoom level of the canvas. It is called
  *  whenever one or more calls are made to reset_zoom().  It executes in an idle handler.
- *  @param fpu New frames per unit; should already have been clamped so that it is sensible.
+ *  @param spp new number of samples per pixel
  */
 void
 Editor::set_samples_per_pixel (framecnt_t spp)
 {
-       clamp_samples_per_pixel (spp);
-       samples_per_pixel = spp;
-
-       if (tempo_lines) {
-               tempo_lines->tempo_map_changed();
+       if (spp < 1) {
+               return;
        }
 
-       /* convert fpu to frame count */
+       const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
+       const framecnt_t lots_of_pixels = 4000;
 
-       framepos_t frames = samples_per_pixel * _visible_canvas_width;
+       /* if the zoom level is greater than what you'd get trying to display 3
+        * days of audio on a really big screen, then it's too big.
+        */
 
-       if (samples_per_pixel != zoom_range_clock->current_duration()) {
-               zoom_range_clock->set (frames);
+       if (spp * lots_of_pixels > three_days) {
+               return;
+       }
+
+       samples_per_pixel = spp;
+
+       if (tempo_lines) {
+               tempo_lines->tempo_map_changed();
        }
 
        bool const showing_time_selection = selection->time.length() > 0;
@@ -4271,10 +4237,6 @@ Editor::set_samples_per_pixel (framecnt_t spp)
 
        ArdourCanvas::GtkCanvasViewport* c;
 
-       c = get_time_bars_canvas();
-       if (c) {
-               c->canvas()->zoomed ();
-       }
        c = get_track_canvas();
        if (c) {
                c->canvas()->zoomed ();
@@ -4336,35 +4298,45 @@ Editor::idle_visual_changer ()
        pending_visual_change.idle_handler_id = -1;
        pending_visual_change.being_handled = true;
        
-       VisualChange::Type p = pending_visual_change.pending;
+       VisualChange vc = pending_visual_change;
+
        pending_visual_change.pending = (VisualChange::Type) 0;
 
-       double const last_time_origin = horizontal_position ();
+       visual_changer (vc);
+
+       pending_visual_change.being_handled = false;
+
+       return 0; /* this is always a one-shot call */
+}
 
+void
+Editor::visual_changer (const VisualChange& vc)
+{
+       double const last_time_origin = horizontal_position ();
 
-       if (p & VisualChange::ZoomLevel) {
-               set_samples_per_pixel (pending_visual_change.samples_per_pixel);
+       if (vc.pending & VisualChange::ZoomLevel) {
+               set_samples_per_pixel (vc.samples_per_pixel);
 
                compute_fixed_ruler_scale ();
 
                ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
                ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
                
-               compute_current_bbt_points (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_samples(),
+               compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
                                            current_bbt_points_begin, current_bbt_points_end);
-               compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_samples(),
+               compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
                                         current_bbt_points_begin, current_bbt_points_end);
                update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
 
                update_video_timeline();
        }
 
-       if (p & VisualChange::TimeOrigin) {
-               set_horizontal_position (pending_visual_change.time_origin / samples_per_pixel);
+       if (vc.pending & VisualChange::TimeOrigin) {
+               set_horizontal_position (vc.time_origin / samples_per_pixel);
        }
 
-       if (p & VisualChange::YOrigin) {
-               vertical_adjustment.set_value (pending_visual_change.y_origin);
+       if (vc.pending & VisualChange::YOrigin) {
+               vertical_adjustment.set_value (vc.y_origin);
        }
 
        if (last_time_origin == horizontal_position ()) {
@@ -4373,14 +4345,11 @@ Editor::idle_visual_changer ()
                redisplay_tempo (true);
        }
 
-       if (!(p & VisualChange::ZoomLevel)) {
+       if (!(vc.pending & VisualChange::ZoomLevel)) {
                update_video_timeline();
        }
 
        _summary->set_overlays_dirty ();
-
-       pending_visual_change.being_handled = false;
-       return 0; /* this is always a one-shot call */
 }
 
 struct EditorOrderTimeAxisSorter {
@@ -4404,7 +4373,7 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
        EditPoint ep = _edit_point;
 
        if (from_context_menu && (ep == EditAtMouse)) {
-               return  canvas_event_frame (&context_click_event, 0, 0);
+               return  canvas_event_sample (&context_click_event, 0, 0);
        }
 
        if (entered_marker) {
@@ -4492,7 +4461,7 @@ Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
                Location* loc = new Location (*_session, start, end, _("Punch"),  Location::IsAutoPunch);
                XMLNode &before = _session->locations()->get_state();
                _session->locations()->add (loc, true);
-               _session->set_auto_loop_location (loc);
+               _session->set_auto_punch_location (loc);
                XMLNode &after = _session->locations()->get_state();
                _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
        }
@@ -4584,22 +4553,14 @@ Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackVie
 
 /** Get regions using the following method:
  *
- *  Make a region list using the selected regions, unless
- *  the edit point is `mouse' and the mouse is over an unselected
- *  region.  In this case, use just that region.
+ *  Make a region list using:
+ *   (a) any selected regions
+ *   (b) the intersection of any selected tracks and the edit point(*)
+ *   (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
  *
- *  If the edit point is not 'mouse', and there are no regions selected,
- *  search the list of selected tracks and return regions that are under
- *  the edit point on these tracks. If there are no selected tracks and
- *  'No Selection = All Tracks' is active, search all tracks,
+ *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
  *
- *  The rationale here is that the mouse edit point is special in that
- *  its position describes both a time and a track; the other edit
- *  modes only describe a time.  Hence if the edit point is `mouse' we
- *  ignore selected tracks, as we assume the user means something by
- *  pointing at a particular track.  Also in this case we take note of
- *  the region directly under the edit point, as there is always just one
- *  (rather than possibly several with non-mouse edit points).
+ *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
  */
 
 RegionSelection
@@ -4607,23 +4568,15 @@ Editor::get_regions_from_selection_and_edit_point ()
 {
        RegionSelection regions;
 
-       if (_edit_point == EditAtMouse && entered_regionview && !selection->regions.contains (entered_regionview)) {
+       if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
                regions.add (entered_regionview);
        } else {
                regions = selection->regions;
        }
 
-
-       if (regions.empty() && _edit_point != EditAtMouse) {
+       if ( regions.empty() ) {
                TrackViewList tracks = selection->tracks;
 
-               if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
-                       /* tracks is empty (no track selected), and 'No Selection = All Tracks'
-                        * is enabled, so consider all tracks
-                        */
-                       tracks = track_views; 
-               }
-
                if (!tracks.empty()) {
                        /* no region selected or entered, but some selected tracks:
                         * act on all regions on the selected tracks at the edit point
@@ -4632,6 +4585,43 @@ Editor::get_regions_from_selection_and_edit_point ()
                        get_regions_at(regions, where, tracks);
                }
        }
+
+       return regions;
+}
+
+/** Get regions using the following method:
+ *
+ *  Make a region list using:
+ *   (a) any selected regions
+ *   (b) the intersection of any selected tracks and the edit point(*)
+ *   (c) if neither exists, then whatever region is under the mouse
+ *
+ *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
+ *
+ *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
+ */
+RegionSelection
+Editor::get_regions_from_selection_and_mouse (framepos_t pos)
+{
+       RegionSelection regions;
+
+       if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
+               regions.add (entered_regionview);
+       } else {
+               regions = selection->regions;
+       }
+
+       if ( regions.empty() ) {
+               TrackViewList tracks = selection->tracks;
+
+               if (!tracks.empty()) {
+                       /* no region selected or entered, but some selected tracks:
+                        * act on all regions on the selected tracks at the edit point
+                        */ 
+                       get_regions_at(regions, pos, tracks);
+               }
+       }
+
        return regions;
 }
 
@@ -4809,16 +4799,16 @@ Editor::located ()
 void
 Editor::region_view_added (RegionView *)
 {
-       _summary->set_dirty ();
+       _summary->set_background_dirty ();
 }
 
 void
 Editor::region_view_removed ()
 {
-       _summary->set_dirty ();
+       _summary->set_background_dirty ();
 }
 
-TimeAxisView*
+RouteTimeAxisView*
 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
 {
        TrackViewList::const_iterator j = track_views.begin ();
@@ -4849,6 +4839,22 @@ Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
        return t;
 }
 
+void
+Editor::suspend_route_redisplay ()
+{
+       if (_routes) {
+               _routes->suspend_redisplay();
+       }
+}
+
+void
+Editor::resume_route_redisplay ()
+{
+       if (_routes) {
+               _routes->resume_redisplay();
+       }
+}
+
 void
 Editor::add_routes (RouteList& routes)
 {
@@ -4906,6 +4912,10 @@ Editor::add_routes (RouteList& routes)
 void
 Editor::timeaxisview_deleted (TimeAxisView *tv)
 {
+       if (tv == entered_track) {
+               entered_track = 0;
+       }
+
        if (_session && _session->deletion_in_progress()) {
                /* the situation is under control */
                return;
@@ -4917,10 +4927,6 @@ Editor::timeaxisview_deleted (TimeAxisView *tv)
 
        _routes->route_removed (tv);
 
-       if (tv == entered_track) {
-               entered_track = 0;
-       }
-
        TimeAxisView::Children c = tv->get_child_list ();
        for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
                if (entered_track == i->get()) {
@@ -5352,7 +5358,6 @@ Editor::session_going_away ()
        }
        track_views.clear ();
 
-       zoom_range_clock->set_session (0);
        nudge_clock->set_session (0);
 
        editor_list_button.set_active(false);
@@ -5430,28 +5435,28 @@ void
 Editor::setup_fade_images ()
 {
        _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
-       _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-short-cut")));
-       _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
-       _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
-       _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-long-cut")));
+       _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
+       _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
+       _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
+       _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
 
        _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
-       _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
-       _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
-       _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
-       _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
+       _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
+       _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
+       _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
+       _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
        
-       _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
-       _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
-       _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
-       _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
-       _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
+       _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
+       _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
+       _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
+       _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
+       _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
 
        _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
-       _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
-       _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
-       _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
-       _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
+       _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
+       _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
+       _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
+       _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
 
 }
 
@@ -5529,3 +5534,18 @@ Editor::zoom_vertical_modifier_released()
 {
        _stepping_axis_view = 0;
 }
+
+void
+Editor::ui_parameter_changed (string parameter)
+{
+       if (parameter == "icon-set") {
+               while (!_cursor_stack.empty()) {
+                       _cursor_stack.pop();
+               }
+               _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
+       } else if (parameter == "draggable-playhead") {
+               if (_verbose_cursor) {
+                       playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());
+               }
+       }
+}