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