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