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