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