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