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