display active peak-builds
[ardour.git] / gtk2_ardour / editor.cc
1 /*
2     Copyright (C) 2000-2009 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /* Note: public Editor methods are documented in public_editor.h */
21
22 #include <stdint.h>
23 #include <unistd.h>
24 #include <cstdlib>
25 #include <cmath>
26 #include <string>
27 #include <algorithm>
28 #include <map>
29
30 #include "ardour_ui.h"
31 /*
32  * ardour_ui.h include was moved to the top of the list
33  * due to a conflicting definition of 'Style' between
34  * Apple's MacTypes.h and BarController.
35  */
36
37 #include <boost/none.hpp>
38
39 #include <sigc++/bind.h>
40
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
48 #include "pbd/timersub.h"
49
50 #include <glibmm/miscutils.h>
51 #include <glibmm/uriutils.h>
52 #include <gtkmm/image.h>
53 #include <gdkmm/color.h>
54 #include <gdkmm/bitmap.h>
55
56 #include <gtkmm/menu.h>
57 #include <gtkmm/menuitem.h>
58
59 #include "gtkmm2ext/bindings.h"
60 #include "gtkmm2ext/grouped_buttons.h"
61 #include "gtkmm2ext/gtk_ui.h"
62 #include "gtkmm2ext/tearoff.h"
63 #include "gtkmm2ext/utils.h"
64 #include "gtkmm2ext/window_title.h"
65 #include "gtkmm2ext/choice.h"
66 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
67
68 #include "ardour/audio_track.h"
69 #include "ardour/audioengine.h"
70 #include "ardour/audioregion.h"
71 #include "ardour/lmath.h"
72 #include "ardour/location.h"
73 #include "ardour/profile.h"
74 #include "ardour/route_group.h"
75 #include "ardour/session_playlists.h"
76 #include "ardour/tempo.h"
77 #include "ardour/utils.h"
78
79 #include "canvas/debug.h"
80 #include "canvas/text.h"
81
82 #include "control_protocol/control_protocol.h"
83
84 #include "actions.h"
85 #include "analysis_window.h"
86 #include "audio_clock.h"
87 #include "audio_region_view.h"
88 #include "audio_streamview.h"
89 #include "audio_time_axis.h"
90 #include "automation_time_axis.h"
91 #include "bundle_manager.h"
92 #include "crossfade_edit.h"
93 #include "debug.h"
94 #include "editing.h"
95 #include "editor.h"
96 #include "editor_cursors.h"
97 #include "editor_drag.h"
98 #include "editor_group_tabs.h"
99 #include "editor_locations.h"
100 #include "editor_regions.h"
101 #include "editor_route_groups.h"
102 #include "editor_routes.h"
103 #include "editor_snapshots.h"
104 #include "editor_summary.h"
105 #include "global_port_matrix.h"
106 #include "gui_object.h"
107 #include "gui_thread.h"
108 #include "keyboard.h"
109 #include "marker.h"
110 #include "midi_region_view.h"
111 #include "midi_time_axis.h"
112 #include "mixer_strip.h"
113 #include "mixer_ui.h"
114 #include "mouse_cursors.h"
115 #include "note_base.h"
116 #include "playlist_selector.h"
117 #include "public_editor.h"
118 #include "quantize_dialog.h"
119 #include "region_layering_order_editor.h"
120 #include "rgb_macros.h"
121 #include "rhythm_ferret.h"
122 #include "selection.h"
123 #include "sfdb_ui.h"
124 #include "tempo_lines.h"
125 #include "time_axis_view.h"
126 #include "timers.h"
127 #include "utils.h"
128 #include "verbose_cursor.h"
129
130 #include "i18n.h"
131
132 using namespace std;
133 using namespace ARDOUR;
134 using namespace ARDOUR_UI_UTILS;
135 using namespace PBD;
136 using namespace Gtk;
137 using namespace Glib;
138 using namespace Gtkmm2ext;
139 using namespace Editing;
140
141 using PBD::internationalize;
142 using PBD::atoi;
143 using Gtkmm2ext::Keyboard;
144
145 double Editor::timebar_height = 15.0;
146
147 static const gchar *_snap_type_strings[] = {
148         N_("CD Frames"),
149         N_("TC Frames"),
150         N_("TC Seconds"),
151         N_("TC Minutes"),
152         N_("Seconds"),
153         N_("Minutes"),
154         N_("Beats/128"),
155         N_("Beats/64"),
156         N_("Beats/32"),
157         N_("Beats/28"),
158         N_("Beats/24"),
159         N_("Beats/20"),
160         N_("Beats/16"),
161         N_("Beats/14"),
162         N_("Beats/12"),
163         N_("Beats/10"),
164         N_("Beats/8"),
165         N_("Beats/7"),
166         N_("Beats/6"),
167         N_("Beats/5"),
168         N_("Beats/4"),
169         N_("Beats/3"),
170         N_("Beats/2"),
171         N_("Beats"),
172         N_("Bars"),
173         N_("Marks"),
174         N_("Region starts"),
175         N_("Region ends"),
176         N_("Region syncs"),
177         N_("Region bounds"),
178         0
179 };
180
181 static const gchar *_snap_mode_strings[] = {
182         N_("No Grid"),
183         N_("Grid"),
184         N_("Magnetic"),
185         0
186 };
187
188 static const gchar *_edit_point_strings[] = {
189         N_("Playhead"),
190         N_("Marker"),
191         N_("Mouse"),
192         0
193 };
194
195 static const gchar *_edit_mode_strings[] = {
196         N_("Slide"),
197         N_("Splice"),
198         N_("Ripple"),
199         N_("Lock"),
200         0
201 };
202
203 static const gchar *_zoom_focus_strings[] = {
204         N_("Left"),
205         N_("Right"),
206         N_("Center"),
207         N_("Playhead"),
208         N_("Mouse"),
209         N_("Edit point"),
210         0
211 };
212
213 #ifdef USE_RUBBERBAND
214 static const gchar *_rb_opt_strings[] = {
215         N_("Mushy"),
216         N_("Smooth"),
217         N_("Balanced multitimbral mixture"),
218         N_("Unpitched percussion with stable notes"),
219         N_("Crisp monophonic instrumental"),
220         N_("Unpitched solo percussion"),
221         N_("Resample without preserving pitch"),
222         0
223 };
224 #endif
225
226 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
227
228 static void
229 pane_size_watcher (Paned* pane)
230 {
231         /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
232            it is:
233
234               X: hard to access
235               Quartz: impossible to access
236               
237            so stop that by preventing it from ever getting too narrow. 35
238            pixels is basically a rough guess at the tab width.
239
240            ugh.
241         */
242
243         int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
244
245         gint pos = pane->get_position ();
246
247         if (pos > max_width_of_lhs) {
248                 pane->set_position (max_width_of_lhs);
249         }
250 }
251
252 Editor::Editor ()
253         : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
254
255         , _mouse_changed_selection (false)
256           /* time display buttons */
257         , minsec_label (_("Mins:Secs"))
258         , bbt_label (_("Bars:Beats"))
259         , timecode_label (_("Timecode"))
260         , samples_label (_("Samples"))
261         , tempo_label (_("Tempo"))
262         , meter_label (_("Meter"))
263         , mark_label (_("Location Markers"))
264         , range_mark_label (_("Range Markers"))
265         , transport_mark_label (_("Loop/Punch Ranges"))
266         , cd_mark_label (_("CD Markers"))
267         , videotl_label (_("Video Timeline"))
268         , edit_packer (4, 4, true)
269
270           /* the values here don't matter: layout widgets
271              reset them as needed.
272           */
273
274         , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
275         , horizontal_adjustment (0.0, 0.0, 1e16)
276         , unused_adjustment (0.0, 0.0, 10.0, 400.0)
277
278         , controls_layout (unused_adjustment, vertical_adjustment)
279
280           /* tool bar related */
281
282         , toolbar_selection_clock_table (2,3)
283         , _mouse_mode_tearoff (0)
284         , automation_mode_button (_("mode"))
285         , _zoom_tearoff (0)
286         , _tools_tearoff (0)
287
288         , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
289         , selection_op_cmd_depth (0)
290         , selection_op_history_it (0)
291
292           /* nudge */
293
294         , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
295         , meters_running(false)
296         , _pending_locate_request (false)
297         , _pending_initial_locate (false)
298         , _last_cut_copy_source_track (0)
299
300         , _region_selection_change_updates_region_list (true)
301         , _following_mixer_selection (false)
302         , _control_point_toggled_on_press (false)
303         , _stepping_axis_view (0)
304         , quantize_dialog (0)
305         , _main_menu_disabler (0)
306 {
307         constructed = false;
308
309         /* we are a singleton */
310
311         PublicEditor::_instance = this;
312
313         _have_idled = false;
314         
315         selection = new Selection (this);
316         cut_buffer = new Selection (this);
317         _selection_memento = new SelectionMemento ();
318         selection_op_history.clear();
319         before.clear();
320
321         clicked_regionview = 0;
322         clicked_axisview = 0;
323         clicked_routeview = 0;
324         clicked_control_point = 0;
325         last_update_frame = 0;
326         last_paste_pos = 0;
327         paste_count = 0;
328         _drags = new DragManager (this);
329         lock_dialog = 0;
330         ruler_dialog = 0;
331         current_mixer_strip = 0;
332         tempo_lines = 0;
333
334         snap_type_strings =  I18N (_snap_type_strings);
335         snap_mode_strings =  I18N (_snap_mode_strings);
336         zoom_focus_strings = I18N (_zoom_focus_strings);
337         edit_mode_strings = I18N (_edit_mode_strings);
338         edit_point_strings = I18N (_edit_point_strings);
339 #ifdef USE_RUBBERBAND
340         rb_opt_strings = I18N (_rb_opt_strings);
341         rb_current_opt = 4;
342 #endif
343
344         build_edit_mode_menu();
345         build_zoom_focus_menu();
346         build_track_count_menu();
347         build_snap_mode_menu();
348         build_snap_type_menu();
349         build_edit_point_menu();
350
351         snap_threshold = 5.0;
352         bbt_beat_subdivision = 4;
353         _visible_canvas_width = 0;
354         _visible_canvas_height = 0;
355         autoscroll_horizontal_allowed = false;
356         autoscroll_vertical_allowed = false;
357         logo_item = 0;
358
359         analysis_window = 0;
360
361         current_interthread_info = 0;
362         _show_measures = true;
363         _maximised = false;
364         show_gain_after_trim = false;
365
366         have_pending_keyboard_selection = false;
367         _follow_playhead = true;
368         _stationary_playhead = false;
369         editor_ruler_menu = 0;
370         no_ruler_shown_update = false;
371         marker_menu = 0;
372         range_marker_menu = 0;
373         marker_menu_item = 0;
374         tempo_or_meter_marker_menu = 0;
375         transport_marker_menu = 0;
376         new_transport_marker_menu = 0;
377         editor_mixer_strip_width = Wide;
378         show_editor_mixer_when_tracks_arrive = false;
379         region_edit_menu_split_multichannel_item = 0;
380         region_edit_menu_split_item = 0;
381         temp_location = 0;
382         leftmost_frame = 0;
383         mouse_mode = MouseObject;
384         current_stepping_trackview = 0;
385         entered_track = 0;
386         entered_regionview = 0;
387         entered_marker = 0;
388         clear_entered_track = false;
389         current_timefx = 0;
390         playhead_cursor = 0;
391         button_release_can_deselect = true;
392         _dragging_playhead = false;
393         _dragging_edit_point = false;
394         select_new_marker = false;
395         rhythm_ferret = 0;
396         layering_order_editor = 0;
397         no_save_visual = false;
398         resize_idle_id = -1;
399         within_track_canvas = false;
400
401         scrubbing_direction = 0;
402
403         sfbrowser = 0;
404
405         location_marker_color = ARDOUR_UI::config()->color ("location marker");
406         location_range_color = ARDOUR_UI::config()->color ("location range");
407         location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker");
408         location_loop_color = ARDOUR_UI::config()->color ("location loop");
409         location_punch_color = ARDOUR_UI::config()->color ("location punch");
410
411         zoom_focus = ZoomFocusPlayhead;
412         _edit_point = EditAtMouse;
413         _visible_track_count = -1;
414
415         samples_per_pixel = 2048; /* too early to use reset_zoom () */
416
417         timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
418         TimeAxisView::setup_sizes ();
419         ArdourMarker::setup_sizes (timebar_height);
420
421         _scroll_callbacks = 0;
422
423         bbt_label.set_name ("EditorRulerLabel");
424         bbt_label.set_size_request (-1, (int)timebar_height);
425         bbt_label.set_alignment (1.0, 0.5);
426         bbt_label.set_padding (5,0);
427         bbt_label.hide ();
428         bbt_label.set_no_show_all();
429         minsec_label.set_name ("EditorRulerLabel");
430         minsec_label.set_size_request (-1, (int)timebar_height);
431         minsec_label.set_alignment (1.0, 0.5);
432         minsec_label.set_padding (5,0);
433         minsec_label.hide ();
434         minsec_label.set_no_show_all();
435         timecode_label.set_name ("EditorRulerLabel");
436         timecode_label.set_size_request (-1, (int)timebar_height);
437         timecode_label.set_alignment (1.0, 0.5);
438         timecode_label.set_padding (5,0);
439         timecode_label.hide ();
440         timecode_label.set_no_show_all();
441         samples_label.set_name ("EditorRulerLabel");
442         samples_label.set_size_request (-1, (int)timebar_height);
443         samples_label.set_alignment (1.0, 0.5);
444         samples_label.set_padding (5,0);
445         samples_label.hide ();
446         samples_label.set_no_show_all();
447
448         tempo_label.set_name ("EditorRulerLabel");
449         tempo_label.set_size_request (-1, (int)timebar_height);
450         tempo_label.set_alignment (1.0, 0.5);
451         tempo_label.set_padding (5,0);
452         tempo_label.hide();
453         tempo_label.set_no_show_all();
454
455         meter_label.set_name ("EditorRulerLabel");
456         meter_label.set_size_request (-1, (int)timebar_height);
457         meter_label.set_alignment (1.0, 0.5);
458         meter_label.set_padding (5,0);
459         meter_label.hide();
460         meter_label.set_no_show_all();
461
462         if (Profile->get_trx()) {
463                 mark_label.set_text (_("Markers"));
464         }
465         mark_label.set_name ("EditorRulerLabel");
466         mark_label.set_size_request (-1, (int)timebar_height);
467         mark_label.set_alignment (1.0, 0.5);
468         mark_label.set_padding (5,0);
469         mark_label.hide();
470         mark_label.set_no_show_all();
471
472         cd_mark_label.set_name ("EditorRulerLabel");
473         cd_mark_label.set_size_request (-1, (int)timebar_height);
474         cd_mark_label.set_alignment (1.0, 0.5);
475         cd_mark_label.set_padding (5,0);
476         cd_mark_label.hide();
477         cd_mark_label.set_no_show_all();
478
479         videotl_bar_height = 4;
480         videotl_label.set_name ("EditorRulerLabel");
481         videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
482         videotl_label.set_alignment (1.0, 0.5);
483         videotl_label.set_padding (5,0);
484         videotl_label.hide();
485         videotl_label.set_no_show_all();
486
487         range_mark_label.set_name ("EditorRulerLabel");
488         range_mark_label.set_size_request (-1, (int)timebar_height);
489         range_mark_label.set_alignment (1.0, 0.5);
490         range_mark_label.set_padding (5,0);
491         range_mark_label.hide();
492         range_mark_label.set_no_show_all();
493
494         transport_mark_label.set_name ("EditorRulerLabel");
495         transport_mark_label.set_size_request (-1, (int)timebar_height);
496         transport_mark_label.set_alignment (1.0, 0.5);
497         transport_mark_label.set_padding (5,0);
498         transport_mark_label.hide();
499         transport_mark_label.set_no_show_all();
500
501         initialize_canvas ();
502
503         CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
504
505         _summary = new EditorSummary (this);
506
507         selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
508         selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
509
510         editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
511
512         selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
513         selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
514
515         edit_controls_vbox.set_spacing (0);
516         vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
517         _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
518
519         HBox* h = manage (new HBox);
520         _group_tabs = new EditorGroupTabs (this);
521         if (!ARDOUR::Profile->get_trx()) {
522                 h->pack_start (*_group_tabs, PACK_SHRINK);
523         }
524         h->pack_start (edit_controls_vbox);
525         controls_layout.add (*h);
526
527         controls_layout.set_name ("EditControlsBase");
528         controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
529         controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
530         controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
531
532         _cursors = new MouseCursors;
533         _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
534         cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
535
536         /* Push default cursor to ever-present bottom of cursor stack. */
537         push_canvas_cursor(_cursors->grabber);
538
539         ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
540
541         ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
542         pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
543         pad_line_1->set_outline_color (0xFF0000FF);
544         pad_line_1->show();
545
546         // CAIROCANVAS
547         time_pad->show();
548
549         edit_packer.set_col_spacings (0);
550         edit_packer.set_row_spacings (0);
551         edit_packer.set_homogeneous (false);
552         edit_packer.set_border_width (0);
553         edit_packer.set_name ("EditorWindow");
554
555         time_bars_event_box.add (time_bars_vbox);
556         time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
557         time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
558
559         /* labels for the time bars */
560         edit_packer.attach (time_bars_event_box,     0, 1, 0, 1,    FILL,        SHRINK, 0, 0);
561         /* track controls */
562         edit_packer.attach (controls_layout,         0, 1, 1, 2,    FILL,        FILL|EXPAND, 0, 0);
563         /* canvas */
564         edit_packer.attach (*_track_canvas_viewport,  1, 2, 0, 2,    FILL|EXPAND, FILL|EXPAND, 0, 0);
565
566         bottom_hbox.set_border_width (2);
567         bottom_hbox.set_spacing (3);
568
569         _route_groups = new EditorRouteGroups (this);
570         _routes = new EditorRoutes (this);
571         _regions = new EditorRegions (this);
572         _snapshots = new EditorSnapshots (this);
573         _locations = new EditorLocations (this);
574
575         /* these are static location signals */
576
577         Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
578         Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
579         Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
580
581         add_notebook_page (_("Regions"), _regions->widget ());
582         add_notebook_page (_("Tracks & Busses"), _routes->widget ());
583         add_notebook_page (_("Snapshots"), _snapshots->widget ());
584         add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
585         add_notebook_page (_("Ranges & Marks"), _locations->widget ());
586
587         _the_notebook.set_show_tabs (true);
588         _the_notebook.set_scrollable (true);
589         _the_notebook.popup_disable ();
590         _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
591         _the_notebook.show_all ();
592
593         _notebook_shrunk = false;
594
595         editor_summary_pane.pack1(edit_packer);
596
597         Button* summary_arrows_left_left = manage (new Button);
598         summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
599         summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
600         summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
601
602         Button* summary_arrows_left_right = manage (new Button);
603         summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
604         summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
605         summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
606
607         VBox* summary_arrows_left = manage (new VBox);
608         summary_arrows_left->pack_start (*summary_arrows_left_left);
609         summary_arrows_left->pack_start (*summary_arrows_left_right);
610
611         Button* summary_arrows_right_up = manage (new Button);
612         summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
613         summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
614         summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
615
616         Button* summary_arrows_right_down = manage (new Button);
617         summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
618         summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
619         summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
620
621         VBox* summary_arrows_right = manage (new VBox);
622         summary_arrows_right->pack_start (*summary_arrows_right_up);
623         summary_arrows_right->pack_start (*summary_arrows_right_down);
624
625         Frame* summary_frame = manage (new Frame);
626         summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
627
628         summary_frame->add (*_summary);
629         summary_frame->show ();
630
631         _summary_hbox.pack_start (*summary_arrows_left, false, false);
632         _summary_hbox.pack_start (*summary_frame, true, true);
633         _summary_hbox.pack_start (*summary_arrows_right, false, false);
634
635         if (!ARDOUR::Profile->get_trx()) {
636                 editor_summary_pane.pack2 (_summary_hbox);
637         }
638
639         edit_pane.pack1 (editor_summary_pane, true, true);
640         if (!ARDOUR::Profile->get_trx()) {
641                 edit_pane.pack2 (_the_notebook, false, true);
642         }
643
644         editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
645
646         /* XXX: editor_summary_pane might need similar to the edit_pane */
647
648         edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
649
650         Glib::PropertyProxy<int> proxy = edit_pane.property_position();
651         proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
652
653         top_hbox.pack_start (toolbar_frame);
654
655         HBox *hbox = manage (new HBox);
656         hbox->pack_start (edit_pane, true, true);
657
658         global_vpacker.pack_start (top_hbox, false, false);
659         global_vpacker.pack_start (*hbox, true, true);
660
661         global_hpacker.pack_start (global_vpacker, true, true);
662
663         set_name ("EditorWindow");
664         add_accel_group (ActionManager::ui_manager->get_accel_group());
665
666         status_bar_hpacker.show ();
667
668         vpacker.pack_end (status_bar_hpacker, false, false);
669         vpacker.pack_end (global_hpacker, true, true);
670
671         /* register actions now so that set_state() can find them and set toggles/checks etc */
672
673         register_actions ();
674         /* when we start using our own keybinding system for the editor, this
675          * will be uncommented
676          */
677         // load_bindings ();
678
679         setup_toolbar ();
680
681         set_zoom_focus (zoom_focus);
682         set_visible_track_count (_visible_track_count);
683         _snap_type = SnapToBeat;
684         set_snap_to (_snap_type);
685         _snap_mode = SnapOff;
686         set_snap_mode (_snap_mode);
687         set_mouse_mode (MouseObject, true);
688         pre_internal_snap_type = _snap_type;
689         pre_internal_snap_mode = _snap_mode;
690         internal_snap_type = _snap_type;
691         internal_snap_mode = _snap_mode;
692         set_edit_point_preference (EditAtMouse, true);
693
694         _playlist_selector = new PlaylistSelector();
695         _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
696
697         RegionView::RegionViewGoingAway.connect (*this, invalidator (*this),  boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
698
699         /* nudge stuff */
700
701         nudge_forward_button.set_name ("nudge button");
702         nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
703
704         nudge_backward_button.set_name ("nudge button");
705         nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
706
707         fade_context_menu.set_name ("ArdourContextMenu");
708
709         /* icons, titles, WM stuff */
710
711         list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
712         Glib::RefPtr<Gdk::Pixbuf> icon;
713
714         if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
715                 window_icons.push_back (icon);
716         }
717         if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
718                 window_icons.push_back (icon);
719         }
720         if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
721                 window_icons.push_back (icon);
722         }
723         if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
724                 window_icons.push_back (icon);
725         }
726         if (!window_icons.empty()) {
727                 // set_icon_list (window_icons);
728                 set_default_icon_list (window_icons);
729         }
730
731         WindowTitle title(Glib::get_application_name());
732         title += _("Editor");
733         set_title (title.get_string());
734         set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
735
736         add (vpacker);
737         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
738
739         signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
740         signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
741
742         Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
743         
744         /* allow external control surfaces/protocols to do various things */
745
746         ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
747         ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
748         ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
749         ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
750         ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
751         ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
752         ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
753         ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
754         ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
755         ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
756         ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
757         ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
758         ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
759         ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
760
761         ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
762         ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
763         ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
764         ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
765         ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
766
767         BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
768
769         /* problematic: has to return a value and thus cannot be x-thread */
770
771         Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
772
773         Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
774         ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
775
776         TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
777
778         _ignore_region_action = false;
779         _last_region_menu_was_main = false;
780         _popup_region_menu_item = 0;
781
782         _ignore_follow_edits = false;
783
784         _show_marker_lines = false;
785
786         /* Button bindings */
787
788         button_bindings = new Bindings;
789
790         XMLNode* node = button_settings();
791         if (node) {
792                 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
793                         button_bindings->load (**i);
794                 }
795         }
796
797         constructed = true;
798
799         /* grab current parameter state */
800         boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
801         ARDOUR_UI::config()->map_parameters (pc);
802
803         setup_fade_images ();
804
805         instant_save ();
806 }
807
808 Editor::~Editor()
809 {
810         delete button_bindings;
811         delete _routes;
812         delete _route_groups;
813         delete _track_canvas_viewport;
814         delete _drags;
815         delete nudge_clock;
816         delete quantize_dialog;
817         delete _summary;
818         delete _group_tabs;
819         delete _regions;
820         delete _snapshots;
821         delete _locations;
822         delete _playlist_selector;
823 }
824
825 XMLNode*
826 Editor::button_settings () const
827 {
828         XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
829         XMLNode* node = find_named_node (*settings, X_("Buttons"));
830
831         if (!node) {
832                 node = new XMLNode (X_("Buttons"));
833         }
834
835         return node;
836 }
837
838 void
839 Editor::add_toplevel_menu (Container& cont)
840 {
841         vpacker.pack_start (cont, false, false);
842         cont.show_all ();
843 }
844
845 void
846 Editor::add_transport_frame (Container& cont)
847 {
848         if(ARDOUR::Profile->get_mixbus()) {
849                 global_vpacker.pack_start (cont, false, false);
850                 global_vpacker.reorder_child (cont, 0);
851                 cont.show_all ();
852         } else {
853                 vpacker.pack_start (cont, false, false);
854         }
855 }
856
857 bool
858 Editor::get_smart_mode () const
859 {
860         return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
861 }
862
863 void
864 Editor::catch_vanishing_regionview (RegionView *rv)
865 {
866         /* note: the selection will take care of the vanishing
867            audioregionview by itself.
868         */
869
870         if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
871                 _drags->abort ();
872         }
873
874         if (clicked_regionview == rv) {
875                 clicked_regionview = 0;
876         }
877
878         if (entered_regionview == rv) {
879                 set_entered_regionview (0);
880         }
881
882         if (!_all_region_actions_sensitized) {
883                 sensitize_all_region_actions (true);
884         }
885 }
886
887 void
888 Editor::set_entered_regionview (RegionView* rv)
889 {
890         if (rv == entered_regionview) {
891                 return;
892         }
893
894         if (entered_regionview) {
895                 entered_regionview->exited ();
896         }
897
898         entered_regionview = rv;
899
900         if (entered_regionview  != 0) {
901                 entered_regionview->entered ();
902         }
903
904         if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
905                 /* This RegionView entry might have changed what region actions
906                    are allowed, so sensitize them all in case a key is pressed.
907                 */
908                 sensitize_all_region_actions (true);
909         }
910 }
911
912 void
913 Editor::set_entered_track (TimeAxisView* tav)
914 {
915         if (entered_track) {
916                 entered_track->exited ();
917         }
918
919         entered_track = tav;
920
921         if (entered_track) {
922                 entered_track->entered ();
923         }
924 }
925
926 void
927 Editor::show_window ()
928 {
929         if (!is_visible ()) {
930                 DisplaySuspender ds;
931                 show_all ();
932
933                 /* XXX: this is a bit unfortunate; it would probably
934                    be nicer if we could just call show () above rather
935                    than needing the show_all ()
936                 */
937
938                 /* re-hide stuff if necessary */
939                 editor_list_button_toggled ();
940                 parameter_changed ("show-summary");
941                 parameter_changed ("show-group-tabs");
942                 parameter_changed ("show-zoom-tools");
943
944                 /* now reset all audio_time_axis heights, because widgets might need
945                    to be re-hidden
946                 */
947
948                 TimeAxisView *tv;
949
950                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
951                         tv = (static_cast<TimeAxisView*>(*i));
952                         tv->reset_height ();
953                 }
954
955                 if (current_mixer_strip) {
956                         current_mixer_strip->hide_things ();
957                         current_mixer_strip->parameter_changed ("mixer-element-visibility");
958                 }
959         }
960
961         present ();
962 }
963
964 void
965 Editor::instant_save ()
966 {
967         if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
968                 return;
969         }
970
971         if (_session) {
972                 _session->add_instant_xml(get_state());
973         } else {
974                 Config->add_instant_xml(get_state());
975         }
976 }
977
978 void
979 Editor::control_vertical_zoom_in_all ()
980 {
981         tav_zoom_smooth (false, true);
982 }
983
984 void
985 Editor::control_vertical_zoom_out_all ()
986 {
987         tav_zoom_smooth (true, true);
988 }
989
990 void
991 Editor::control_vertical_zoom_in_selected ()
992 {
993         tav_zoom_smooth (false, false);
994 }
995
996 void
997 Editor::control_vertical_zoom_out_selected ()
998 {
999         tav_zoom_smooth (true, false);
1000 }
1001
1002 void
1003 Editor::control_view (uint32_t view)
1004 {
1005         goto_visual_state (view);
1006 }
1007
1008 void
1009 Editor::control_unselect ()
1010 {
1011         selection->clear_tracks ();
1012 }
1013
1014 void
1015 Editor::control_select (uint32_t rid, Selection::Operation op) 
1016 {
1017         /* handles the (static) signal from the ControlProtocol class that
1018          * requests setting the selected track to a given RID
1019          */
1020          
1021         if (!_session) {
1022                 return;
1023         }
1024
1025         boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1026
1027         if (!r) {
1028                 return;
1029         }
1030
1031         TimeAxisView* tav = axis_view_from_route (r);
1032
1033         if (tav) {
1034                 switch (op) {
1035                 case Selection::Add:
1036                         selection->add (tav);
1037                         break;
1038                 case Selection::Toggle:
1039                         selection->toggle (tav);
1040                         break;
1041                 case Selection::Extend:
1042                         break;
1043                 case Selection::Set:
1044                         selection->set (tav);
1045                         break;
1046                 }
1047         } else {
1048                 selection->clear_tracks ();
1049         }
1050 }
1051
1052 void
1053 Editor::control_step_tracks_up ()
1054 {
1055         scroll_tracks_up_line ();
1056 }
1057
1058 void
1059 Editor::control_step_tracks_down ()
1060 {
1061         scroll_tracks_down_line ();
1062 }
1063
1064 void
1065 Editor::control_scroll (float fraction)
1066 {
1067         ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1068
1069         if (!_session) {
1070                 return;
1071         }
1072
1073         double step = fraction * current_page_samples();
1074
1075         /*
1076                 _control_scroll_target is an optional<T>
1077
1078                 it acts like a pointer to an framepos_t, with
1079                 a operator conversion to boolean to check
1080                 that it has a value could possibly use
1081                 playhead_cursor->current_frame to store the
1082                 value and a boolean in the class to know
1083                 when it's out of date
1084         */
1085
1086         if (!_control_scroll_target) {
1087                 _control_scroll_target = _session->transport_frame();
1088                 _dragging_playhead = true;
1089         }
1090
1091         if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1092                 *_control_scroll_target = 0;
1093         } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1094                 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1095         } else {
1096                 *_control_scroll_target += (framepos_t) trunc (step);
1097         }
1098
1099         /* move visuals, we'll catch up with it later */
1100
1101         playhead_cursor->set_position (*_control_scroll_target);
1102         UpdateAllTransportClocks (*_control_scroll_target);
1103
1104         if (*_control_scroll_target > (current_page_samples() / 2)) {
1105                 /* try to center PH in window */
1106                 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1107         } else {
1108                 reset_x_origin (0);
1109         }
1110
1111         /*
1112                 Now we do a timeout to actually bring the session to the right place
1113                 according to the playhead. This is to avoid reading disk buffers on every
1114                 call to control_scroll, which is driven by ScrollTimeline and therefore
1115                 probably by a control surface wheel which can generate lots of events.
1116         */
1117         /* cancel the existing timeout */
1118
1119         control_scroll_connection.disconnect ();
1120
1121         /* add the next timeout */
1122
1123         control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1124 }
1125
1126 bool
1127 Editor::deferred_control_scroll (framepos_t /*target*/)
1128 {
1129         _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1130         // reset for next stream
1131         _control_scroll_target = boost::none;
1132         _dragging_playhead = false;
1133         return false;
1134 }
1135
1136 void
1137 Editor::access_action (std::string action_group, std::string action_item)
1138 {
1139         if (!_session) {
1140                 return;
1141         }
1142
1143         ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1144
1145         RefPtr<Action> act;
1146         act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1147
1148         if (act) {
1149                 act->activate();
1150         }
1151 }
1152
1153 void
1154 Editor::on_realize ()
1155 {
1156         Window::on_realize ();
1157         Realized ();
1158
1159         if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1160                 start_lock_event_timing ();
1161         }
1162
1163         signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
1164 }
1165
1166 void
1167 Editor::start_lock_event_timing ()
1168 {
1169         /* check if we should lock the GUI every 30 seconds */
1170
1171         Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1172 }
1173
1174 bool
1175 Editor::generic_event_handler (GdkEvent* ev)
1176 {
1177         switch (ev->type) {
1178         case GDK_BUTTON_PRESS:
1179         case GDK_BUTTON_RELEASE:
1180         case GDK_MOTION_NOTIFY:
1181         case GDK_KEY_PRESS:
1182         case GDK_KEY_RELEASE:
1183                 gettimeofday (&last_event_time, 0);
1184                 break;
1185
1186         case GDK_LEAVE_NOTIFY:
1187                 switch (ev->crossing.detail) {
1188                 case GDK_NOTIFY_UNKNOWN:
1189                 case GDK_NOTIFY_INFERIOR:
1190                 case GDK_NOTIFY_ANCESTOR:
1191                         break; 
1192                 case GDK_NOTIFY_VIRTUAL:
1193                 case GDK_NOTIFY_NONLINEAR:
1194                 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1195                         /* leaving window, so reset focus, thus ending any and
1196                            all text entry operations.
1197                         */
1198                         reset_focus();
1199                         break;
1200                 }
1201                 break;
1202
1203         default:
1204                 break;
1205         }
1206
1207         return false;
1208 }
1209
1210 bool
1211 Editor::lock_timeout_callback ()
1212 {
1213         struct timeval now, delta;
1214
1215         gettimeofday (&now, 0);
1216
1217         timersub (&now, &last_event_time, &delta);
1218
1219         if (delta.tv_sec > (time_t) ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1220                 lock ();
1221                 /* don't call again. Returning false will effectively
1222                    disconnect us from the timer callback.
1223
1224                    unlock() will call start_lock_event_timing() to get things
1225                    started again.
1226                 */
1227                 return false;
1228         }
1229
1230         return true;
1231 }
1232
1233 void
1234 Editor::map_position_change (framepos_t frame)
1235 {
1236         ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1237
1238         if (_session == 0) {
1239                 return;
1240         }
1241
1242         if (_follow_playhead) {
1243                 center_screen (frame);
1244         }
1245
1246         playhead_cursor->set_position (frame);
1247 }
1248
1249 void
1250 Editor::center_screen (framepos_t frame)
1251 {
1252         framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1253
1254         /* if we're off the page, then scroll.
1255          */
1256
1257         if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1258                 center_screen_internal (frame, page);
1259         }
1260 }
1261
1262 void
1263 Editor::center_screen_internal (framepos_t frame, float page)
1264 {
1265         page /= 2;
1266
1267         if (frame > page) {
1268                 frame -= (framepos_t) page;
1269         } else {
1270                 frame = 0;
1271         }
1272
1273         reset_x_origin (frame);
1274 }
1275
1276
1277 void
1278 Editor::update_title ()
1279 {
1280         ENSURE_GUI_THREAD (*this, &Editor::update_title)
1281
1282         if (_session) {
1283                 bool dirty = _session->dirty();
1284
1285                 string session_name;
1286
1287                 if (_session->snap_name() != _session->name()) {
1288                         session_name = _session->snap_name();
1289                 } else {
1290                         session_name = _session->name();
1291                 }
1292
1293                 if (dirty) {
1294                         session_name = "*" + session_name;
1295                 }
1296
1297                 WindowTitle title(session_name);
1298                 title += Glib::get_application_name();
1299                 set_title (title.get_string());
1300         } else {
1301                 /* ::session_going_away() will have taken care of it */
1302         }
1303 }
1304
1305 void
1306 Editor::set_session (Session *t)
1307 {
1308         SessionHandlePtr::set_session (t);
1309
1310         if (!_session) {
1311                 return;
1312         }
1313
1314         _playlist_selector->set_session (_session);
1315         nudge_clock->set_session (_session);
1316         _summary->set_session (_session);
1317         _group_tabs->set_session (_session);
1318         _route_groups->set_session (_session);
1319         _regions->set_session (_session);
1320         _snapshots->set_session (_session);
1321         _routes->set_session (_session);
1322         _locations->set_session (_session);
1323
1324         if (rhythm_ferret) {
1325                 rhythm_ferret->set_session (_session);
1326         }
1327
1328         if (analysis_window) {
1329                 analysis_window->set_session (_session);
1330         }
1331
1332         if (sfbrowser) {
1333                 sfbrowser->set_session (_session);
1334         }
1335
1336         compute_fixed_ruler_scale ();
1337
1338         /* Make sure we have auto loop and auto punch ranges */
1339
1340         Location* loc = _session->locations()->auto_loop_location();
1341         if (loc != 0) {
1342                 loc->set_name (_("Loop"));
1343         }
1344
1345         loc = _session->locations()->auto_punch_location();
1346         if (loc != 0) {
1347                 // force name
1348                 loc->set_name (_("Punch"));
1349         }
1350
1351         refresh_location_display ();
1352
1353         /* This must happen after refresh_location_display(), as (amongst other things) we restore
1354            the selected Marker; this needs the LocationMarker list to be available.
1355         */
1356         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1357         set_state (*node, Stateful::loading_state_version);
1358
1359         /* catch up with the playhead */
1360
1361         _session->request_locate (playhead_cursor->current_frame ());
1362         _pending_initial_locate = true;
1363
1364         update_title ();
1365
1366         /* These signals can all be emitted by a non-GUI thread. Therefore the
1367            handlers for them must not attempt to directly interact with the GUI,
1368            but use PBD::Signal<T>::connect() which accepts an event loop
1369            ("context") where the handler will be asked to run.
1370         */
1371
1372         _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1373         _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1374         _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1375         _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1376         _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1377         _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1378         _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1379         _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1380         _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1381         _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1382         _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1383         _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1384         _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1385
1386         playhead_cursor->show ();
1387
1388         boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1389         Config->map_parameters (pc);
1390         _session->config.map_parameters (pc);
1391
1392         restore_ruler_visibility ();
1393         //tempo_map_changed (PropertyChange (0));
1394         _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1395
1396         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1397                 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1398         }
1399
1400         super_rapid_screen_update_connection = Timers::super_rapid_connect (
1401                 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1402                 );
1403
1404         switch (_snap_type) {
1405         case SnapToRegionStart:
1406         case SnapToRegionEnd:
1407         case SnapToRegionSync:
1408         case SnapToRegionBoundary:
1409                 build_region_boundary_cache ();
1410                 break;
1411
1412         default:
1413                 break;
1414         }
1415
1416         /* register for undo history */
1417         _session->register_with_memento_command_factory(id(), this);
1418         _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1419
1420         ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1421
1422         start_updating_meters ();
1423 }
1424
1425 void
1426 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1427 {
1428         if (a->get_name() == "RegionMenu") {
1429                 /* When the main menu's region menu is opened, we setup the actions so that they look right
1430                    in the menu.  I can't find a way of getting a signal when this menu is subsequently closed,
1431                    so we resensitize all region actions when the entered regionview or the region selection
1432                    changes.  HOWEVER we can't always resensitize on entered_regionview change because that
1433                    happens after the region context menu is opened.  So we set a flag here, too.
1434
1435                    What a carry on :(
1436                 */
1437                 sensitize_the_right_region_actions ();
1438                 _last_region_menu_was_main = true;
1439         }
1440 }
1441
1442 void
1443 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1444 {
1445         using namespace Menu_Helpers;
1446
1447         void (Editor::*emf)(FadeShape);
1448         std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1449
1450         if (start) {
1451                 images = &_xfade_in_images;
1452                 emf = &Editor::set_fade_in_shape;
1453         } else {
1454                 images = &_xfade_out_images;
1455                 emf = &Editor::set_fade_out_shape;
1456         }
1457
1458         items.push_back (
1459                 ImageMenuElem (
1460                         _("Linear (for highly correlated material)"),
1461                         *(*images)[FadeLinear],
1462                         sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1463                         )
1464                 );
1465         
1466         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1467         
1468         items.push_back (
1469                 ImageMenuElem (
1470                         _("Constant power"),
1471                         *(*images)[FadeConstantPower],
1472                         sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1473                         ));
1474         
1475         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1476         
1477         items.push_back (
1478                 ImageMenuElem (
1479                         _("Symmetric"),
1480                         *(*images)[FadeSymmetric],
1481                         sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1482                         )
1483                 );
1484         
1485         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1486         
1487         items.push_back (
1488                 ImageMenuElem (
1489                         _("Slow"),
1490                         *(*images)[FadeSlow],
1491                         sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1492                         ));
1493         
1494         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1495         
1496         items.push_back (
1497                 ImageMenuElem (
1498                         _("Fast"),
1499                         *(*images)[FadeFast],
1500                         sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1501                         ));
1502         
1503         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1504 }
1505
1506 /** Pop up a context menu for when the user clicks on a start crossfade */
1507 void
1508 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1509 {
1510         using namespace Menu_Helpers;
1511         AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1512         if (!arv) {
1513                 return;
1514         }
1515
1516         MenuList& items (xfade_in_context_menu.items());
1517         items.clear ();
1518
1519         if (arv->audio_region()->fade_in_active()) {
1520                 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1521         } else {
1522                 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1523         }
1524
1525         items.push_back (SeparatorElem());
1526         fill_xfade_menu (items, true);
1527
1528         xfade_in_context_menu.popup (button, time);
1529 }
1530
1531 /** Pop up a context menu for when the user clicks on an end crossfade */
1532 void
1533 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1534 {
1535         using namespace Menu_Helpers;
1536         AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1537         if (!arv) {
1538                 return;
1539         }
1540
1541         MenuList& items (xfade_out_context_menu.items());
1542         items.clear ();
1543
1544         if (arv->audio_region()->fade_out_active()) {
1545                 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1546         } else {
1547                 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1548         }
1549
1550         items.push_back (SeparatorElem());
1551         fill_xfade_menu (items, false);
1552
1553         xfade_out_context_menu.popup (button, time);
1554 }
1555
1556 void
1557 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1558 {
1559         using namespace Menu_Helpers;
1560         Menu* (Editor::*build_menu_function)();
1561         Menu *menu;
1562
1563         switch (item_type) {
1564         case RegionItem:
1565         case RegionViewName:
1566         case RegionViewNameHighlight:
1567         case LeftFrameHandle:
1568         case RightFrameHandle:
1569                 if (with_selection) {
1570                         build_menu_function = &Editor::build_track_selection_context_menu;
1571                 } else {
1572                         build_menu_function = &Editor::build_track_region_context_menu;
1573                 }
1574                 break;
1575
1576         case SelectionItem:
1577                 if (with_selection) {
1578                         build_menu_function = &Editor::build_track_selection_context_menu;
1579                 } else {
1580                         build_menu_function = &Editor::build_track_context_menu;
1581                 }
1582                 break;
1583
1584         case StreamItem:
1585                 if (clicked_routeview->track()) {
1586                         build_menu_function = &Editor::build_track_context_menu;
1587                 } else {
1588                         build_menu_function = &Editor::build_track_bus_context_menu;
1589                 }
1590                 break;
1591
1592         default:
1593                 /* probably shouldn't happen but if it does, we don't care */
1594                 return;
1595         }
1596
1597         menu = (this->*build_menu_function)();
1598         menu->set_name ("ArdourContextMenu");
1599
1600         /* now handle specific situations */
1601
1602         switch (item_type) {
1603         case RegionItem:
1604         case RegionViewName:
1605         case RegionViewNameHighlight:
1606         case LeftFrameHandle:
1607         case RightFrameHandle:
1608                 if (!with_selection) {
1609                         if (region_edit_menu_split_item) {
1610                                 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1611                                         ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1612                                 } else {
1613                                         ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1614                                 }
1615                         }
1616                         if (region_edit_menu_split_multichannel_item) {
1617                                 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1618                                         region_edit_menu_split_multichannel_item->set_sensitive (true);
1619                                 } else {
1620                                         region_edit_menu_split_multichannel_item->set_sensitive (false);
1621                                 }
1622                         }
1623                 }
1624                 break;
1625
1626         case SelectionItem:
1627                 break;
1628
1629         case StreamItem:
1630                 break;
1631
1632         default:
1633                 /* probably shouldn't happen but if it does, we don't care */
1634                 return;
1635         }
1636
1637         if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1638
1639                 /* Bounce to disk */
1640
1641                 using namespace Menu_Helpers;
1642                 MenuList& edit_items  = menu->items();
1643
1644                 edit_items.push_back (SeparatorElem());
1645
1646                 switch (clicked_routeview->audio_track()->freeze_state()) {
1647                 case AudioTrack::NoFreeze:
1648                         edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1649                         break;
1650
1651                 case AudioTrack::Frozen:
1652                         edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1653                         break;
1654
1655                 case AudioTrack::UnFrozen:
1656                         edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1657                         break;
1658                 }
1659
1660         }
1661
1662         if (item_type == StreamItem && clicked_routeview) {
1663                 clicked_routeview->build_underlay_menu(menu);
1664         }
1665
1666         /* When the region menu is opened, we setup the actions so that they look right
1667            in the menu.
1668         */
1669         sensitize_the_right_region_actions ();
1670         _last_region_menu_was_main = false;
1671
1672         menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1673         menu->popup (button, time);
1674 }
1675
1676 Menu*
1677 Editor::build_track_context_menu ()
1678 {
1679         using namespace Menu_Helpers;
1680
1681         MenuList& edit_items = track_context_menu.items();
1682         edit_items.clear();
1683
1684         add_dstream_context_items (edit_items);
1685         return &track_context_menu;
1686 }
1687
1688 Menu*
1689 Editor::build_track_bus_context_menu ()
1690 {
1691         using namespace Menu_Helpers;
1692
1693         MenuList& edit_items = track_context_menu.items();
1694         edit_items.clear();
1695
1696         add_bus_context_items (edit_items);
1697         return &track_context_menu;
1698 }
1699
1700 Menu*
1701 Editor::build_track_region_context_menu ()
1702 {
1703         using namespace Menu_Helpers;
1704         MenuList& edit_items  = track_region_context_menu.items();
1705         edit_items.clear();
1706
1707         /* we've just cleared the track region context menu, so the menu that these
1708            two items were on will have disappeared; stop them dangling.
1709         */
1710         region_edit_menu_split_item = 0;
1711         region_edit_menu_split_multichannel_item = 0;
1712
1713         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1714
1715         if (rtv) {
1716                 boost::shared_ptr<Track> tr;
1717                 boost::shared_ptr<Playlist> pl;
1718
1719                 if ((tr = rtv->track())) {
1720                         add_region_context_items (edit_items, tr);
1721                 }
1722         }
1723
1724         add_dstream_context_items (edit_items);
1725
1726         return &track_region_context_menu;
1727 }
1728
1729 void
1730 Editor::analyze_region_selection ()
1731 {
1732         if (analysis_window == 0) {
1733                 analysis_window = new AnalysisWindow();
1734
1735                 if (_session != 0)
1736                         analysis_window->set_session(_session);
1737
1738                 analysis_window->show_all();
1739         }
1740
1741         analysis_window->set_regionmode();
1742         analysis_window->analyze();
1743
1744         analysis_window->present();
1745 }
1746
1747 void
1748 Editor::analyze_range_selection()
1749 {
1750         if (analysis_window == 0) {
1751                 analysis_window = new AnalysisWindow();
1752
1753                 if (_session != 0)
1754                         analysis_window->set_session(_session);
1755
1756                 analysis_window->show_all();
1757         }
1758
1759         analysis_window->set_rangemode();
1760         analysis_window->analyze();
1761
1762         analysis_window->present();
1763 }
1764
1765 Menu*
1766 Editor::build_track_selection_context_menu ()
1767 {
1768         using namespace Menu_Helpers;
1769         MenuList& edit_items  = track_selection_context_menu.items();
1770         edit_items.clear ();
1771
1772         add_selection_context_items (edit_items);
1773         // edit_items.push_back (SeparatorElem());
1774         // add_dstream_context_items (edit_items);
1775
1776         return &track_selection_context_menu;
1777 }
1778
1779 void
1780 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1781 {
1782         using namespace Menu_Helpers;
1783
1784         /* OK, stick the region submenu at the top of the list, and then add
1785            the standard items.
1786         */
1787
1788         RegionSelection rs = get_regions_from_selection_and_entered ();
1789
1790         string::size_type pos = 0;
1791         string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1792
1793         /* we have to hack up the region name because "_" has a special
1794            meaning for menu titles.
1795         */
1796
1797         while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1798                 menu_item_name.replace (pos, 1, "__");
1799                 pos += 2;
1800         }
1801
1802         if (_popup_region_menu_item == 0) {
1803                 _popup_region_menu_item = new MenuItem (menu_item_name);
1804                 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1805                 _popup_region_menu_item->show ();
1806         } else {
1807                 _popup_region_menu_item->set_label (menu_item_name);
1808         }
1809
1810         /* No latering allowed in later is higher layering model */
1811         RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1812         if (act && Config->get_layer_model() == LaterHigher) {
1813                 act->set_sensitive (false);
1814         } else if (act) {
1815                 act->set_sensitive (true);
1816         }
1817
1818         const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1819
1820         edit_items.push_back (*_popup_region_menu_item);
1821         if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1822                 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1823         }
1824         edit_items.push_back (SeparatorElem());
1825 }
1826
1827 /** Add context menu items relevant to selection ranges.
1828  * @param edit_items List to add the items to.
1829  */
1830 void
1831 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1832 {
1833         using namespace Menu_Helpers;
1834
1835         edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1836         edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1837
1838         edit_items.push_back (SeparatorElem());
1839         edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1840
1841         edit_items.push_back (SeparatorElem());
1842         edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1843
1844         edit_items.push_back (SeparatorElem());
1845
1846         edit_items.push_back (
1847                 MenuElem (
1848                         _("Move Range Start to Previous Region Boundary"),
1849                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1850                         )
1851                 );
1852
1853         edit_items.push_back (
1854                 MenuElem (
1855                         _("Move Range Start to Next Region Boundary"),
1856                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1857                         )
1858                 );
1859
1860         edit_items.push_back (
1861                 MenuElem (
1862                         _("Move Range End to Previous Region Boundary"),
1863                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1864                         )
1865                 );
1866
1867         edit_items.push_back (
1868                 MenuElem (
1869                         _("Move Range End to Next Region Boundary"),
1870                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1871                         )
1872                 );
1873
1874         edit_items.push_back (SeparatorElem());
1875         edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1876         edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1877
1878         edit_items.push_back (SeparatorElem());
1879         edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1880
1881         edit_items.push_back (SeparatorElem());
1882         edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1883         edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1884         edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1885
1886         edit_items.push_back (SeparatorElem());
1887         edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1888
1889         edit_items.push_back (SeparatorElem());
1890         edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1891         edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1892         edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1893
1894         edit_items.push_back (SeparatorElem());
1895         edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1896         edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1897         edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1898         edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1899         edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1900         if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1901                 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1902         }
1903 }
1904
1905
1906 void
1907 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1908 {
1909         using namespace Menu_Helpers;
1910
1911         /* Playback */
1912
1913         Menu *play_menu = manage (new Menu);
1914         MenuList& play_items = play_menu->items();
1915         play_menu->set_name ("ArdourContextMenu");
1916
1917         play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1918         play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1919         play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1920         play_items.push_back (SeparatorElem());
1921         play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1922
1923         edit_items.push_back (MenuElem (_("Play"), *play_menu));
1924
1925         /* Selection */
1926
1927         Menu *select_menu = manage (new Menu);
1928         MenuList& select_items = select_menu->items();
1929         select_menu->set_name ("ArdourContextMenu");
1930
1931         select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1932         select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1933         select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1934         select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1935         select_items.push_back (SeparatorElem());
1936         select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1937         select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1938         select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
1939         select_items.push_back (SeparatorElem());
1940         select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1941         select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1942         select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1943         select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1944         select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1945         select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1946         select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1947
1948         edit_items.push_back (MenuElem (_("Select"), *select_menu));
1949
1950         /* Cut-n-Paste */
1951
1952         Menu *cutnpaste_menu = manage (new Menu);
1953         MenuList& cutnpaste_items = cutnpaste_menu->items();
1954         cutnpaste_menu->set_name ("ArdourContextMenu");
1955
1956         cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1957         cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1958         cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1959
1960         cutnpaste_items.push_back (SeparatorElem());
1961
1962         cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1963         cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1964
1965         edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1966
1967         /* Adding new material */
1968
1969         edit_items.push_back (SeparatorElem());
1970         edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1971         edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1972
1973         /* Nudge track */
1974
1975         Menu *nudge_menu = manage (new Menu());
1976         MenuList& nudge_items = nudge_menu->items();
1977         nudge_menu->set_name ("ArdourContextMenu");
1978
1979         edit_items.push_back (SeparatorElem());
1980         nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1981         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1982         nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1983         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1984
1985         edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1986 }
1987
1988 void
1989 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1990 {
1991         using namespace Menu_Helpers;
1992
1993         /* Playback */
1994
1995         Menu *play_menu = manage (new Menu);
1996         MenuList& play_items = play_menu->items();
1997         play_menu->set_name ("ArdourContextMenu");
1998
1999         play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2000         play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2001         edit_items.push_back (MenuElem (_("Play"), *play_menu));
2002
2003         /* Selection */
2004
2005         Menu *select_menu = manage (new Menu);
2006         MenuList& select_items = select_menu->items();
2007         select_menu->set_name ("ArdourContextMenu");
2008
2009         select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2010         select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2011         select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2012         select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2013         select_items.push_back (SeparatorElem());
2014         select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
2015         select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
2016         select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2017         select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2018
2019         edit_items.push_back (MenuElem (_("Select"), *select_menu));
2020
2021         /* Cut-n-Paste */
2022
2023         Menu *cutnpaste_menu = manage (new Menu);
2024         MenuList& cutnpaste_items = cutnpaste_menu->items();
2025         cutnpaste_menu->set_name ("ArdourContextMenu");
2026
2027         cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2028         cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2029         cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2030
2031         Menu *nudge_menu = manage (new Menu());
2032         MenuList& nudge_items = nudge_menu->items();
2033         nudge_menu->set_name ("ArdourContextMenu");
2034
2035         edit_items.push_back (SeparatorElem());
2036         nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2037         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2038         nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2039         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2040
2041         edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2042 }
2043
2044 SnapType
2045 Editor::snap_type() const
2046 {
2047         return _snap_type;
2048 }
2049
2050 SnapMode
2051 Editor::snap_mode() const
2052 {
2053         return _snap_mode;
2054 }
2055
2056 void
2057 Editor::set_snap_to (SnapType st)
2058 {
2059         unsigned int snap_ind = (unsigned int)st;
2060
2061         if (internal_editing()) {
2062                 internal_snap_type = st;
2063         } else {
2064                 pre_internal_snap_type = st;
2065         }
2066
2067         _snap_type = st;
2068
2069         if (snap_ind > snap_type_strings.size() - 1) {
2070                 snap_ind = 0;
2071                 _snap_type = (SnapType)snap_ind;
2072         }
2073
2074         string str = snap_type_strings[snap_ind];
2075
2076         if (str != snap_type_selector.get_text()) {
2077                 snap_type_selector.set_text (str);
2078         }
2079
2080         instant_save ();
2081
2082         switch (_snap_type) {
2083         case SnapToBeatDiv128:
2084         case SnapToBeatDiv64:
2085         case SnapToBeatDiv32:
2086         case SnapToBeatDiv28:
2087         case SnapToBeatDiv24:
2088         case SnapToBeatDiv20:
2089         case SnapToBeatDiv16:
2090         case SnapToBeatDiv14:
2091         case SnapToBeatDiv12:
2092         case SnapToBeatDiv10:
2093         case SnapToBeatDiv8:
2094         case SnapToBeatDiv7:
2095         case SnapToBeatDiv6:
2096         case SnapToBeatDiv5:
2097         case SnapToBeatDiv4:
2098         case SnapToBeatDiv3:
2099         case SnapToBeatDiv2: {
2100                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2101                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2102                 
2103                 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2104                                             current_bbt_points_begin, current_bbt_points_end);
2105                 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2106                                          current_bbt_points_begin, current_bbt_points_end);
2107                 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2108                 break;
2109         }
2110
2111         case SnapToRegionStart:
2112         case SnapToRegionEnd:
2113         case SnapToRegionSync:
2114         case SnapToRegionBoundary:
2115                 build_region_boundary_cache ();
2116                 break;
2117
2118         default:
2119                 /* relax */
2120                 break;
2121         }
2122
2123         redisplay_tempo (false);
2124
2125         SnapChanged (); /* EMIT SIGNAL */
2126 }
2127
2128 void
2129 Editor::set_snap_mode (SnapMode mode)
2130 {
2131         string str = snap_mode_strings[(int)mode];
2132
2133         if (internal_editing()) {
2134                 internal_snap_mode = mode;
2135         } else {
2136                 pre_internal_snap_mode = mode;
2137         }
2138
2139         _snap_mode = mode;
2140
2141         if (str != snap_mode_selector.get_text ()) {
2142                 snap_mode_selector.set_text (str);
2143         }
2144
2145         instant_save ();
2146 }
2147
2148 void
2149 Editor::set_edit_point_preference (EditPoint ep, bool force)
2150 {
2151         bool changed = (_edit_point != ep);
2152
2153         _edit_point = ep;
2154         if (Profile->get_mixbus())
2155                 if (ep == EditAtSelectedMarker)
2156                         ep = EditAtPlayhead;
2157
2158         string str = edit_point_strings[(int)ep];
2159         if (str != edit_point_selector.get_text ()) {
2160                 edit_point_selector.set_text (str);
2161         }
2162
2163         update_all_enter_cursors();
2164
2165         if (!force && !changed) {
2166                 return;
2167         }
2168
2169         const char* action=NULL;
2170
2171         switch (_edit_point) {
2172         case EditAtPlayhead:
2173                 action = "edit-at-playhead";
2174                 break;
2175         case EditAtSelectedMarker:
2176                 action = "edit-at-marker";
2177                 break;
2178         case EditAtMouse:
2179                 action = "edit-at-mouse";
2180                 break;
2181         }
2182
2183         Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2184         if (act) {
2185                 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2186         }
2187
2188         framepos_t foo;
2189         bool in_track_canvas;
2190
2191         if (!mouse_frame (foo, in_track_canvas)) {
2192                 in_track_canvas = false;
2193         }
2194
2195         reset_canvas_action_sensitivity (in_track_canvas);
2196
2197         instant_save ();
2198 }
2199
2200 int
2201 Editor::set_state (const XMLNode& node, int /*version*/)
2202 {
2203         const XMLProperty* prop;
2204         XMLNode* geometry;
2205         int x, y;
2206         Gdk::Geometry g;
2207
2208         set_id (node);
2209
2210         g.base_width = default_width;
2211         g.base_height = default_height;
2212         x = 1;
2213         y = 1;
2214
2215         if ((geometry = find_named_node (node, "geometry")) != 0) {
2216
2217                 XMLProperty* prop;
2218
2219                 if ((prop = geometry->property("x_size")) == 0) {
2220                         prop = geometry->property ("x-size");
2221                 }
2222                 if (prop) {
2223                         g.base_width = atoi(prop->value());
2224                 }
2225                 if ((prop = geometry->property("y_size")) == 0) {
2226                         prop = geometry->property ("y-size");
2227                 }
2228                 if (prop) {
2229                         g.base_height = atoi(prop->value());
2230                 }
2231
2232                 if ((prop = geometry->property ("x_pos")) == 0) {
2233                         prop = geometry->property ("x-pos");
2234                 }
2235                 if (prop) {
2236                         x = atoi (prop->value());
2237
2238                 }
2239                 if ((prop = geometry->property ("y_pos")) == 0) {
2240                         prop = geometry->property ("y-pos");
2241                 }
2242                 if (prop) {
2243                         y = atoi (prop->value());
2244                 }
2245         }
2246
2247         set_default_size (g.base_width, g.base_height);
2248         move (x, y);
2249
2250         if (_session && (prop = node.property ("playhead"))) {
2251                 framepos_t pos;
2252                 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2253                 if (pos >= 0) {
2254                         playhead_cursor->set_position (pos);
2255                 } else {
2256                         warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2257                         playhead_cursor->set_position (0);
2258                 }
2259         } else {
2260                 playhead_cursor->set_position (0);
2261         }
2262
2263         if ((prop = node.property ("mixer-width"))) {
2264                 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2265         }
2266
2267         if ((prop = node.property ("zoom-focus"))) {
2268                 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2269         }
2270
2271         if ((prop = node.property ("zoom"))) {
2272                 /* older versions of ardour used floating point samples_per_pixel */
2273                 double f = PBD::atof (prop->value());
2274                 reset_zoom (llrintf (f));
2275         } else {
2276                 reset_zoom (samples_per_pixel);
2277         }
2278
2279         if ((prop = node.property ("visible-track-count"))) {
2280                 set_visible_track_count (PBD::atoi (prop->value()));
2281         }
2282
2283         if ((prop = node.property ("snap-to"))) {
2284                 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2285         }
2286
2287         if ((prop = node.property ("snap-mode"))) {
2288                 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2289         }
2290
2291         if ((prop = node.property ("internal-snap-to"))) {
2292                 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2293         }
2294
2295         if ((prop = node.property ("internal-snap-mode"))) {
2296                 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2297         }
2298
2299         if ((prop = node.property ("pre-internal-snap-to"))) {
2300                 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2301         }
2302
2303         if ((prop = node.property ("pre-internal-snap-mode"))) {
2304                 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2305         }
2306
2307         if ((prop = node.property ("mouse-mode"))) {
2308                 MouseMode m = str2mousemode(prop->value());
2309                 set_mouse_mode (m, true);
2310         } else {
2311                 set_mouse_mode (MouseObject, true);
2312         }
2313
2314         if ((prop = node.property ("left-frame")) != 0) {
2315                 framepos_t pos;
2316                 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2317                         if (pos < 0) {
2318                                 pos = 0;
2319                         }
2320                         reset_x_origin (pos);
2321                 }
2322         }
2323
2324         if ((prop = node.property ("y-origin")) != 0) {
2325                 reset_y_origin (atof (prop->value ()));
2326         }
2327
2328         if ((prop = node.property ("join-object-range"))) {
2329                 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2330                 bool yn = string_is_affirmative (prop->value());
2331                 if (act) {
2332                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2333                         tact->set_active (!yn);
2334                         tact->set_active (yn);
2335                 }
2336                 set_mouse_mode(mouse_mode, true);
2337         }
2338
2339         if ((prop = node.property ("edit-point"))) {
2340                 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2341         }
2342
2343         if ((prop = node.property ("show-measures"))) {
2344                 bool yn = string_is_affirmative (prop->value());
2345                 _show_measures = yn;
2346         }
2347
2348         if ((prop = node.property ("follow-playhead"))) {
2349                 bool yn = string_is_affirmative (prop->value());
2350                 set_follow_playhead (yn);
2351         }
2352
2353         if ((prop = node.property ("stationary-playhead"))) {
2354                 bool yn = string_is_affirmative (prop->value());
2355                 set_stationary_playhead (yn);
2356         }
2357
2358         if ((prop = node.property ("region-list-sort-type"))) {
2359                 RegionListSortType st;
2360                 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2361         }
2362
2363         if ((prop = node.property ("show-editor-mixer"))) {
2364
2365                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2366                 assert (act);
2367
2368                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2369                 bool yn = string_is_affirmative (prop->value());
2370
2371                 /* do it twice to force the change */
2372
2373                 tact->set_active (!yn);
2374                 tact->set_active (yn);
2375         }
2376
2377         if ((prop = node.property ("show-editor-list"))) {
2378
2379                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2380                 assert (act);
2381
2382                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2383                 bool yn = string_is_affirmative (prop->value());
2384
2385                 /* do it twice to force the change */
2386
2387                 tact->set_active (!yn);
2388                 tact->set_active (yn);
2389         }
2390
2391         if ((prop = node.property (X_("editor-list-page")))) {
2392                 _the_notebook.set_current_page (atoi (prop->value ()));
2393         }
2394
2395         if ((prop = node.property (X_("show-marker-lines")))) {
2396                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2397                 assert (act);
2398                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2399                 bool yn = string_is_affirmative (prop->value ());
2400
2401                 tact->set_active (!yn);
2402                 tact->set_active (yn);
2403         }
2404
2405         XMLNodeList children = node.children ();
2406         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2407                 selection->set_state (**i, Stateful::current_state_version);
2408                 _regions->set_state (**i);
2409         }
2410
2411         if ((prop = node.property ("maximised"))) {
2412                 bool yn = string_is_affirmative (prop->value());
2413                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2414                 assert (act);
2415                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2416                 bool fs = tact && tact->get_active();
2417                 if (yn ^ fs) {
2418                         ActionManager::do_action ("Common", "ToggleMaximalEditor");
2419                 }
2420         }
2421
2422         if ((prop = node.property ("nudge-clock-value"))) {
2423                 framepos_t f;
2424                 sscanf (prop->value().c_str(), "%" PRId64, &f);
2425                 nudge_clock->set (f);
2426         } else {
2427                 nudge_clock->set_mode (AudioClock::Timecode);
2428                 nudge_clock->set (_session->frame_rate() * 5, true);
2429         }
2430
2431         {
2432                 /* apply state
2433                  * Not all properties may have been in XML, but
2434                  * those that are linked to a private variable may need changing
2435                  */
2436                 RefPtr<Action> act;
2437                 bool yn;
2438
2439                 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2440                 if (act) {
2441                         yn = _show_measures;
2442                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2443                         /* do it twice to force the change */
2444                         tact->set_active (!yn);
2445                         tact->set_active (yn);
2446                 }
2447
2448                 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2449                 yn = _follow_playhead;
2450                 if (act) {
2451                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2452                         if (tact->get_active() != yn) {
2453                                 tact->set_active (yn);
2454                         }
2455                 }
2456
2457                 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2458                 yn = _stationary_playhead;
2459                 if (act) {
2460                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2461                         if (tact->get_active() != yn) {
2462                                 tact->set_active (yn);
2463                         }
2464                 }
2465         }
2466
2467         return 0;
2468 }
2469
2470 XMLNode&
2471 Editor::get_state ()
2472 {
2473         XMLNode* node = new XMLNode ("Editor");
2474         char buf[32];
2475
2476         id().print (buf, sizeof (buf));
2477         node->add_property ("id", buf);
2478
2479         if (is_realized()) {
2480                 Glib::RefPtr<Gdk::Window> win = get_window();
2481
2482                 int x, y, width, height;
2483                 win->get_root_origin(x, y);
2484                 win->get_size(width, height);
2485
2486                 XMLNode* geometry = new XMLNode ("geometry");
2487
2488                 snprintf(buf, sizeof(buf), "%d", width);
2489                 geometry->add_property("x-size", string(buf));
2490                 snprintf(buf, sizeof(buf), "%d", height);
2491                 geometry->add_property("y-size", string(buf));
2492                 snprintf(buf, sizeof(buf), "%d", x);
2493                 geometry->add_property("x-pos", string(buf));
2494                 snprintf(buf, sizeof(buf), "%d", y);
2495                 geometry->add_property("y-pos", string(buf));
2496                 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2497                 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2498                 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2499                 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2500                 geometry->add_property("edit-vertical-pane-pos", string(buf));
2501
2502                 node->add_child_nocopy (*geometry);
2503         }
2504
2505         maybe_add_mixer_strip_width (*node);
2506
2507         node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2508
2509         snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2510         node->add_property ("zoom", buf);
2511         node->add_property ("snap-to", enum_2_string (_snap_type));
2512         node->add_property ("snap-mode", enum_2_string (_snap_mode));
2513         node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2514         node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2515         node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2516         node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2517         node->add_property ("edit-point", enum_2_string (_edit_point));
2518         snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2519         node->add_property ("visible-track-count", buf);
2520
2521         snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2522         node->add_property ("playhead", buf);
2523         snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2524         node->add_property ("left-frame", buf);
2525         snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2526         node->add_property ("y-origin", buf);
2527
2528         node->add_property ("show-measures", _show_measures ? "yes" : "no");
2529         node->add_property ("maximised", _maximised ? "yes" : "no");
2530         node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2531         node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2532         node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2533         node->add_property ("mouse-mode", enum2str(mouse_mode));
2534         node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2535
2536         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2537         if (act) {
2538                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2539                 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2540         }
2541
2542         act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2543         if (act) {
2544                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2545                 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2546         }
2547
2548         snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2549         node->add_property (X_("editor-list-page"), buf);
2550
2551         if (button_bindings) {
2552                 XMLNode* bb = new XMLNode (X_("Buttons"));
2553                 button_bindings->save (*bb);
2554                 node->add_child_nocopy (*bb);
2555         }
2556
2557         node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2558
2559         node->add_child_nocopy (selection->get_state ());
2560         node->add_child_nocopy (_regions->get_state ());
2561
2562         snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2563         node->add_property ("nudge-clock-value", buf);
2564
2565         return *node;
2566 }
2567
2568 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2569  *  if @param trackview_relative_offset is false, @param y y is a global canvas *  coordinate, in pixel units
2570  *
2571  *  @return pair: TimeAxisView that y is over, layer index.
2572  *
2573  *  TimeAxisView may be 0.  Layer index is the layer number if the TimeAxisView is valid and is
2574  *  in stacked or expanded region display mode, otherwise 0.
2575  */
2576 std::pair<TimeAxisView *, double>
2577 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2578 {
2579         if (!trackview_relative_offset) {
2580                 y -= _trackview_group->canvas_origin().y;
2581         }
2582
2583         if (y < 0) {
2584                 return std::make_pair ( (TimeAxisView *) 0, 0);
2585         }
2586
2587         for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2588                         
2589                 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2590                         
2591                 if (r.first) {
2592                         return r;
2593                 }
2594         }
2595
2596         return std::make_pair ( (TimeAxisView *) 0, 0);
2597 }
2598
2599 /** Snap a position to the grid, if appropriate, taking into account current
2600  *  grid settings and also the state of any snap modifier keys that may be pressed.
2601  *  @param start Position to snap.
2602  *  @param event Event to get current key modifier information from, or 0.
2603  */
2604 void
2605 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2606 {
2607         if (!_session || !event) {
2608                 return;
2609         }
2610
2611         if (ArdourKeyboard::indicates_snap (event->button.state)) {
2612                 if (_snap_mode == SnapOff) {
2613                         snap_to_internal (start, direction, for_mark);
2614                 }
2615         } else {
2616                 if (_snap_mode != SnapOff) {
2617                         snap_to_internal (start, direction, for_mark);
2618                 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2619                         /* SnapOff, but we pressed the snap_delta modifier */
2620                         snap_to_internal (start, direction, for_mark);
2621                 }
2622         }
2623 }
2624
2625 void
2626 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2627 {
2628         if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2629                 return;
2630         }
2631
2632         snap_to_internal (start, direction, for_mark, ensure_snap);
2633 }
2634
2635 void
2636 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2637 {
2638         const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2639         framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2640
2641         switch (_snap_type) {
2642         case SnapToTimecodeFrame:
2643                 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2644                     fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2645                         /* start is already on a whole timecode frame, do nothing */
2646                 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2647                         start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2648                 } else {
2649                         start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) *  _session->frames_per_timecode_frame());
2650                 }
2651                 break;
2652
2653         case SnapToTimecodeSeconds:
2654                 if (_session->config.get_timecode_offset_negative()) {
2655                         start += _session->config.get_timecode_offset ();
2656                 } else {
2657                         start -= _session->config.get_timecode_offset ();
2658                 }
2659                 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2660                     (start % one_timecode_second == 0)) {
2661                         /* start is already on a whole second, do nothing */
2662                 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2663                         start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2664                 } else {
2665                         start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2666                 }
2667
2668                 if (_session->config.get_timecode_offset_negative()) {
2669                         start -= _session->config.get_timecode_offset ();
2670                 } else {
2671                         start += _session->config.get_timecode_offset ();
2672                 }
2673                 break;
2674
2675         case SnapToTimecodeMinutes:
2676                 if (_session->config.get_timecode_offset_negative()) {
2677                         start += _session->config.get_timecode_offset ();
2678                 } else {
2679                         start -= _session->config.get_timecode_offset ();
2680                 }
2681                 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2682                     (start % one_timecode_minute == 0)) {
2683                         /* start is already on a whole minute, do nothing */
2684                 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2685                         start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2686                 } else {
2687                         start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2688                 }
2689                 if (_session->config.get_timecode_offset_negative()) {
2690                         start -= _session->config.get_timecode_offset ();
2691                 } else {
2692                         start += _session->config.get_timecode_offset ();
2693                 }
2694                 break;
2695         default:
2696                 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2697                 abort(); /*NOTREACHED*/
2698         }
2699 }
2700
2701 void
2702 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2703 {
2704         const framepos_t one_second = _session->frame_rate();
2705         const framepos_t one_minute = _session->frame_rate() * 60;
2706         framepos_t presnap = start;
2707         framepos_t before;
2708         framepos_t after;
2709
2710         switch (_snap_type) {
2711         case SnapToTimecodeFrame:
2712         case SnapToTimecodeSeconds:
2713         case SnapToTimecodeMinutes:
2714                 return timecode_snap_to_internal (start, direction, for_mark);
2715
2716         case SnapToCDFrame:
2717                 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2718                     start % (one_second/75) == 0) {
2719                         /* start is already on a whole CD frame, do nothing */
2720                 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2721                         start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2722                 } else {
2723                         start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2724                 }
2725                 break;
2726
2727         case SnapToSeconds:
2728                 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2729                     start % one_second == 0) {
2730                         /* start is already on a whole second, do nothing */
2731                 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2732                         start = (framepos_t) ceil ((double) start / one_second) * one_second;
2733                 } else {
2734                         start = (framepos_t) floor ((double) start / one_second) * one_second;
2735                 }
2736                 break;
2737
2738         case SnapToMinutes:
2739                 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2740                     start % one_minute == 0) {
2741                         /* start is already on a whole minute, do nothing */
2742                 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2743                         start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2744                 } else {
2745                         start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2746                 }
2747                 break;
2748
2749         case SnapToBar:
2750                 start = _session->tempo_map().round_to_bar (start, direction);
2751                 break;
2752
2753         case SnapToBeat:
2754                 start = _session->tempo_map().round_to_beat (start, direction);
2755                 break;
2756
2757         case SnapToBeatDiv128:
2758                 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2759                 break;
2760         case SnapToBeatDiv64:
2761                 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2762                 break;
2763         case SnapToBeatDiv32:
2764                 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2765                 break;
2766         case SnapToBeatDiv28:
2767                 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2768                 break;
2769         case SnapToBeatDiv24:
2770                 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2771                 break;
2772         case SnapToBeatDiv20:
2773                 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2774                 break;
2775         case SnapToBeatDiv16:
2776                 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2777                 break;
2778         case SnapToBeatDiv14:
2779                 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2780                 break;
2781         case SnapToBeatDiv12:
2782                 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2783                 break;
2784         case SnapToBeatDiv10:
2785                 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2786                 break;
2787         case SnapToBeatDiv8:
2788                 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2789                 break;
2790         case SnapToBeatDiv7:
2791                 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2792                 break;
2793         case SnapToBeatDiv6:
2794                 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2795                 break;
2796         case SnapToBeatDiv5:
2797                 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2798                 break;
2799         case SnapToBeatDiv4:
2800                 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2801                 break;
2802         case SnapToBeatDiv3:
2803                 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2804                 break;
2805         case SnapToBeatDiv2:
2806                 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2807                 break;
2808
2809         case SnapToMark:
2810                 if (for_mark) {
2811                         return;
2812                 }
2813
2814                 _session->locations()->marks_either_side (start, before, after);
2815
2816                 if (before == max_framepos && after == max_framepos) {
2817                         /* No marks to snap to, so just don't snap */
2818                         return;
2819                 } else if (before == max_framepos) {
2820                         start = after;
2821                 } else if (after == max_framepos) {
2822                         start = before;
2823                 } else if (before != max_framepos && after != max_framepos) {
2824                         /* have before and after */
2825                         if ((start - before) < (after - start)) {
2826                                 start = before;
2827                         } else {
2828                                 start = after;
2829                         }
2830                 }
2831
2832                 break;
2833
2834         case SnapToRegionStart:
2835         case SnapToRegionEnd:
2836         case SnapToRegionSync:
2837         case SnapToRegionBoundary:
2838                 if (!region_boundary_cache.empty()) {
2839
2840                         vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2841                         vector<framepos_t>::iterator next = region_boundary_cache.end ();
2842
2843                         if (direction > 0) {
2844                                 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2845                         } else {
2846                                 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2847                         }
2848
2849                         if (next != region_boundary_cache.begin ()) {
2850                                 prev = next;
2851                                 prev--;
2852                         }
2853
2854                         framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2855                         framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2856
2857                         if (start > (p + n) / 2) {
2858                                 start = n;
2859                         } else {
2860                                 start = p;
2861                         }
2862                 }
2863                 break;
2864         }
2865
2866         switch (_snap_mode) {
2867         case SnapNormal:
2868                 return;
2869
2870         case SnapMagnetic:
2871
2872                 if (ensure_snap) {
2873                         return;
2874                 }
2875
2876                 if (presnap > start) {
2877                         if (presnap > (start + pixel_to_sample(snap_threshold))) {
2878                                 start = presnap;
2879                         }
2880
2881                 } else if (presnap < start) {
2882                         if (presnap < (start - pixel_to_sample(snap_threshold))) {
2883                                 start = presnap;
2884                         }
2885                 }
2886
2887         default:
2888                 /* handled at entry */
2889                 return;
2890
2891         }
2892 }
2893
2894
2895 void
2896 Editor::setup_toolbar ()
2897 {
2898         HBox* mode_box = manage(new HBox);
2899         mode_box->set_border_width (2);
2900         mode_box->set_spacing(2);
2901
2902         HBox* mouse_mode_box = manage (new HBox);
2903         HBox* mouse_mode_hbox = manage (new HBox);
2904         VBox* mouse_mode_vbox = manage (new VBox);
2905         Alignment* mouse_mode_align = manage (new Alignment);
2906
2907         Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2908         mouse_mode_size_group->add_widget (smart_mode_button);
2909         mouse_mode_size_group->add_widget (mouse_move_button);
2910         mouse_mode_size_group->add_widget (mouse_cut_button);
2911         mouse_mode_size_group->add_widget (mouse_select_button);
2912         mouse_mode_size_group->add_widget (mouse_timefx_button);
2913         mouse_mode_size_group->add_widget (mouse_audition_button);
2914         mouse_mode_size_group->add_widget (mouse_draw_button);
2915         mouse_mode_size_group->add_widget (mouse_content_button);
2916
2917         mouse_mode_size_group->add_widget (zoom_in_button);
2918         mouse_mode_size_group->add_widget (zoom_out_button);
2919         mouse_mode_size_group->add_widget (zoom_preset_selector);
2920         mouse_mode_size_group->add_widget (zoom_out_full_button);
2921         mouse_mode_size_group->add_widget (zoom_focus_selector);
2922
2923         mouse_mode_size_group->add_widget (tav_shrink_button);
2924         mouse_mode_size_group->add_widget (tav_expand_button);
2925         mouse_mode_size_group->add_widget (visible_tracks_selector);
2926
2927         mouse_mode_size_group->add_widget (snap_type_selector);
2928         mouse_mode_size_group->add_widget (snap_mode_selector);
2929
2930         mouse_mode_size_group->add_widget (edit_point_selector);
2931         mouse_mode_size_group->add_widget (edit_mode_selector);
2932
2933         mouse_mode_size_group->add_widget (*nudge_clock);
2934         mouse_mode_size_group->add_widget (nudge_forward_button);
2935         mouse_mode_size_group->add_widget (nudge_backward_button);
2936
2937         mouse_mode_hbox->set_spacing (2);
2938
2939         if (!ARDOUR::Profile->get_trx()) {
2940                 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2941         }
2942
2943         mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2944         mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2945
2946         if (!ARDOUR::Profile->get_mixbus()) {
2947                 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2948         }
2949         
2950         if (!ARDOUR::Profile->get_trx()) {
2951                 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2952                 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2953                 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2954                 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2955         }
2956
2957         mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2958
2959         mouse_mode_align->add (*mouse_mode_vbox);
2960         mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2961
2962         mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2963
2964         edit_mode_selector.set_name ("mouse mode button");
2965
2966         if (!ARDOUR::Profile->get_trx()) {
2967                 mode_box->pack_start (edit_mode_selector, false, false);
2968         }
2969         mode_box->pack_start (*mouse_mode_box, false, false);
2970
2971         _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2972         _mouse_mode_tearoff->set_name ("MouseModeBase");
2973         _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2974
2975         if (Profile->get_sae() || Profile->get_mixbus() ) {
2976                 _mouse_mode_tearoff->set_can_be_torn_off (false);
2977         }
2978
2979         _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2980                                                          &_mouse_mode_tearoff->tearoff_window()));
2981         _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2982                                                          &_mouse_mode_tearoff->tearoff_window(), 1));
2983         _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2984                                                          &_mouse_mode_tearoff->tearoff_window()));
2985         _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2986                                                           &_mouse_mode_tearoff->tearoff_window(), 1));
2987
2988         /* Zoom */
2989
2990         _zoom_box.set_spacing (2);
2991         _zoom_box.set_border_width (2);
2992
2993         RefPtr<Action> act;
2994
2995         zoom_preset_selector.set_name ("zoom button");
2996         zoom_preset_selector.set_image(::get_icon ("time_exp"));
2997         zoom_preset_selector.set_size_request (42, -1);
2998
2999         zoom_in_button.set_name ("zoom button");
3000         zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3001         act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3002         zoom_in_button.set_related_action (act);
3003
3004         zoom_out_button.set_name ("zoom button");
3005         zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3006         act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3007         zoom_out_button.set_related_action (act);
3008
3009         zoom_out_full_button.set_name ("zoom button");
3010         zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3011         act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3012         zoom_out_full_button.set_related_action (act);
3013
3014         zoom_focus_selector.set_name ("zoom button");
3015
3016         if (ARDOUR::Profile->get_mixbus()) {
3017                 _zoom_box.pack_start (zoom_preset_selector, false, false);
3018         } else if (ARDOUR::Profile->get_trx()) {
3019                 mode_box->pack_start (zoom_out_button, false, false);
3020                 mode_box->pack_start (zoom_in_button, false, false);
3021         } else {
3022                 _zoom_box.pack_start (zoom_out_button, false, false);
3023                 _zoom_box.pack_start (zoom_in_button, false, false);
3024                 _zoom_box.pack_start (zoom_out_full_button, false, false);
3025                 _zoom_box.pack_start (zoom_focus_selector, false, false);
3026         }
3027
3028         /* Track zoom buttons */
3029         visible_tracks_selector.set_name ("zoom button");
3030         if (Profile->get_mixbus()) {
3031                 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3032                 visible_tracks_selector.set_size_request (42, -1);
3033         } else {
3034                 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3035         }
3036
3037         tav_expand_button.set_name ("zoom button");
3038         tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3039         act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3040         tav_expand_button.set_related_action (act);
3041
3042         tav_shrink_button.set_name ("zoom button");
3043         tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3044         act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3045         tav_shrink_button.set_related_action (act);
3046
3047         if (ARDOUR::Profile->get_mixbus()) {
3048                 _zoom_box.pack_start (visible_tracks_selector);
3049         } else if (ARDOUR::Profile->get_trx()) {
3050                 _zoom_box.pack_start (tav_shrink_button);
3051                 _zoom_box.pack_start (tav_expand_button);
3052         } else {
3053                 _zoom_box.pack_start (visible_tracks_selector);
3054                 _zoom_box.pack_start (tav_shrink_button);
3055                 _zoom_box.pack_start (tav_expand_button);
3056         }
3057
3058         if (!ARDOUR::Profile->get_trx()) {
3059                 _zoom_tearoff = manage (new TearOff (_zoom_box));
3060                 
3061                 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3062                                                            &_zoom_tearoff->tearoff_window()));
3063                 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3064                                                            &_zoom_tearoff->tearoff_window(), 0));
3065                 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3066                                                            &_zoom_tearoff->tearoff_window()));
3067                 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3068                                                             &_zoom_tearoff->tearoff_window(), 0));
3069         } 
3070
3071         if (Profile->get_sae() || Profile->get_mixbus() ) {
3072                 _zoom_tearoff->set_can_be_torn_off (false);
3073         }
3074
3075         snap_box.set_spacing (2);
3076         snap_box.set_border_width (2);
3077
3078         snap_type_selector.set_name ("mouse mode button");
3079
3080         snap_mode_selector.set_name ("mouse mode button");
3081
3082         edit_point_selector.set_name ("mouse mode button");
3083
3084         snap_box.pack_start (snap_mode_selector, false, false);
3085         snap_box.pack_start (snap_type_selector, false, false);
3086         snap_box.pack_start (edit_point_selector, false, false);
3087
3088         /* Nudge */
3089
3090         HBox *nudge_box = manage (new HBox);
3091         nudge_box->set_spacing (2);
3092         nudge_box->set_border_width (2);
3093
3094         nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3095         nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3096
3097         nudge_box->pack_start (nudge_backward_button, false, false);
3098         nudge_box->pack_start (nudge_forward_button, false, false);
3099         nudge_box->pack_start (*nudge_clock, false, false);
3100
3101
3102         /* Pack everything in... */
3103
3104         HBox* hbox = manage (new HBox);
3105         hbox->set_spacing(2);
3106
3107         _tools_tearoff = manage (new TearOff (*hbox));
3108         _tools_tearoff->set_name ("MouseModeBase");
3109         _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3110
3111         if (Profile->get_sae() || Profile->get_mixbus()) {
3112                 _tools_tearoff->set_can_be_torn_off (false);
3113         }
3114
3115         _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3116                                                     &_tools_tearoff->tearoff_window()));
3117         _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3118                                                     &_tools_tearoff->tearoff_window(), 0));
3119         _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3120                                                     &_tools_tearoff->tearoff_window()));
3121         _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3122                                                      &_tools_tearoff->tearoff_window(), 0));
3123
3124         toolbar_hbox.set_spacing (2);
3125         toolbar_hbox.set_border_width (1);
3126
3127         toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3128         if (!ARDOUR::Profile->get_trx()) {
3129                 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3130                 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3131         }
3132
3133         if (!ARDOUR::Profile->get_trx()) {
3134                 hbox->pack_start (snap_box, false, false);
3135                 hbox->pack_start (*nudge_box, false, false);
3136         }
3137         hbox->pack_start (panic_box, false, false);
3138
3139         hbox->show_all ();
3140
3141         toolbar_base.set_name ("ToolBarBase");
3142         toolbar_base.add (toolbar_hbox);
3143
3144         _toolbar_viewport.add (toolbar_base);
3145         /* stick to the required height but allow width to vary if there's not enough room */
3146         _toolbar_viewport.set_size_request (1, -1);
3147
3148         toolbar_frame.set_shadow_type (SHADOW_OUT);
3149         toolbar_frame.set_name ("BaseFrame");
3150         toolbar_frame.add (_toolbar_viewport);
3151 }
3152
3153 void
3154 Editor::build_edit_point_menu ()
3155 {
3156         using namespace Menu_Helpers;
3157
3158         edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3159         if(!Profile->get_mixbus())
3160                 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3161         edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3162
3163         set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3164 }
3165
3166 void
3167 Editor::build_edit_mode_menu ()
3168 {
3169         using namespace Menu_Helpers;
3170         
3171         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3172 //      edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3173         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3174         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
3175
3176         set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3177 }
3178
3179 void
3180 Editor::build_snap_mode_menu ()
3181 {
3182         using namespace Menu_Helpers;
3183
3184         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3185         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3186         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3187
3188         set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3189 }
3190
3191 void
3192 Editor::build_snap_type_menu ()
3193 {
3194         using namespace Menu_Helpers;
3195
3196         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3197         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3198         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3199         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3200         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3201         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3202         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3203         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3204         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3205         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3206         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3207         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3208         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3209         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3210         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3211         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3212         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3213         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3214         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3215         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3216         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3217         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3218         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3219         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3220         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3221         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3222         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3223         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3224         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3225         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3226
3227         set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3228
3229 }
3230
3231 void
3232 Editor::setup_tooltips ()
3233 {
3234         ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Grab mode)"));
3235         ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Grab Mode (select/move objects)"));
3236         ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split regions)"));
3237         ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select time ranges)"));
3238         ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3239         ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3240         ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3241         ARDOUR_UI::instance()->set_tip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3242         ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3243         ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3244         ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3245         ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3246         ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3247         ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3248         ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3249         ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3250         ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3251         ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3252         ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3253         ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3254         ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3255         ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3256         ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3257         ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3258 }
3259
3260 int
3261 Editor::convert_drop_to_paths (
3262                 vector<string>&                paths,
3263                 const RefPtr<Gdk::DragContext>& /*context*/,
3264                 gint                            /*x*/,
3265                 gint                            /*y*/,
3266                 const SelectionData&            data,
3267                 guint                           /*info*/,
3268                 guint                           /*time*/)
3269 {
3270         if (_session == 0) {
3271                 return -1;
3272         }
3273
3274         vector<string> uris = data.get_uris();
3275
3276         if (uris.empty()) {
3277
3278                 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3279                    are actually URI lists. So do it by hand.
3280                 */
3281
3282                 if (data.get_target() != "text/plain") {
3283                         return -1;
3284                 }
3285
3286                 /* Parse the "uri-list" format that Nautilus provides,
3287                    where each pathname is delimited by \r\n.
3288
3289                    THERE MAY BE NO NULL TERMINATING CHAR!!!
3290                 */
3291
3292                 string txt = data.get_text();
3293                 char* p;
3294                 const char* q;
3295
3296                 p = (char *) malloc (txt.length() + 1);
3297                 txt.copy (p, txt.length(), 0);
3298                 p[txt.length()] = '\0';
3299
3300                 while (p)
3301                 {
3302                         if (*p != '#')
3303                         {
3304                                 while (g_ascii_isspace (*p))
3305                                         p++;
3306
3307                                 q = p;
3308                                 while (*q && (*q != '\n') && (*q != '\r')) {
3309                                         q++;
3310                                 }
3311
3312                                 if (q > p)
3313                                 {
3314                                         q--;
3315                                         while (q > p && g_ascii_isspace (*q))
3316                                                 q--;
3317
3318                                         if (q > p)
3319                                         {
3320                                                 uris.push_back (string (p, q - p + 1));
3321                                         }
3322                                 }
3323                         }
3324                         p = strchr (p, '\n');
3325                         if (p)
3326                                 p++;
3327                 }
3328
3329                 free ((void*)p);
3330
3331                 if (uris.empty()) {
3332                         return -1;
3333                 }
3334         }
3335
3336         for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3337                 if ((*i).substr (0,7) == "file://") {
3338                         paths.push_back (Glib::filename_from_uri (*i));
3339                 }
3340         }
3341
3342         return 0;
3343 }
3344
3345 void
3346 Editor::new_tempo_section ()
3347 {
3348 }
3349
3350 void
3351 Editor::map_transport_state ()
3352 {
3353         ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3354
3355         if (_session && _session->transport_stopped()) {
3356                 have_pending_keyboard_selection = false;
3357         }
3358
3359         update_loop_range_view ();
3360 }
3361
3362 /* UNDO/REDO */
3363
3364 void
3365 Editor::begin_selection_op_history ()
3366 {
3367         selection_op_cmd_depth = 0;
3368         selection_op_history_it = 0;
3369
3370         while(!selection_op_history.empty()) {
3371                 delete selection_op_history.front();
3372                 selection_op_history.pop_front();
3373         }
3374
3375         selection_undo_action->set_sensitive (false);
3376         selection_redo_action->set_sensitive (false);
3377         selection_op_history.push_front (&_selection_memento->get_state ());
3378 }
3379
3380 void
3381 Editor::begin_reversible_selection_op (string name)
3382 {
3383         if (_session) {
3384                 //cerr << name << endl;
3385                 /* begin/commit pairs can be nested */
3386                 selection_op_cmd_depth++;
3387         }
3388 }
3389
3390 void
3391 Editor::commit_reversible_selection_op ()
3392 {
3393         if (_session) {
3394                 if (selection_op_cmd_depth == 1) {
3395
3396                         if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3397                                 /**
3398                                     The user has undone some selection ops and then made a new one,
3399                                     making anything earlier in the list invalid.
3400                                 */
3401                                 
3402                                 list<XMLNode *>::iterator it = selection_op_history.begin();
3403                                 list<XMLNode *>::iterator e_it = it;
3404                                 advance (e_it, selection_op_history_it);
3405                                 
3406                                 for ( ; it != e_it; ++it) {
3407                                         delete *it;
3408                                 }
3409                                 selection_op_history.erase (selection_op_history.begin(), e_it);
3410                         }
3411
3412                         selection_op_history.push_front (&_selection_memento->get_state ());
3413                         selection_op_history_it = 0;
3414
3415                         selection_undo_action->set_sensitive (true);
3416                         selection_redo_action->set_sensitive (false);
3417                 }
3418
3419                 if (selection_op_cmd_depth > 0) {
3420                         selection_op_cmd_depth--;
3421                 }
3422         }
3423 }
3424
3425 void
3426 Editor::undo_selection_op ()
3427 {
3428         if (_session) {
3429                 selection_op_history_it++;
3430                 uint32_t n = 0;
3431                 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3432                         if (n == selection_op_history_it) {
3433                                 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3434                                 selection_redo_action->set_sensitive (true);
3435                         }
3436                         ++n;
3437                 }
3438                 /* is there an earlier entry? */
3439                 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3440                         selection_undo_action->set_sensitive (false);
3441                 }
3442         }
3443 }
3444
3445 void
3446 Editor::redo_selection_op ()
3447 {
3448         if (_session) {
3449                 if (selection_op_history_it > 0) {
3450                         selection_op_history_it--;
3451                 }
3452                 uint32_t n = 0;
3453                 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3454                         if (n == selection_op_history_it) {
3455                                 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3456                                 selection_undo_action->set_sensitive (true);
3457                         }
3458                         ++n;
3459                 }
3460
3461                 if (selection_op_history_it == 0) {
3462                         selection_redo_action->set_sensitive (false);
3463                 }
3464         }
3465 }
3466
3467 void
3468 Editor::begin_reversible_command (string name)
3469 {
3470         if (_session) {
3471                 before.push_back (&_selection_memento->get_state ());
3472                 _session->begin_reversible_command (name);
3473         }
3474 }
3475
3476 void
3477 Editor::begin_reversible_command (GQuark q)
3478 {
3479         if (_session) {
3480                 before.push_back (&_selection_memento->get_state ());
3481                 _session->begin_reversible_command (q);
3482         }
3483 }
3484
3485 void
3486 Editor::abort_reversible_command ()
3487 {
3488         if (_session) {
3489                 while(!before.empty()) {
3490                         delete before.front();
3491                         before.pop_front();
3492                 }
3493                 _session->abort_reversible_command ();
3494         }
3495 }
3496
3497 void
3498 Editor::commit_reversible_command ()
3499 {
3500         if (_session) {
3501                 if (before.size() == 1) {
3502                         _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3503                         redo_action->set_sensitive(false);
3504                         undo_action->set_sensitive(true);
3505                         begin_selection_op_history ();
3506                 }
3507
3508                 if (before.empty()) {
3509                         cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3510                 } else {
3511                         before.pop_back();
3512                 }
3513
3514                 _session->commit_reversible_command ();
3515         }
3516 }
3517
3518 void
3519 Editor::history_changed ()
3520 {
3521         string label;
3522
3523         if (undo_action && _session) {
3524                 if (_session->undo_depth() == 0) {
3525                         label = S_("Command|Undo");
3526                 } else {
3527                         label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3528                 }
3529                 undo_action->property_label() = label;
3530         }
3531
3532         if (redo_action && _session) {
3533                 if (_session->redo_depth() == 0) {
3534                         label = _("Redo");
3535                 } else {
3536                         label = string_compose(_("Redo (%1)"), _session->next_redo());
3537                 }
3538                 redo_action->property_label() = label;
3539         }
3540 }
3541
3542 void
3543 Editor::duplicate_range (bool with_dialog)
3544 {
3545         float times = 1.0f;
3546
3547         RegionSelection rs = get_regions_from_selection_and_entered ();
3548
3549         if ( selection->time.length() == 0 && rs.empty()) {
3550                 return;
3551         }
3552
3553         if (with_dialog) {
3554
3555                 ArdourDialog win (_("Duplicate"));
3556                 Label label (_("Number of duplications:"));
3557                 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3558                 SpinButton spinner (adjustment, 0.0, 1);
3559                 HBox hbox;
3560
3561                 win.get_vbox()->set_spacing (12);
3562                 win.get_vbox()->pack_start (hbox);
3563                 hbox.set_border_width (6);
3564                 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3565
3566                 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3567                    place, visually. so do this by hand.
3568                 */
3569
3570                 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3571                 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3572                 spinner.grab_focus();
3573
3574                 hbox.show ();
3575                 label.show ();
3576                 spinner.show ();
3577
3578                 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3579                 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3580                 win.set_default_response (RESPONSE_ACCEPT);
3581
3582                 spinner.grab_focus ();
3583
3584                 switch (win.run ()) {
3585                 case RESPONSE_ACCEPT:
3586                         break;
3587                 default:
3588                         return;
3589                 }
3590
3591                 times = adjustment.get_value();
3592         }
3593
3594         if ((current_mouse_mode() == Editing::MouseRange)) {
3595                 if (selection->time.length()) {
3596                         duplicate_selection (times);
3597                 }
3598         } else if (get_smart_mode()) {
3599                 if (selection->time.length()) {
3600                         duplicate_selection (times);
3601                 } else 
3602                         duplicate_some_regions (rs, times);
3603         } else {
3604                 duplicate_some_regions (rs, times);
3605         }
3606 }
3607
3608 void
3609 Editor::set_edit_mode (EditMode m)
3610 {
3611         Config->set_edit_mode (m);
3612 }
3613
3614 void
3615 Editor::cycle_edit_mode ()
3616 {
3617         switch (Config->get_edit_mode()) {
3618         case Slide:
3619                 if (Profile->get_sae()) {
3620                         Config->set_edit_mode (Lock);
3621                 } else {
3622                         Config->set_edit_mode (Ripple);
3623                 }
3624                 break;
3625         case Splice:
3626         case Ripple:
3627                 Config->set_edit_mode (Lock);
3628                 break;
3629         case Lock:
3630                 Config->set_edit_mode (Slide);
3631                 break;
3632         }
3633 }
3634
3635 void
3636 Editor::edit_mode_selection_done ( EditMode m )
3637 {
3638         Config->set_edit_mode ( m );
3639 }
3640
3641 void
3642 Editor::snap_type_selection_done (SnapType snaptype)
3643 {
3644         RefPtr<RadioAction> ract = snap_type_action (snaptype);
3645         if (ract) {
3646                 ract->set_active ();
3647         }
3648 }
3649
3650 void
3651 Editor::snap_mode_selection_done (SnapMode mode)
3652 {
3653         RefPtr<RadioAction> ract = snap_mode_action (mode);
3654
3655         if (ract) {
3656                 ract->set_active (true);
3657         }
3658 }
3659
3660 void
3661 Editor::cycle_edit_point (bool with_marker)
3662 {
3663         if(Profile->get_mixbus())
3664                 with_marker = false;
3665
3666         switch (_edit_point) {
3667         case EditAtMouse:
3668                 set_edit_point_preference (EditAtPlayhead);
3669                 break;
3670         case EditAtPlayhead:
3671                 if (with_marker) {
3672                         set_edit_point_preference (EditAtSelectedMarker);
3673                 } else {
3674                         set_edit_point_preference (EditAtMouse);
3675                 }
3676                 break;
3677         case EditAtSelectedMarker:
3678                 set_edit_point_preference (EditAtMouse);
3679                 break;
3680         }
3681 }
3682
3683 void
3684 Editor::edit_point_selection_done (EditPoint ep)
3685 {
3686         set_edit_point_preference ( ep );
3687 }
3688
3689 void
3690 Editor::build_zoom_focus_menu ()
3691 {
3692         using namespace Menu_Helpers;
3693
3694         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3695         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3696         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3697         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3698         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3699         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3700
3701         set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3702 }
3703
3704 void
3705 Editor::zoom_focus_selection_done ( ZoomFocus f )
3706 {
3707         RefPtr<RadioAction> ract = zoom_focus_action (f);
3708         if (ract) {
3709                 ract->set_active ();
3710         }
3711 }
3712
3713 void
3714 Editor::build_track_count_menu ()
3715 {
3716         using namespace Menu_Helpers;
3717
3718         if (!Profile->get_mixbus()) {
3719                 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3720                 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3721                 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3722                 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3723                 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3724                 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3725                 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3726                 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3727                 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3728                 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3729                 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3730                 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3731                 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3732         } else {
3733                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3734                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3735                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3736                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3737                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3738                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3739                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3740                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3741                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3742                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3743
3744                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3745                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3746                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3747                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3748                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3749                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3750                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3751                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3752                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3753                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3754                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3755         }
3756 }
3757
3758 void
3759 Editor::set_zoom_preset (int64_t ms)
3760 {
3761         if ( ms <= 0 ) {
3762                 temporal_zoom_session();
3763                 return;
3764         }
3765         
3766         ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3767         temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3768 }
3769
3770 void
3771 Editor::set_visible_track_count (int32_t n)
3772 {
3773         _visible_track_count = n;
3774
3775         /* if the canvas hasn't really been allocated any size yet, just
3776            record the desired number of visible tracks and return. when canvas
3777            allocation happens, we will get called again and then we can do the
3778            real work.
3779         */
3780         
3781         if (_visible_canvas_height <= 1) {
3782                 return;
3783         }
3784
3785         int h;
3786         string str;
3787         DisplaySuspender ds;
3788         
3789         if (_visible_track_count > 0) {
3790                 h = trackviews_height() / _visible_track_count;
3791                 std::ostringstream s;
3792                 s << _visible_track_count;
3793                 str = s.str();
3794         } else if (_visible_track_count == 0) {
3795                 uint32_t n = 0;
3796                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3797                         if ((*i)->marked_for_display()) {
3798                                 ++n;
3799                         }
3800                 }
3801                 h = trackviews_height() / n;
3802                 str = _("All");
3803         } else {
3804                 /* negative value means that the visible track count has 
3805                    been overridden by explicit track height changes.
3806                 */
3807                 visible_tracks_selector.set_text (X_("*"));
3808                 return;
3809         }
3810
3811         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3812                 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3813         }
3814         
3815         if (str != visible_tracks_selector.get_text()) {
3816                 visible_tracks_selector.set_text (str);
3817         }
3818 }
3819
3820 void
3821 Editor::override_visible_track_count ()
3822 {
3823         _visible_track_count = -1;
3824         visible_tracks_selector.set_text ( _("*") );
3825 }
3826
3827 bool
3828 Editor::edit_controls_button_release (GdkEventButton* ev)
3829 {
3830         if (Keyboard::is_context_menu_event (ev)) {
3831                 ARDOUR_UI::instance()->add_route (this);
3832         } else if (ev->button == 1) {
3833                 selection->clear_tracks ();
3834         }
3835
3836         return true;
3837 }
3838
3839 bool
3840 Editor::mouse_select_button_release (GdkEventButton* ev)
3841 {
3842         /* this handles just right-clicks */
3843
3844         if (ev->button != 3) {
3845                 return false;
3846         }
3847
3848         return true;
3849 }
3850
3851 void
3852 Editor::set_zoom_focus (ZoomFocus f)
3853 {
3854         string str = zoom_focus_strings[(int)f];
3855
3856         if (str != zoom_focus_selector.get_text()) {
3857                 zoom_focus_selector.set_text (str);
3858         }
3859
3860         if (zoom_focus != f) {
3861                 zoom_focus = f;
3862                 instant_save ();
3863         }
3864 }
3865
3866 void
3867 Editor::cycle_zoom_focus ()
3868 {
3869         switch (zoom_focus) {
3870         case ZoomFocusLeft:
3871                 set_zoom_focus (ZoomFocusRight);
3872                 break;
3873         case ZoomFocusRight:
3874                 set_zoom_focus (ZoomFocusCenter);
3875                 break;
3876         case ZoomFocusCenter:
3877                 set_zoom_focus (ZoomFocusPlayhead);
3878                 break;
3879         case ZoomFocusPlayhead:
3880                 set_zoom_focus (ZoomFocusMouse);
3881                 break;
3882         case ZoomFocusMouse:
3883                 set_zoom_focus (ZoomFocusEdit);
3884                 break;
3885         case ZoomFocusEdit:
3886                 set_zoom_focus (ZoomFocusLeft);
3887                 break;
3888         }
3889 }
3890
3891 void
3892 Editor::ensure_float (Window& win)
3893 {
3894         win.set_transient_for (*this);
3895 }
3896
3897 void
3898 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3899 {
3900         /* recover or initialize pane positions. do this here rather than earlier because
3901            we don't want the positions to change the child allocations, which they seem to do.
3902          */
3903
3904         int pos;
3905         XMLProperty* prop;
3906         char buf[32];
3907         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3908
3909         enum Pane {
3910                 Horizontal = 0x1,
3911                 Vertical = 0x2
3912         };
3913
3914         static Pane done;
3915
3916         XMLNode* geometry = find_named_node (*node, "geometry");
3917
3918         if (which == static_cast<Paned*> (&edit_pane)) {
3919
3920                 if (done & Horizontal) {
3921                         return;
3922                 }
3923
3924                 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3925                         _notebook_shrunk = string_is_affirmative (prop->value ());
3926                 }
3927
3928                 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3929                         /* initial allocation is 90% to canvas, 10% to notebook */
3930                         pos = (int) floor (alloc.get_width() * 0.90f);
3931                         snprintf (buf, sizeof(buf), "%d", pos);
3932                 } else {
3933                         pos = atoi (prop->value());
3934                 }
3935
3936                 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3937                         edit_pane.set_position (pos);
3938                 }
3939
3940                 done = (Pane) (done | Horizontal);
3941
3942         } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3943
3944                 if (done & Vertical) {
3945                         return;
3946                 }
3947
3948                 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3949                         /* initial allocation is 90% to canvas, 10% to summary */
3950                         pos = (int) floor (alloc.get_height() * 0.90f);
3951                         snprintf (buf, sizeof(buf), "%d", pos);
3952                 } else {
3953
3954                         pos = atoi (prop->value());
3955                 }
3956
3957                 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3958                         editor_summary_pane.set_position (pos);
3959                 }
3960
3961                 done = (Pane) (done | Vertical);
3962         }
3963 }
3964
3965 void
3966 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3967 {
3968         if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) && 
3969             (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) && 
3970             (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3971                 top_hbox.remove (toolbar_frame);
3972         }
3973 }
3974
3975 void
3976 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3977 {
3978         if (toolbar_frame.get_parent() == 0) {
3979                 top_hbox.pack_end (toolbar_frame);
3980         }
3981 }
3982
3983 void
3984 Editor::set_show_measures (bool yn)
3985 {
3986         if (_show_measures != yn) {
3987                 hide_measures ();
3988
3989                 if ((_show_measures = yn) == true) {
3990                         if (tempo_lines) {
3991                                 tempo_lines->show();
3992                         }
3993
3994                         ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3995                         ARDOUR::TempoMap::BBTPointList::const_iterator end;
3996                         
3997                         compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3998                         draw_measures (begin, end);
3999                 } 
4000
4001                 instant_save ();
4002         }
4003 }
4004
4005 void
4006 Editor::toggle_follow_playhead ()
4007 {
4008         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
4009         if (act) {
4010                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
4011                 set_follow_playhead (tact->get_active());
4012         }
4013 }
4014
4015 /** @param yn true to follow playhead, otherwise false.
4016  *  @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
4017  */
4018 void
4019 Editor::set_follow_playhead (bool yn, bool catch_up)
4020 {
4021         if (_follow_playhead != yn) {
4022                 if ((_follow_playhead = yn) == true && catch_up) {
4023                         /* catch up */
4024                         reset_x_origin_to_follow_playhead ();
4025                 }
4026                 instant_save ();
4027         }
4028 }
4029
4030 void
4031 Editor::toggle_stationary_playhead ()
4032 {
4033         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
4034         if (act) {
4035                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
4036                 set_stationary_playhead (tact->get_active());
4037         }
4038 }
4039
4040 void
4041 Editor::set_stationary_playhead (bool yn)
4042 {
4043         if (_stationary_playhead != yn) {
4044                 if ((_stationary_playhead = yn) == true) {
4045                         /* catch up */
4046                         // FIXME need a 3.0 equivalent of this 2.X call
4047                         // update_current_screen ();
4048                 }
4049                 instant_save ();
4050         }
4051 }
4052
4053 PlaylistSelector&
4054 Editor::playlist_selector () const
4055 {
4056         return *_playlist_selector;
4057 }
4058
4059 framecnt_t
4060 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4061 {
4062         if (paste_count == 0) {
4063                 /* don't bother calculating an offset that will be zero anyway */
4064                 return 0;
4065         }
4066
4067         /* calculate basic unsnapped multi-paste offset */
4068         framecnt_t offset = paste_count * duration;
4069
4070         /* snap offset so pos + offset is aligned to the grid */
4071         framepos_t offset_pos = pos + offset;
4072         snap_to(offset_pos, RoundUpMaybe);
4073         offset = offset_pos - pos;
4074
4075         return offset;
4076 }
4077
4078 unsigned
4079 Editor::get_grid_beat_divisions(framepos_t position)
4080 {
4081         switch (_snap_type) {
4082         case SnapToBeatDiv128: return 128;
4083         case SnapToBeatDiv64:  return 64;
4084         case SnapToBeatDiv32:  return 32;
4085         case SnapToBeatDiv28:  return 28;
4086         case SnapToBeatDiv24:  return 24;
4087         case SnapToBeatDiv20:  return 20;
4088         case SnapToBeatDiv16:  return 16;
4089         case SnapToBeatDiv14:  return 14;
4090         case SnapToBeatDiv12:  return 12;
4091         case SnapToBeatDiv10:  return 10;
4092         case SnapToBeatDiv8:   return 8;
4093         case SnapToBeatDiv7:   return 7;
4094         case SnapToBeatDiv6:   return 6;
4095         case SnapToBeatDiv5:   return 5;
4096         case SnapToBeatDiv4:   return 4;
4097         case SnapToBeatDiv3:   return 3;
4098         case SnapToBeatDiv2:   return 2;
4099         default:               return 0;
4100         }
4101         return 0;
4102 }
4103
4104 Evoral::Beats
4105 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4106 {
4107         success = true;
4108
4109         const unsigned divisions = get_grid_beat_divisions(position);
4110         if (divisions) {
4111                 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4112         }
4113
4114         switch (_snap_type) {
4115         case SnapToBeat:
4116                 return Evoral::Beats(1.0);
4117         case SnapToBar:
4118                 if (_session) {
4119                         return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4120                 }
4121                 break;
4122         default:
4123                 success = false;
4124                 break;
4125         }
4126
4127         return Evoral::Beats();
4128 }
4129
4130 framecnt_t
4131 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4132 {
4133         framecnt_t ret;
4134
4135         ret = nudge_clock->current_duration (pos);
4136         next = ret + 1; /* XXXX fix me */
4137
4138         return ret;
4139 }
4140
4141 int
4142 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4143 {
4144         ArdourDialog dialog (_("Playlist Deletion"));
4145         Label  label (string_compose (_("Playlist %1 is currently unused.\n"
4146                                         "If it is kept, its audio files will not be cleaned.\n"
4147                                         "If it is deleted, audio files used by it alone will be cleaned."),
4148                                       pl->name()));
4149
4150         dialog.set_position (WIN_POS_CENTER);
4151         dialog.get_vbox()->pack_start (label);
4152
4153         label.show ();
4154
4155         dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4156         dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4157         dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4158
4159         switch (dialog.run ()) {
4160         case RESPONSE_ACCEPT:
4161                 /* delete the playlist */
4162                 return 0;
4163                 break;
4164
4165         case RESPONSE_REJECT:
4166                 /* keep the playlist */
4167                 return 1;
4168                 break;
4169
4170         default:
4171                 break;
4172         }
4173
4174         return -1;
4175 }
4176
4177 bool
4178 Editor::audio_region_selection_covers (framepos_t where)
4179 {
4180         for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4181                 if ((*a)->region()->covers (where)) {
4182                         return true;
4183                 }
4184         }
4185
4186         return false;
4187 }
4188
4189 void
4190 Editor::prepare_for_cleanup ()
4191 {
4192         cut_buffer->clear_regions ();
4193         cut_buffer->clear_playlists ();
4194
4195         selection->clear_regions ();
4196         selection->clear_playlists ();
4197
4198         _regions->suspend_redisplay ();
4199 }
4200
4201 void
4202 Editor::finish_cleanup ()
4203 {
4204         _regions->resume_redisplay ();
4205 }
4206
4207 Location*
4208 Editor::transport_loop_location()
4209 {
4210         if (_session) {
4211                 return _session->locations()->auto_loop_location();
4212         } else {
4213                 return 0;
4214         }
4215 }
4216
4217 Location*
4218 Editor::transport_punch_location()
4219 {
4220         if (_session) {
4221                 return _session->locations()->auto_punch_location();
4222         } else {
4223                 return 0;
4224         }
4225 }
4226
4227 bool
4228 Editor::control_layout_scroll (GdkEventScroll* ev)
4229 {
4230         /* Just forward to the normal canvas scroll method. The coordinate
4231            systems are different but since the canvas is always larger than the
4232            track headers, and aligned with the trackview area, this will work.
4233
4234            In the not too distant future this layout is going away anyway and
4235            headers will be on the canvas.
4236         */
4237         return canvas_scroll_event (ev, false);
4238 }
4239
4240 void
4241 Editor::session_state_saved (string)
4242 {
4243         update_title ();
4244         _snapshots->redisplay ();
4245 }
4246
4247 void
4248 Editor::update_tearoff_visibility()
4249 {
4250         bool visible = ARDOUR_UI::config()->get_keep_tearoffs();
4251         _mouse_mode_tearoff->set_visible (visible);
4252         _tools_tearoff->set_visible (visible);
4253         if (_zoom_tearoff) {
4254                 _zoom_tearoff->set_visible (visible);
4255         }
4256 }
4257
4258 void
4259 Editor::reattach_all_tearoffs ()
4260 {
4261         if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
4262         if (_tools_tearoff) _tools_tearoff->put_it_back ();
4263         if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
4264 }
4265
4266 void
4267 Editor::maximise_editing_space ()
4268 {
4269         if (_maximised) {
4270                 return;
4271         }
4272
4273         fullscreen ();
4274
4275         _maximised = true;
4276 }
4277
4278 void
4279 Editor::restore_editing_space ()
4280 {
4281         if (!_maximised) {
4282                 return;
4283         }
4284
4285         unfullscreen();
4286
4287         _maximised = false;
4288 }
4289
4290 /**
4291  *  Make new playlists for a given track and also any others that belong
4292  *  to the same active route group with the `select' property.
4293  *  @param v Track.
4294  */
4295
4296 void
4297 Editor::new_playlists (TimeAxisView* v)
4298 {
4299         begin_reversible_command (_("new playlists"));
4300         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4301         _session->playlists->get (playlists);
4302         mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4303         commit_reversible_command ();
4304 }
4305
4306 /**
4307  *  Use a copy of the current playlist for a given track and also any others that belong
4308  *  to the same active route group with the `select' property.
4309  *  @param v Track.
4310  */
4311
4312 void
4313 Editor::copy_playlists (TimeAxisView* v)
4314 {
4315         begin_reversible_command (_("copy playlists"));
4316         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4317         _session->playlists->get (playlists);
4318         mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4319         commit_reversible_command ();
4320 }
4321
4322 /** Clear the current playlist for a given track and also any others that belong
4323  *  to the same active route group with the `select' property.
4324  *  @param v Track.
4325  */
4326
4327 void
4328 Editor::clear_playlists (TimeAxisView* v)
4329 {
4330         begin_reversible_command (_("clear playlists"));        
4331         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4332         _session->playlists->get (playlists);
4333         mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4334         commit_reversible_command ();
4335 }
4336
4337 void
4338 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4339 {
4340         atv.use_new_playlist (sz > 1 ? false : true, playlists);
4341 }
4342
4343 void
4344 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4345 {
4346         atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4347 }
4348
4349 void
4350 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4351 {
4352         atv.clear_playlist ();
4353 }
4354
4355 bool
4356 Editor::on_key_press_event (GdkEventKey* ev)
4357 {
4358         return key_press_focus_accelerator_handler (*this, ev);
4359 }
4360
4361 bool
4362 Editor::on_key_release_event (GdkEventKey* ev)
4363 {
4364         return Gtk::Window::on_key_release_event (ev);
4365         // return key_press_focus_accelerator_handler (*this, ev);
4366 }
4367
4368 double
4369 Editor::get_y_origin () const
4370 {
4371         return vertical_adjustment.get_value ();
4372 }
4373
4374 /** Queue up a change to the viewport x origin.
4375  *  @param frame New x origin.
4376  */
4377 void
4378 Editor::reset_x_origin (framepos_t frame)
4379 {
4380         pending_visual_change.add (VisualChange::TimeOrigin);
4381         pending_visual_change.time_origin = frame;
4382         ensure_visual_change_idle_handler ();
4383 }
4384
4385 void
4386 Editor::reset_y_origin (double y)
4387 {
4388         pending_visual_change.add (VisualChange::YOrigin);
4389         pending_visual_change.y_origin = y;
4390         ensure_visual_change_idle_handler ();
4391 }
4392
4393 void
4394 Editor::reset_zoom (framecnt_t spp)
4395 {
4396         if (spp == samples_per_pixel) {
4397                 return;
4398         }
4399
4400         pending_visual_change.add (VisualChange::ZoomLevel);
4401         pending_visual_change.samples_per_pixel = spp;
4402         ensure_visual_change_idle_handler ();
4403 }
4404
4405 void
4406 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4407 {
4408         reset_x_origin (frame);
4409         reset_zoom (fpu);
4410
4411         if (!no_save_visual) {
4412                 undo_visual_stack.push_back (current_visual_state(false));
4413         }
4414 }
4415
4416 Editor::VisualState::VisualState (bool with_tracks)
4417         : gui_state (with_tracks ? new GUIObjectState : 0)
4418 {
4419 }
4420
4421 Editor::VisualState::~VisualState ()
4422 {
4423         delete gui_state;
4424 }
4425
4426 Editor::VisualState*
4427 Editor::current_visual_state (bool with_tracks)
4428 {
4429         VisualState* vs = new VisualState (with_tracks);
4430         vs->y_position = vertical_adjustment.get_value();
4431         vs->samples_per_pixel = samples_per_pixel;
4432         vs->leftmost_frame = leftmost_frame;
4433         vs->zoom_focus = zoom_focus;
4434
4435         if (with_tracks) {      
4436                 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4437         }
4438
4439         return vs;
4440 }
4441
4442 void
4443 Editor::undo_visual_state ()
4444 {
4445         if (undo_visual_stack.empty()) {
4446                 return;
4447         }
4448
4449         VisualState* vs = undo_visual_stack.back();
4450         undo_visual_stack.pop_back();
4451
4452
4453         redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4454
4455         if (vs) {
4456                 use_visual_state (*vs);
4457         }
4458 }
4459
4460 void
4461 Editor::redo_visual_state ()
4462 {
4463         if (redo_visual_stack.empty()) {
4464                 return;
4465         }
4466
4467         VisualState* vs = redo_visual_stack.back();
4468         redo_visual_stack.pop_back();
4469
4470         // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4471         // why do we check here?
4472         undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4473
4474         if (vs) {
4475                 use_visual_state (*vs);
4476         }
4477 }
4478
4479 void
4480 Editor::swap_visual_state ()
4481 {
4482         if (undo_visual_stack.empty()) {
4483                 redo_visual_state ();
4484         } else {
4485                 undo_visual_state ();
4486         }
4487 }
4488
4489 void
4490 Editor::use_visual_state (VisualState& vs)
4491 {
4492         PBD::Unwinder<bool> nsv (no_save_visual, true);
4493         DisplaySuspender ds;
4494
4495         vertical_adjustment.set_value (vs.y_position);
4496
4497         set_zoom_focus (vs.zoom_focus);
4498         reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4499         
4500         if (vs.gui_state) {
4501                 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4502                 
4503                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {    
4504                         (*i)->clear_property_cache();
4505                         (*i)->reset_visual_state ();
4506                 }
4507         }
4508
4509         _routes->update_visibility ();
4510 }
4511
4512 /** This is the core function that controls the zoom level of the canvas. It is called
4513  *  whenever one or more calls are made to reset_zoom().  It executes in an idle handler.
4514  *  @param spp new number of samples per pixel
4515  */
4516 void
4517 Editor::set_samples_per_pixel (framecnt_t spp)
4518 {
4519         if (spp < 1) {
4520                 return;
4521         }
4522
4523         const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4524         const framecnt_t lots_of_pixels = 4000;
4525
4526         /* if the zoom level is greater than what you'd get trying to display 3
4527          * days of audio on a really big screen, then it's too big.
4528          */
4529
4530         if (spp * lots_of_pixels > three_days) {
4531                 return;
4532         }
4533
4534         samples_per_pixel = spp;
4535
4536         if (tempo_lines) {
4537                 tempo_lines->tempo_map_changed();
4538         }
4539
4540         bool const showing_time_selection = selection->time.length() > 0;
4541
4542         if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4543                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4544                         (*i)->reshow_selection (selection->time);
4545                 }
4546         }
4547
4548         ZoomChanged (); /* EMIT_SIGNAL */
4549
4550         ArdourCanvas::GtkCanvasViewport* c;
4551
4552         c = get_track_canvas();
4553         if (c) {
4554                 c->canvas()->zoomed ();
4555         }
4556
4557         if (playhead_cursor) {
4558                 playhead_cursor->set_position (playhead_cursor->current_frame ());
4559         }
4560
4561         refresh_location_display();
4562         _summary->set_overlays_dirty ();
4563
4564         update_marker_labels ();
4565
4566         instant_save ();
4567 }
4568
4569 void
4570 Editor::queue_visual_videotimeline_update ()
4571 {
4572         /* TODO:
4573          * pending_visual_change.add (VisualChange::VideoTimeline);
4574          * or maybe even more specific: which videotimeline-image
4575          * currently it calls update_video_timeline() to update
4576          * _all outdated_ images on the video-timeline.
4577          * see 'exposeimg()' in video_image_frame.cc
4578          */
4579         ensure_visual_change_idle_handler ();
4580 }
4581
4582 void
4583 Editor::ensure_visual_change_idle_handler ()
4584 {
4585         if (pending_visual_change.idle_handler_id < 0) {
4586                 // see comment in add_to_idle_resize above.
4587                 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4588                 pending_visual_change.being_handled = false;
4589         }
4590 }
4591
4592 int
4593 Editor::_idle_visual_changer (void* arg)
4594 {
4595         return static_cast<Editor*>(arg)->idle_visual_changer ();
4596 }
4597
4598 int
4599 Editor::idle_visual_changer ()
4600 {
4601         /* set_horizontal_position() below (and maybe other calls) call
4602            gtk_main_iteration(), so it's possible that a signal will be handled
4603            half-way through this method.  If this signal wants an
4604            idle_visual_changer we must schedule another one after this one, so
4605            mark the idle_handler_id as -1 here to allow that.  Also make a note
4606            that we are doing the visual change, so that changes in response to
4607            super-rapid-screen-update can be dropped if we are still processing
4608            the last one.
4609         */
4610
4611         pending_visual_change.idle_handler_id = -1;
4612         pending_visual_change.being_handled = true;
4613         
4614         VisualChange vc = pending_visual_change;
4615
4616         pending_visual_change.pending = (VisualChange::Type) 0;
4617
4618         visual_changer (vc);
4619
4620         pending_visual_change.being_handled = false;
4621
4622         return 0; /* this is always a one-shot call */
4623 }
4624
4625 void
4626 Editor::visual_changer (const VisualChange& vc)
4627 {
4628         double const last_time_origin = horizontal_position ();
4629
4630         if (vc.pending & VisualChange::ZoomLevel) {
4631                 set_samples_per_pixel (vc.samples_per_pixel);
4632
4633                 compute_fixed_ruler_scale ();
4634
4635                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4636                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4637                 
4638                 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4639                                             current_bbt_points_begin, current_bbt_points_end);
4640                 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4641                                          current_bbt_points_begin, current_bbt_points_end);
4642                 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4643
4644                 update_video_timeline();
4645         }
4646
4647         if (vc.pending & VisualChange::TimeOrigin) {
4648                 set_horizontal_position (vc.time_origin / samples_per_pixel);
4649         }
4650
4651         if (vc.pending & VisualChange::YOrigin) {
4652                 vertical_adjustment.set_value (vc.y_origin);
4653         }
4654
4655         if (last_time_origin == horizontal_position ()) {
4656                 /* changed signal not emitted */
4657                 update_fixed_rulers ();
4658                 redisplay_tempo (true);
4659         }
4660
4661         if (!(vc.pending & VisualChange::ZoomLevel)) {
4662                 update_video_timeline();
4663         }
4664
4665         _summary->set_overlays_dirty ();
4666 }
4667
4668 struct EditorOrderTimeAxisSorter {
4669     bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4670             return a->order () < b->order ();
4671     }
4672 };
4673
4674 void
4675 Editor::sort_track_selection (TrackViewList& sel)
4676 {
4677         EditorOrderTimeAxisSorter cmp;
4678         sel.sort (cmp);
4679 }
4680
4681 framepos_t
4682 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4683 {
4684         bool ignored;
4685         framepos_t where = 0;
4686         EditPoint ep = _edit_point;
4687
4688         if (Profile->get_mixbus())
4689                 if (ep == EditAtSelectedMarker)
4690                         ep = EditAtPlayhead;
4691
4692         if (from_outside_canvas && (ep == EditAtMouse)) {
4693                 ep = EditAtPlayhead;
4694         } else if (from_context_menu && (ep == EditAtMouse)) {
4695                 return  canvas_event_sample (&context_click_event, 0, 0);
4696         }
4697
4698         if (entered_marker) {
4699                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4700                 return entered_marker->position();
4701         }
4702
4703         if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4704                 ep = EditAtSelectedMarker;
4705         }
4706
4707         if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4708                 ep = EditAtPlayhead;
4709         }
4710
4711         switch (ep) {
4712         case EditAtPlayhead:
4713                 if (_dragging_playhead) {
4714                         if (!mouse_frame (where, ignored)) {
4715                                 /* XXX not right but what can we do ? */
4716                                 return 0;
4717                         }
4718                 } else {
4719                         where = _session->audible_frame();
4720                 }
4721                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4722                 break;
4723
4724         case EditAtSelectedMarker:
4725                 if (!selection->markers.empty()) {
4726                         bool is_start;
4727                         Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4728                         if (loc) {
4729                                 if (is_start) {
4730                                         where =  loc->start();
4731                                 } else {
4732                                         where = loc->end();
4733                                 }
4734                                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4735                                 break;
4736                         }
4737                 }
4738                 /* fallthru */
4739
4740         default:
4741         case EditAtMouse:
4742                 if (!mouse_frame (where, ignored)) {
4743                         /* XXX not right but what can we do ? */
4744                         return 0;
4745                 }
4746                 snap_to (where);
4747                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4748                 break;
4749         }
4750
4751         return where;
4752 }
4753
4754 void
4755 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4756 {
4757         if (!_session) return;
4758
4759         begin_reversible_command (cmd);
4760
4761         Location* tll;
4762
4763         if ((tll = transport_loop_location()) == 0) {
4764                 Location* loc = new Location (*_session, start, end, _("Loop"),  Location::IsAutoLoop);
4765                 XMLNode &before = _session->locations()->get_state();
4766                 _session->locations()->add (loc, true);
4767                 _session->set_auto_loop_location (loc);
4768                 XMLNode &after = _session->locations()->get_state();
4769                 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4770         } else {
4771                 XMLNode &before = tll->get_state();
4772                 tll->set_hidden (false, this);
4773                 tll->set (start, end);
4774                 XMLNode &after = tll->get_state();
4775                 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4776         }
4777
4778         commit_reversible_command ();
4779 }
4780
4781 void
4782 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4783 {
4784         if (!_session) return;
4785
4786         begin_reversible_command (cmd);
4787
4788         Location* tpl;
4789
4790         if ((tpl = transport_punch_location()) == 0) {
4791                 Location* loc = new Location (*_session, start, end, _("Punch"),  Location::IsAutoPunch);
4792                 XMLNode &before = _session->locations()->get_state();
4793                 _session->locations()->add (loc, true);
4794                 _session->set_auto_punch_location (loc);
4795                 XMLNode &after = _session->locations()->get_state();
4796                 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4797         } else {
4798                 XMLNode &before = tpl->get_state();
4799                 tpl->set_hidden (false, this);
4800                 tpl->set (start, end);
4801                 XMLNode &after = tpl->get_state();
4802                 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4803         }
4804
4805         commit_reversible_command ();
4806 }
4807
4808 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4809  *  @param rs List to which found regions are added.
4810  *  @param where Time to look at.
4811  *  @param ts Tracks to look on; if this is empty, all tracks are examined.
4812  */
4813 void
4814 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4815 {
4816         const TrackViewList* tracks;
4817
4818         if (ts.empty()) {
4819                 tracks = &track_views;
4820         } else {
4821                 tracks = &ts;
4822         }
4823
4824         for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4825
4826                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4827
4828                 if (rtv) {
4829                         boost::shared_ptr<Track> tr;
4830                         boost::shared_ptr<Playlist> pl;
4831
4832                         if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4833
4834                                 boost::shared_ptr<RegionList> regions = pl->regions_at (
4835                                                 (framepos_t) floor ( (double) where * tr->speed()));
4836
4837                                 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4838                                         RegionView* rv = rtv->view()->find_view (*i);
4839                                         if (rv) {
4840                                                 rs.add (rv);
4841                                         }
4842                                 }
4843                         }
4844                 }
4845         }
4846 }
4847
4848 void
4849 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4850 {
4851         const TrackViewList* tracks;
4852
4853         if (ts.empty()) {
4854                 tracks = &track_views;
4855         } else {
4856                 tracks = &ts;
4857         }
4858
4859         for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4860                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4861                 if (rtv) {
4862                         boost::shared_ptr<Track> tr;
4863                         boost::shared_ptr<Playlist> pl;
4864
4865                         if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4866
4867                                 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4868                                         (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4869
4870                                 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4871
4872                                         RegionView* rv = rtv->view()->find_view (*i);
4873
4874                                         if (rv) {
4875                                                 rs.add (rv);
4876                                         }
4877                                 }
4878                         }
4879                 }
4880         }
4881 }
4882
4883 /** Get regions using the following method:
4884  *
4885  *  Make a region list using:
4886  *   (a) any selected regions
4887  *   (b) the intersection of any selected tracks and the edit point(*)
4888  *   (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4889  *
4890  *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4891  *
4892  *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4893  */
4894
4895 RegionSelection
4896 Editor::get_regions_from_selection_and_edit_point ()
4897 {
4898         RegionSelection regions;
4899
4900         if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4901                 regions.add (entered_regionview);
4902         } else {
4903                 regions = selection->regions;
4904         }
4905
4906         if ( regions.empty() ) {
4907                 TrackViewList tracks = selection->tracks;
4908
4909                 if (!tracks.empty()) {
4910                         /* no region selected or entered, but some selected tracks:
4911                          * act on all regions on the selected tracks at the edit point
4912                          */ 
4913                         framepos_t const where = get_preferred_edit_position ();
4914                         get_regions_at(regions, where, tracks);
4915                 }
4916         }
4917
4918         return regions;
4919 }
4920
4921 /** Get regions using the following method:
4922  *
4923  *  Make a region list using:
4924  *   (a) any selected regions
4925  *   (b) the intersection of any selected tracks and the edit point(*)
4926  *   (c) if neither exists, then whatever region is under the mouse
4927  *
4928  *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4929  *
4930  *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4931  */
4932 RegionSelection
4933 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4934 {
4935         RegionSelection regions;
4936
4937         if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4938                 regions.add (entered_regionview);
4939         } else {
4940                 regions = selection->regions;
4941         }
4942
4943         if ( regions.empty() ) {
4944                 TrackViewList tracks = selection->tracks;
4945
4946                 if (!tracks.empty()) {
4947                         /* no region selected or entered, but some selected tracks:
4948                          * act on all regions on the selected tracks at the edit point
4949                          */ 
4950                         get_regions_at(regions, pos, tracks);
4951                 }
4952         }
4953
4954         return regions;
4955 }
4956
4957 /** Start with regions that are selected, or the entered regionview if none are selected.
4958  *  Then add equivalent regions on tracks in the same active edit-enabled route group as any
4959  *  of the regions that we started with.
4960  */
4961
4962 RegionSelection
4963 Editor::get_regions_from_selection_and_entered ()
4964 {
4965         RegionSelection regions = selection->regions;
4966
4967         if (regions.empty() && entered_regionview) {
4968                 regions.add (entered_regionview);
4969         }
4970
4971         return regions;
4972 }
4973
4974 void
4975 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4976 {
4977         for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4978                 RouteTimeAxisView* rtav;
4979                 
4980                 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4981                         boost::shared_ptr<Playlist> pl;
4982                         std::vector<boost::shared_ptr<Region> > results;
4983                         boost::shared_ptr<Track> tr;
4984                         
4985                         if ((tr = rtav->track()) == 0) {
4986                                 /* bus */
4987                                 continue;
4988                         }
4989                         
4990                         if ((pl = (tr->playlist())) != 0) {
4991                                 boost::shared_ptr<Region> r = pl->region_by_id (id);
4992                                 if (r) {
4993                                         RegionView* rv = rtav->view()->find_view (r);
4994                                         if (rv) {
4995                                                 regions.push_back (rv);
4996                                         }
4997                                 }
4998                         }
4999                 }
5000         }
5001 }
5002
5003 void
5004 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
5005 {
5006
5007         for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5008                 MidiTimeAxisView* mtav;
5009
5010                 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
5011
5012                         mtav->get_per_region_note_selection (selection);
5013                 }
5014         }
5015         
5016 }
5017
5018 void
5019 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
5020 {
5021         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5022
5023                 RouteTimeAxisView* tatv;
5024
5025                 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
5026
5027                         boost::shared_ptr<Playlist> pl;
5028                         vector<boost::shared_ptr<Region> > results;
5029                         RegionView* marv;
5030                         boost::shared_ptr<Track> tr;
5031
5032                         if ((tr = tatv->track()) == 0) {
5033                                 /* bus */
5034                                 continue;
5035                         }
5036
5037                         if ((pl = (tr->playlist())) != 0) {
5038                                 if (src_comparison) {
5039                                         pl->get_source_equivalent_regions (region, results);
5040                                 } else {
5041                                         pl->get_region_list_equivalent_regions (region, results);
5042                                 }
5043                         }
5044
5045                         for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
5046                                 if ((marv = tatv->view()->find_view (*ir)) != 0) {
5047                                         regions.push_back (marv);
5048                                 }
5049                         }
5050
5051                 }
5052         }
5053 }
5054
5055 void
5056 Editor::show_rhythm_ferret ()
5057 {
5058         if (rhythm_ferret == 0) {
5059                 rhythm_ferret = new RhythmFerret(*this);
5060         }
5061
5062         rhythm_ferret->set_session (_session);
5063         rhythm_ferret->show ();
5064         rhythm_ferret->present ();
5065 }
5066
5067 void
5068 Editor::first_idle ()
5069 {
5070         MessageDialog* dialog = 0;
5071         
5072         if (track_views.size() > 1) {
5073                 dialog = new MessageDialog (
5074                         *this,
5075                         string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5076                         true
5077                         );
5078                 dialog->present ();
5079                 ARDOUR_UI::instance()->flush_pending ();
5080         }
5081
5082         for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5083                 (*t)->first_idle();
5084         }
5085
5086         // first idle adds route children (automation tracks), so we need to redisplay here
5087         _routes->redisplay ();
5088
5089         delete dialog;
5090
5091         if (_session->undo_depth() == 0) {
5092                 undo_action->set_sensitive(false);
5093         }
5094         redo_action->set_sensitive(false);
5095         begin_selection_op_history ();
5096
5097         _have_idled = true;
5098 }
5099
5100 gboolean
5101 Editor::_idle_resize (gpointer arg)
5102 {
5103         return ((Editor*)arg)->idle_resize ();
5104 }
5105
5106 void
5107 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5108 {
5109         if (resize_idle_id < 0) {
5110                 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5111                  * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5112                  * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5113                  */
5114                 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5115                 _pending_resize_amount = 0;
5116         }
5117
5118         /* make a note of the smallest resulting height, so that we can clamp the
5119            lower limit at TimeAxisView::hSmall */
5120
5121         int32_t min_resulting = INT32_MAX;
5122
5123         _pending_resize_amount += h;
5124         _pending_resize_view = view;
5125
5126         min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5127
5128         if (selection->tracks.contains (_pending_resize_view)) {
5129                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5130                         min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5131                 }
5132         }
5133
5134         if (min_resulting < 0) {
5135                 min_resulting = 0;
5136         }
5137
5138         /* clamp */
5139         if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5140                 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5141         }
5142 }
5143
5144 /** Handle pending resizing of tracks */
5145 bool
5146 Editor::idle_resize ()
5147 {
5148         _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5149
5150         if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5151             selection->tracks.contains (_pending_resize_view)) {
5152
5153                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5154                         if (*i != _pending_resize_view) {
5155                                 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5156                         }
5157                 }
5158         }
5159
5160         _pending_resize_amount = 0;
5161         _group_tabs->set_dirty ();
5162         resize_idle_id = -1;
5163
5164         return false;
5165 }
5166
5167 void
5168 Editor::located ()
5169 {
5170         ENSURE_GUI_THREAD (*this, &Editor::located);
5171
5172         if (_session) {
5173                 playhead_cursor->set_position (_session->audible_frame ());
5174                 if (_follow_playhead && !_pending_initial_locate) {
5175                         reset_x_origin_to_follow_playhead ();
5176                 }
5177         }
5178
5179         _pending_locate_request = false;
5180         _pending_initial_locate = false;
5181 }
5182
5183 void
5184 Editor::region_view_added (RegionView * rv)
5185 {
5186         for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5187                 if (rv->region ()->id () == (*pr)) {
5188                         selection->add (rv);
5189                         selection->regions.pending.erase (pr);
5190                         break;
5191                 }
5192         }
5193
5194         MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5195         if (mrv) {
5196                 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5197                 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5198                         if (rv->region()->id () == (*rnote).first) {
5199                                 mrv->select_notes ((*rnote).second);
5200                                 selection->pending_midi_note_selection.erase(rnote);
5201                                 break;
5202                         }
5203                 }
5204         }
5205
5206         _summary->set_background_dirty ();
5207 }
5208
5209 void
5210 Editor::region_view_removed ()
5211 {
5212         _summary->set_background_dirty ();
5213 }
5214
5215 RouteTimeAxisView*
5216 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5217 {
5218         TrackViewList::const_iterator j = track_views.begin ();
5219         while (j != track_views.end()) {
5220                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5221                 if (rtv && rtv->route() == r) {
5222                         return rtv;
5223                 }
5224                 ++j;
5225         }
5226
5227         return 0;
5228 }
5229
5230
5231 TrackViewList
5232 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5233 {
5234         TrackViewList t;
5235
5236         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5237                 TimeAxisView* tv = axis_view_from_route (*i);
5238                 if (tv) {
5239                         t.push_back (tv);
5240                 }
5241         }
5242
5243         return t;
5244 }
5245
5246 void
5247 Editor::suspend_route_redisplay ()
5248 {
5249         if (_routes) {
5250                 _routes->suspend_redisplay();
5251         }
5252 }
5253
5254 void
5255 Editor::resume_route_redisplay ()
5256 {
5257         if (_routes) {
5258                 _routes->redisplay(); // queue redisplay
5259                 _routes->resume_redisplay();
5260         }
5261 }
5262
5263 void
5264 Editor::add_routes (RouteList& routes)
5265 {
5266         ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5267
5268         RouteTimeAxisView *rtv;
5269         list<RouteTimeAxisView*> new_views;
5270         TrackViewList new_selection;
5271         bool from_scratch = (track_views.size() == 0);
5272
5273         for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5274                 boost::shared_ptr<Route> route = (*x);
5275
5276                 if (route->is_auditioner() || route->is_monitor()) {
5277                         continue;
5278                 }
5279
5280                 DataType dt = route->input()->default_type();
5281
5282                 if (dt == ARDOUR::DataType::AUDIO) {
5283                         rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5284                         rtv->set_route (route);
5285                 } else if (dt == ARDOUR::DataType::MIDI) {
5286                         rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5287                         rtv->set_route (route);
5288                 } else {
5289                         throw unknown_type();
5290                 }
5291
5292                 new_views.push_back (rtv);
5293                 track_views.push_back (rtv);
5294                 new_selection.push_back (rtv);
5295
5296                 rtv->effective_gain_display ();
5297
5298                 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5299                 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5300         }
5301
5302         if (new_views.size() > 0) {
5303                 _routes->routes_added (new_views);
5304                 _summary->routes_added (new_views);
5305         }
5306
5307         if (!from_scratch) {
5308                 selection->tracks.clear();
5309                 selection->add (new_selection);
5310                 begin_selection_op_history();
5311         }
5312
5313         if (show_editor_mixer_when_tracks_arrive) {
5314                 show_editor_mixer (true);
5315         }
5316
5317         editor_list_button.set_sensitive (true);
5318 }
5319
5320 void
5321 Editor::timeaxisview_deleted (TimeAxisView *tv)
5322 {
5323         if (tv == entered_track) {
5324                 entered_track = 0;
5325         }
5326
5327         if (_session && _session->deletion_in_progress()) {
5328                 /* the situation is under control */
5329                 return;
5330         }
5331
5332         ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5333
5334         RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5335
5336         _routes->route_removed (tv);
5337
5338         TimeAxisView::Children c = tv->get_child_list ();
5339         for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5340                 if (entered_track == i->get()) {
5341                         entered_track = 0;
5342                 }
5343         }
5344
5345         /* remove it from the list of track views */
5346
5347         TrackViewList::iterator i;
5348
5349         if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5350                 i = track_views.erase (i);
5351         }
5352
5353         /* update whatever the current mixer strip is displaying, if revelant */
5354
5355         boost::shared_ptr<Route> route;
5356
5357         if (rtav) {
5358                 route = rtav->route ();
5359         }
5360
5361         if (current_mixer_strip && current_mixer_strip->route() == route) {
5362
5363                 TimeAxisView* next_tv;
5364
5365                 if (track_views.empty()) {
5366                         next_tv = 0;
5367                 } else if (i == track_views.end()) {
5368                         next_tv = track_views.front();
5369                 } else {
5370                         next_tv = (*i);
5371                 }
5372
5373
5374                 if (next_tv) {
5375                         set_selected_mixer_strip (*next_tv);
5376                 } else {
5377                         /* make the editor mixer strip go away setting the
5378                          * button to inactive (which also unticks the menu option)
5379                          */
5380
5381                         ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5382                 }
5383         }
5384 }
5385
5386 void
5387 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5388 {
5389         if (apply_to_selection) {
5390                 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5391
5392                         TrackSelection::iterator j = i;
5393                         ++j;
5394
5395                         hide_track_in_display (*i, false);
5396
5397                         i = j;
5398                 }
5399         } else {
5400                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5401
5402                 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5403                         // this will hide the mixer strip
5404                         set_selected_mixer_strip (*tv);
5405                 }
5406
5407                 _routes->hide_track_in_display (*tv);
5408         }
5409 }
5410
5411 bool
5412 Editor::sync_track_view_list_and_routes ()
5413 {
5414         track_views = TrackViewList (_routes->views ());
5415
5416         _summary->set_background_dirty();
5417         _group_tabs->set_dirty ();
5418
5419         return false; // do not call again (until needed)
5420 }
5421
5422 void
5423 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5424 {
5425         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5426                 theslot (**i);
5427         }
5428 }
5429
5430 /** Find a RouteTimeAxisView by the ID of its route */
5431 RouteTimeAxisView*
5432 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5433 {
5434         RouteTimeAxisView* v;
5435
5436         for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5437                 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5438                         if(v->route()->id() == id) {
5439                                 return v;
5440                         }
5441                 }
5442         }
5443
5444         return 0;
5445 }
5446
5447 void
5448 Editor::fit_route_group (RouteGroup *g)
5449 {
5450         TrackViewList ts = axis_views_from_routes (g->route_list ());
5451         fit_tracks (ts);
5452 }
5453
5454 void
5455 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5456 {
5457         boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5458
5459         if (r == 0) {
5460                 _session->cancel_audition ();
5461                 return;
5462         }
5463
5464         if (_session->is_auditioning()) {
5465                 _session->cancel_audition ();
5466                 if (r == last_audition_region) {
5467                         return;
5468                 }
5469         }
5470
5471         _session->audition_region (r);
5472         last_audition_region = r;
5473 }
5474
5475
5476 void
5477 Editor::hide_a_region (boost::shared_ptr<Region> r)
5478 {
5479         r->set_hidden (true);
5480 }
5481
5482 void
5483 Editor::show_a_region (boost::shared_ptr<Region> r)
5484 {
5485         r->set_hidden (false);
5486 }
5487
5488 void
5489 Editor::audition_region_from_region_list ()
5490 {
5491         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5492 }
5493
5494 void
5495 Editor::hide_region_from_region_list ()
5496 {
5497         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5498 }
5499
5500 void
5501 Editor::show_region_in_region_list ()
5502 {
5503         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5504 }
5505
5506 void
5507 Editor::step_edit_status_change (bool yn)
5508 {
5509         if (yn) {
5510                 start_step_editing ();
5511         } else {
5512                 stop_step_editing ();
5513         }
5514 }
5515
5516 void
5517 Editor::start_step_editing ()
5518 {
5519         step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5520 }
5521
5522 void
5523 Editor::stop_step_editing ()
5524 {
5525         step_edit_connection.disconnect ();
5526 }
5527
5528 bool
5529 Editor::check_step_edit ()
5530 {
5531         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5532                 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5533                 if (mtv) {
5534                         mtv->check_step_edit ();
5535                 }
5536         }
5537
5538         return true; // do it again, till we stop
5539 }
5540
5541 bool
5542 Editor::scroll_press (Direction dir)
5543 {
5544         ++_scroll_callbacks;
5545
5546         if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5547                 /* delay the first auto-repeat */
5548                 return true;
5549         }
5550
5551         switch (dir) {
5552         case LEFT:
5553                 scroll_backward (1);
5554                 break;
5555
5556         case RIGHT:
5557                 scroll_forward (1);
5558                 break;
5559
5560         case UP:
5561                 scroll_up_one_track ();
5562                 break;
5563
5564         case DOWN:
5565                 scroll_down_one_track ();
5566                 break;
5567         }
5568
5569         /* do hacky auto-repeat */
5570         if (!_scroll_connection.connected ()) {
5571
5572                 _scroll_connection = Glib::signal_timeout().connect (
5573                         sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5574                         );
5575
5576                 _scroll_callbacks = 0;
5577         }
5578
5579         return true;
5580 }
5581
5582 void
5583 Editor::scroll_release ()
5584 {
5585         _scroll_connection.disconnect ();
5586 }
5587
5588 /** Queue a change for the Editor viewport x origin to follow the playhead */
5589 void
5590 Editor::reset_x_origin_to_follow_playhead ()
5591 {
5592         framepos_t const frame = playhead_cursor->current_frame ();
5593
5594         if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5595
5596                 if (_session->transport_speed() < 0) {
5597
5598                         if (frame > (current_page_samples() / 2)) {
5599                                 center_screen (frame-(current_page_samples()/2));
5600                         } else {
5601                                 center_screen (current_page_samples()/2);
5602                         }
5603
5604                 } else {
5605
5606                         framepos_t l = 0;
5607                         
5608                         if (frame < leftmost_frame) {
5609                                 /* moving left */
5610                                 if (_session->transport_rolling()) {
5611                                         /* rolling; end up with the playhead at the right of the page */
5612                                         l = frame - current_page_samples ();
5613                                 } else {
5614                                         /* not rolling: end up with the playhead 1/4 of the way along the page */
5615                                         l = frame - current_page_samples() / 4;
5616                                 }
5617                         } else {
5618                                 /* moving right */
5619                                 if (_session->transport_rolling()) {
5620                                         /* rolling: end up with the playhead on the left of the page */
5621                                         l = frame;
5622                                 } else {
5623                                         /* not rolling: end up with the playhead 3/4 of the way along the page */
5624                                         l = frame - 3 * current_page_samples() / 4;
5625                                 }
5626                         }
5627
5628                         if (l < 0) {
5629                                 l = 0;
5630                         }
5631                         
5632                         center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5633                 }
5634         }
5635 }
5636
5637 void
5638 Editor::super_rapid_screen_update ()
5639 {
5640         if (!_session || !_session->engine().running()) {
5641                 return;
5642         }
5643
5644         /* METERING / MIXER STRIPS */
5645
5646         /* update track meters, if required */
5647         if (is_mapped() && meters_running) {
5648                 RouteTimeAxisView* rtv;
5649                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5650                         if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5651                                 rtv->fast_update ();
5652                         }
5653                 }
5654         }
5655
5656         /* and any current mixer strip */
5657         if (current_mixer_strip) {
5658                 current_mixer_strip->fast_update ();
5659         }
5660
5661         /* PLAYHEAD AND VIEWPORT */
5662
5663         framepos_t const frame = _session->audible_frame();
5664
5665         /* There are a few reasons why we might not update the playhead / viewport stuff:
5666          *
5667          * 1.  we don't update things when there's a pending locate request, otherwise
5668          *     when the editor requests a locate there is a chance that this method
5669          *     will move the playhead before the locate request is processed, causing
5670          *     a visual glitch.
5671          * 2.  if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5672          * 3.  if we're still at the same frame that we were last time, there's nothing to do.
5673          */
5674
5675         if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5676
5677                 last_update_frame = frame;
5678
5679                 if (!_dragging_playhead) {
5680                         playhead_cursor->set_position (frame);
5681                 }
5682
5683                 if (!_stationary_playhead) {
5684
5685                         if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5686                                 /* We only do this if we aren't already
5687                                    handling a visual change (ie if
5688                                    pending_visual_change.being_handled is
5689                                    false) so that these requests don't stack
5690                                    up there are too many of them to handle in
5691                                    time.
5692                                 */
5693                                 reset_x_origin_to_follow_playhead ();
5694                         }
5695
5696                 } else {
5697
5698                         if (!_dragging_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5699                                 framepos_t const frame = playhead_cursor->current_frame ();
5700                                 double target = ((double)frame - (double)current_page_samples()/3.0);
5701                                 if (target <= 0.0) {
5702                                         target = 0.0;
5703                                 }
5704                                 // compare to EditorCursor::set_position()
5705                                 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5706                                 double const new_pos = sample_to_pixel_unrounded (target);
5707                                 if (rint (new_pos) != rint (old_pos)) {
5708                                         reset_x_origin (pixel_to_sample (floor (new_pos)));
5709                                 }
5710                         }
5711
5712                 }
5713
5714         }
5715 }
5716
5717
5718 void
5719 Editor::session_going_away ()
5720 {
5721         _have_idled = false;
5722
5723         _session_connections.drop_connections ();
5724
5725         super_rapid_screen_update_connection.disconnect ();
5726
5727         selection->clear ();
5728         cut_buffer->clear ();
5729
5730         clicked_regionview = 0;
5731         clicked_axisview = 0;
5732         clicked_routeview = 0;
5733         entered_regionview = 0;
5734         entered_track = 0;
5735         last_update_frame = 0;
5736         _drags->abort ();
5737
5738         playhead_cursor->hide ();
5739
5740         /* rip everything out of the list displays */
5741
5742         _regions->clear ();
5743         _routes->clear ();
5744         _route_groups->clear ();
5745
5746         /* do this first so that deleting a track doesn't reset cms to null
5747            and thus cause a leak.
5748         */
5749
5750         if (current_mixer_strip) {
5751                 if (current_mixer_strip->get_parent() != 0) {
5752                         global_hpacker.remove (*current_mixer_strip);
5753                 }
5754                 delete current_mixer_strip;
5755                 current_mixer_strip = 0;
5756         }
5757
5758         /* delete all trackviews */
5759
5760         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5761                 delete *i;
5762         }
5763         track_views.clear ();
5764
5765         nudge_clock->set_session (0);
5766
5767         editor_list_button.set_active(false);
5768         editor_list_button.set_sensitive(false);
5769
5770         /* clear tempo/meter rulers */
5771         remove_metric_marks ();
5772         hide_measures ();
5773         clear_marker_display ();
5774
5775         stop_step_editing ();
5776         
5777         /* get rid of any existing editor mixer strip */
5778
5779         WindowTitle title(Glib::get_application_name());
5780         title += _("Editor");
5781
5782         set_title (title.get_string());
5783
5784         SessionHandlePtr::session_going_away ();
5785 }
5786
5787
5788 void
5789 Editor::show_editor_list (bool yn)
5790 {
5791         if (yn) {
5792                 _the_notebook.show ();
5793         } else {
5794                 _the_notebook.hide ();
5795         }
5796 }
5797
5798 void
5799 Editor::change_region_layering_order (bool from_context_menu)
5800 {
5801         const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5802
5803         if (!clicked_routeview) {
5804                 if (layering_order_editor) {
5805                         layering_order_editor->hide ();
5806                 }
5807                 return;
5808         }
5809
5810         boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5811
5812         if (!track) {
5813                 return;
5814         }
5815
5816         boost::shared_ptr<Playlist> pl = track->playlist();
5817
5818         if (!pl) {
5819                 return;
5820         }
5821
5822         if (layering_order_editor == 0) {
5823                 layering_order_editor = new RegionLayeringOrderEditor (*this);
5824         }
5825
5826         layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5827         layering_order_editor->maybe_present ();
5828 }
5829
5830 void
5831 Editor::update_region_layering_order_editor ()
5832 {
5833         if (layering_order_editor && layering_order_editor->is_visible ()) {
5834                 change_region_layering_order (true);
5835         }
5836 }
5837
5838 void
5839 Editor::setup_fade_images ()
5840 {
5841         _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5842         _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5843         _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5844         _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5845         _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5846
5847         _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5848         _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5849         _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5850         _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5851         _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5852         
5853         _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5854         _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5855         _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5856         _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5857         _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5858
5859         _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5860         _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5861         _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5862         _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5863         _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5864
5865 }
5866
5867 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5868 Gtk::MenuItem&
5869 Editor::action_menu_item (std::string const & name)
5870 {
5871         Glib::RefPtr<Action> a = editor_actions->get_action (name);
5872         assert (a);
5873
5874         return *manage (a->create_menu_item ());
5875 }
5876
5877 void
5878 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5879 {
5880         EventBox* b = manage (new EventBox);
5881         b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5882         Label* l = manage (new Label (name));
5883         l->set_angle (-90);
5884         b->add (*l);
5885         b->show_all ();
5886         _the_notebook.append_page (widget, *b);
5887 }
5888
5889 bool
5890 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5891 {
5892         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5893                 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5894         }
5895
5896         if (ev->type == GDK_2BUTTON_PRESS) {
5897
5898                 /* double-click on a notebook tab shrinks or expands the notebook */
5899
5900                 if (_notebook_shrunk) {
5901                         if (pre_notebook_shrink_pane_width) {
5902                                 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5903                         }
5904                         _notebook_shrunk = false;
5905                 } else {
5906                         pre_notebook_shrink_pane_width = edit_pane.get_position();
5907
5908                         /* this expands the LHS of the edit pane to cover the notebook
5909                            PAGE but leaves the tabs visible.
5910                          */
5911                         edit_pane.set_position (edit_pane.get_position() + page->get_width());
5912                         _notebook_shrunk = true;
5913                 }
5914         }
5915
5916         return true;
5917 }
5918
5919 void
5920 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5921 {
5922         using namespace Menu_Helpers;
5923         
5924         MenuList& items = _control_point_context_menu.items ();
5925         items.clear ();
5926         
5927         items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5928         items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5929         if (!can_remove_control_point (item)) {
5930                 items.back().set_sensitive (false);
5931         }
5932
5933         _control_point_context_menu.popup (event->button.button, event->button.time);
5934 }
5935
5936 void
5937 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5938 {
5939         using namespace Menu_Helpers;
5940
5941         NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5942         if (!note) {
5943                 return;
5944         }
5945
5946         /* We need to get the selection here and pass it to the operations, since
5947            popping up the menu will cause a region leave event which clears
5948            entered_regionview. */
5949
5950         MidiRegionView&       mrv = note->region_view();
5951         const RegionSelection rs  = get_regions_from_selection_and_entered ();
5952
5953         MenuList& items = _note_context_menu.items();
5954         items.clear();
5955
5956         items.push_back(MenuElem(_("Delete"),
5957                                  sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5958         items.push_back(MenuElem(_("Edit..."),
5959                                  sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5960         items.push_back(MenuElem(_("Legatize"),
5961                                  sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5962         items.push_back(MenuElem(_("Quantize..."),
5963                                  sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5964         items.push_back(MenuElem(_("Remove Overlap"),
5965                                  sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5966         items.push_back(MenuElem(_("Transform..."),
5967                                  sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5968
5969         _note_context_menu.popup (event->button.button, event->button.time);
5970 }
5971
5972 void
5973 Editor::zoom_vertical_modifier_released()
5974 {
5975         _stepping_axis_view = 0;
5976 }
5977
5978 void
5979 Editor::ui_parameter_changed (string parameter)
5980 {
5981         if (parameter == "icon-set") {
5982                 while (!_cursor_stack.empty()) {
5983                         _cursor_stack.pop_back();
5984                 }
5985                 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5986                 _cursor_stack.push_back(_cursors->grabber);
5987         } else if (parameter == "draggable-playhead") {
5988                 if (_verbose_cursor) {
5989                         playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());
5990                 }
5991         }
5992 }