Merge branch 'waveview_caching_for_upstream' of https://github.com/nmains/ardour...
[ardour.git] / gtk2_ardour / editor.cc
index 5da1d09d8f565c2248608db2e666b1aedb601b63..96aa51f4da33847469889786aa826c8b560e2abe 100644 (file)
 #include "pbd/stacktrace.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"
@@ -258,10 +262,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 +290,7 @@ Editor::Editor ()
        PublicEditor::_instance = this;
 
        _have_idled = false;
-
+       
        selection = new Selection (this);
        cut_buffer = new Selection (this);
 
@@ -308,14 +313,19 @@ Editor::Editor ()
        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,6 +383,7 @@ 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 () */
 
@@ -419,6 +430,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);
@@ -474,7 +488,9 @@ 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);
 
@@ -525,10 +541,8 @@ Editor::Editor ()
        edit_packer.attach (time_canvas_event_box,   2, 3, 0, 1,    FILL|EXPAND, FILL, 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 (*_track_canvas_viewport,  2, 3, 1, 3,    FILL|EXPAND, FILL|EXPAND, 0, 0);
 
        bottom_hbox.set_border_width (2);
        bottom_hbox.set_spacing (3);
@@ -593,10 +607,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 +654,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 +674,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");
@@ -762,7 +781,6 @@ Editor::~Editor()
         delete button_bindings;
        delete _routes;
        delete _route_groups;
-       delete _time_bars_canvas_viewport;
        delete _track_canvas_viewport;
        delete _drags;
 }
@@ -1213,32 +1231,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 +1398,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
@@ -2082,8 +1943,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 +2006,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,8 +2020,8 @@ 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 ();
@@ -2263,7 +2124,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 +2135,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 +2301,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 +2370,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,25 +2421,28 @@ Editor::get_state ()
        return *node;
 }
 
-
-
-/** @param y y offset from the top of all trackviews.
+/** @param y y is an offset into the trackview area, 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)
 {
+       if (y < 0) {
+               return std::make_pair ( (TimeAxisView *) 0, 0);
+       }
+               
        for (TrackViewList::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;
                }
        }
-
-       return std::make_pair ( (TimeAxisView *) 0, 0);
 }
 
 /** Snap a position to the grid, if appropriate, taking into account current
@@ -2870,15 +2744,21 @@ Editor::setup_toolbar ()
 
        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_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, 8);
+       }
 
        mouse_mode_vbox->pack_start (*mouse_mode_hbox);
 
@@ -2893,11 +2773,13 @@ Editor::setup_toolbar ()
        }
        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.set_size_request (65, -1);
+       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));
@@ -2925,39 +2807,47 @@ 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.set_size_request (80, -1);
+//     zoom_focus_selector.add_elements (ArdourButton::Inset);
 
-       _zoom_box.pack_start (zoom_focus_selector, false, false);
+       if (!ARDOUR::Profile->get_trx()) {
+               _zoom_box.pack_start (zoom_out_button, false, false);
+               _zoom_box.pack_start (zoom_in_button, false, false);
+               _zoom_box.pack_start (zoom_out_full_button, false, false);
+               _zoom_box.pack_start (zoom_focus_selector, false, false);
+       } else {
+               mode_box->pack_start (zoom_out_button, false, false);
+               mode_box->pack_start (zoom_in_button, false, false);
+       }
 
        /* Track zoom buttons */
+       visible_tracks_selector.set_name ("zoom button");
+//     visible_tracks_selector.add_elements ( ArdourButton::Inset );
+       set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
+
        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 +2855,46 @@ 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));
-
-       _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 (!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));
+       } 
 
        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.set_size_request (140, -1);
+       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.set_size_request (85, -1);
+       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.set_size_request (85, -1);
+       edit_point_selector.add_elements (ArdourButton::Inset);
 
        snap_box.pack_start (snap_mode_selector, false, false);
        snap_box.pack_start (snap_type_selector, false, false);
@@ -3048,15 +2943,19 @@ Editor::setup_toolbar ()
        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,6 +2972,73 @@ 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)));
+}
+
+void
+Editor::build_edit_mode_menu ()
+{
+       using namespace Menu_Helpers;
+
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
+       edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
+}
+
+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)));
+}
+
+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)));
+}
+
 void
 Editor::setup_tooltips ()
 {
@@ -3094,6 +3060,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 +3145,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 +3155,6 @@ Editor::convert_drop_to_paths (
 
 void
 Editor::new_tempo_section ()
-
 {
 }
 
@@ -3226,7 +3167,7 @@ Editor::map_transport_state ()
                have_pending_keyboard_selection = false;
        }
 
-       update_loop_range_view (true);
+       update_loop_range_view ();
 }
 
 /* UNDO/REDO */
@@ -3372,83 +3313,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 +3328,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 +3358,101 @@ 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;
 
-       RefPtr<RadioAction> ract = edit_point_action (ep);
+       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)));
+}
 
+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 ()
+{
+       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)));
+}
+
+void
+Editor::set_visible_track_count (int32_t n)
 {
-       string choice = zoom_focus_selector.get_active_text();
-       ZoomFocus focus_type = ZoomFocusLeft;
+       _visible_track_count = n;
 
-       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;
+       /* 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 +3482,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 +3596,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);
        }
 }
@@ -3997,7 +3906,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
@@ -4269,7 +4180,12 @@ Editor::set_samples_per_pixel (framecnt_t spp)
 
        ZoomChanged (); /* EMIT_SIGNAL */
 
-       //reset_scrolling_region ();
+       ArdourCanvas::GtkCanvasViewport* c;
+
+       c = get_track_canvas();
+       if (c) {
+               c->canvas()->zoomed ();
+       }
 
        if (playhead_cursor) {
                playhead_cursor->set_position (playhead_cursor->current_frame ());
@@ -4327,35 +4243,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;
 
-       if (p & VisualChange::ZoomLevel) {
-               set_samples_per_pixel (pending_visual_change.samples_per_pixel);
+       return 0; /* this is always a one-shot call */
+}
+
+void
+Editor::visual_changer (const VisualChange& vc)
+{
+       double const last_time_origin = horizontal_position ();
+
+       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 ()) {
@@ -4364,14 +4290,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 {
@@ -4395,7 +4318,7 @@ Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_men
        EditPoint ep = _edit_point;
 
        if (from_context_menu && (ep == EditAtMouse)) {
-               return  window_event_frame (&context_click_event, 0, 0);
+               return  canvas_event_sample (&context_click_event, 0, 0);
        }
 
        if (entered_marker) {
@@ -4483,7 +4406,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));
        }
@@ -4809,7 +4732,7 @@ Editor::region_view_removed ()
        _summary->set_dirty ();
 }
 
-TimeAxisView*
+RouteTimeAxisView*
 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
 {
        TrackViewList::const_iterator j = track_views.begin ();
@@ -4882,8 +4805,10 @@ Editor::add_routes (RouteList& routes)
                rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
        }
 
-       _routes->routes_added (new_views);
-       _summary->routes_added (new_views);
+       if (new_views.size() > 0) {
+               _routes->routes_added (new_views);
+               _summary->routes_added (new_views);
+       }
 
        if (show_editor_mixer_when_tracks_arrive) {
                show_editor_mixer (true);
@@ -5419,28 +5344,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")));
 
 }