eeb09c5aa845ef600b8684458eb9f4061e7bbad9
[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_canvasvar_LocationMarker();
392         location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
393         location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
394         location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
395         location_punch_color = ARDOUR_UI::config()->get_canvasvar_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->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1360         _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1361
1362         playhead_cursor->show ();
1363
1364         boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1365         Config->map_parameters (pc);
1366         _session->config.map_parameters (pc);
1367
1368         restore_ruler_visibility ();
1369         //tempo_map_changed (PropertyChange (0));
1370         _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1371
1372         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1373                 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1374         }
1375
1376         super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1377                 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1378                 );
1379
1380         switch (_snap_type) {
1381         case SnapToRegionStart:
1382         case SnapToRegionEnd:
1383         case SnapToRegionSync:
1384         case SnapToRegionBoundary:
1385                 build_region_boundary_cache ();
1386                 break;
1387
1388         default:
1389                 break;
1390         }
1391
1392         /* register for undo history */
1393         _session->register_with_memento_command_factory(id(), this);
1394
1395         ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1396
1397         start_updating_meters ();
1398 }
1399
1400 void
1401 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1402 {
1403         if (a->get_name() == "RegionMenu") {
1404                 /* When the main menu's region menu is opened, we setup the actions so that they look right
1405                    in the menu.  I can't find a way of getting a signal when this menu is subsequently closed,
1406                    so we resensitize all region actions when the entered regionview or the region selection
1407                    changes.  HOWEVER we can't always resensitize on entered_regionview change because that
1408                    happens after the region context menu is opened.  So we set a flag here, too.
1409
1410                    What a carry on :(
1411                 */
1412                 sensitize_the_right_region_actions ();
1413                 _last_region_menu_was_main = true;
1414         }
1415 }
1416
1417 void
1418 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1419 {
1420         using namespace Menu_Helpers;
1421
1422         void (Editor::*emf)(FadeShape);
1423         std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1424
1425         if (start) {
1426                 images = &_xfade_in_images;
1427                 emf = &Editor::set_fade_in_shape;
1428         } else {
1429                 images = &_xfade_out_images;
1430                 emf = &Editor::set_fade_out_shape;
1431         }
1432
1433         items.push_back (
1434                 ImageMenuElem (
1435                         _("Linear (for highly correlated material)"),
1436                         *(*images)[FadeLinear],
1437                         sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1438                         )
1439                 );
1440         
1441         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1442         
1443         items.push_back (
1444                 ImageMenuElem (
1445                         _("Constant power"),
1446                         *(*images)[FadeConstantPower],
1447                         sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1448                         ));
1449         
1450         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1451         
1452         items.push_back (
1453                 ImageMenuElem (
1454                         _("Symmetric"),
1455                         *(*images)[FadeSymmetric],
1456                         sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1457                         )
1458                 );
1459         
1460         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1461         
1462         items.push_back (
1463                 ImageMenuElem (
1464                         _("Slow"),
1465                         *(*images)[FadeSlow],
1466                         sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1467                         ));
1468         
1469         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1470         
1471         items.push_back (
1472                 ImageMenuElem (
1473                         _("Fast"),
1474                         *(*images)[FadeFast],
1475                         sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1476                         ));
1477         
1478         dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1479 }
1480
1481 /** Pop up a context menu for when the user clicks on a start crossfade */
1482 void
1483 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1484 {
1485         using namespace Menu_Helpers;
1486         AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1487         assert(arv);
1488
1489         MenuList& items (xfade_in_context_menu.items());
1490         items.clear ();
1491
1492         if (arv->audio_region()->fade_in_active()) {
1493                 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1494         } else {
1495                 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1496         }
1497
1498         items.push_back (SeparatorElem());
1499         fill_xfade_menu (items, true);
1500
1501         xfade_in_context_menu.popup (button, time);
1502 }
1503
1504 /** Pop up a context menu for when the user clicks on an end crossfade */
1505 void
1506 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1507 {
1508         using namespace Menu_Helpers;
1509         AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1510         assert(arv);
1511
1512         MenuList& items (xfade_out_context_menu.items());
1513         items.clear ();
1514
1515         if (arv->audio_region()->fade_out_active()) {
1516                 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1517         } else {
1518                 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1519         }
1520
1521         items.push_back (SeparatorElem());
1522         fill_xfade_menu (items, false);
1523
1524         xfade_out_context_menu.popup (button, time);
1525 }
1526
1527 void
1528 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1529 {
1530         using namespace Menu_Helpers;
1531         Menu* (Editor::*build_menu_function)();
1532         Menu *menu;
1533
1534         switch (item_type) {
1535         case RegionItem:
1536         case RegionViewName:
1537         case RegionViewNameHighlight:
1538         case LeftFrameHandle:
1539         case RightFrameHandle:
1540                 if (with_selection) {
1541                         build_menu_function = &Editor::build_track_selection_context_menu;
1542                 } else {
1543                         build_menu_function = &Editor::build_track_region_context_menu;
1544                 }
1545                 break;
1546
1547         case SelectionItem:
1548                 if (with_selection) {
1549                         build_menu_function = &Editor::build_track_selection_context_menu;
1550                 } else {
1551                         build_menu_function = &Editor::build_track_context_menu;
1552                 }
1553                 break;
1554
1555         case StreamItem:
1556                 if (clicked_routeview->track()) {
1557                         build_menu_function = &Editor::build_track_context_menu;
1558                 } else {
1559                         build_menu_function = &Editor::build_track_bus_context_menu;
1560                 }
1561                 break;
1562
1563         default:
1564                 /* probably shouldn't happen but if it does, we don't care */
1565                 return;
1566         }
1567
1568         menu = (this->*build_menu_function)();
1569         menu->set_name ("ArdourContextMenu");
1570
1571         /* now handle specific situations */
1572
1573         switch (item_type) {
1574         case RegionItem:
1575         case RegionViewName:
1576         case RegionViewNameHighlight:
1577         case LeftFrameHandle:
1578         case RightFrameHandle:
1579                 if (!with_selection) {
1580                         if (region_edit_menu_split_item) {
1581                                 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1582                                         ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1583                                 } else {
1584                                         ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1585                                 }
1586                         }
1587                         if (region_edit_menu_split_multichannel_item) {
1588                                 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1589                                         region_edit_menu_split_multichannel_item->set_sensitive (true);
1590                                 } else {
1591                                         region_edit_menu_split_multichannel_item->set_sensitive (false);
1592                                 }
1593                         }
1594                 }
1595                 break;
1596
1597         case SelectionItem:
1598                 break;
1599
1600         case StreamItem:
1601                 break;
1602
1603         default:
1604                 /* probably shouldn't happen but if it does, we don't care */
1605                 return;
1606         }
1607
1608         if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1609
1610                 /* Bounce to disk */
1611
1612                 using namespace Menu_Helpers;
1613                 MenuList& edit_items  = menu->items();
1614
1615                 edit_items.push_back (SeparatorElem());
1616
1617                 switch (clicked_routeview->audio_track()->freeze_state()) {
1618                 case AudioTrack::NoFreeze:
1619                         edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1620                         break;
1621
1622                 case AudioTrack::Frozen:
1623                         edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1624                         break;
1625
1626                 case AudioTrack::UnFrozen:
1627                         edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1628                         break;
1629                 }
1630
1631         }
1632
1633         if (item_type == StreamItem && clicked_routeview) {
1634                 clicked_routeview->build_underlay_menu(menu);
1635         }
1636
1637         /* When the region menu is opened, we setup the actions so that they look right
1638            in the menu.
1639         */
1640         sensitize_the_right_region_actions ();
1641         _last_region_menu_was_main = false;
1642
1643         menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1644         menu->popup (button, time);
1645 }
1646
1647 Menu*
1648 Editor::build_track_context_menu ()
1649 {
1650         using namespace Menu_Helpers;
1651
1652         MenuList& edit_items = track_context_menu.items();
1653         edit_items.clear();
1654
1655         add_dstream_context_items (edit_items);
1656         return &track_context_menu;
1657 }
1658
1659 Menu*
1660 Editor::build_track_bus_context_menu ()
1661 {
1662         using namespace Menu_Helpers;
1663
1664         MenuList& edit_items = track_context_menu.items();
1665         edit_items.clear();
1666
1667         add_bus_context_items (edit_items);
1668         return &track_context_menu;
1669 }
1670
1671 Menu*
1672 Editor::build_track_region_context_menu ()
1673 {
1674         using namespace Menu_Helpers;
1675         MenuList& edit_items  = track_region_context_menu.items();
1676         edit_items.clear();
1677
1678         /* we've just cleared the track region context menu, so the menu that these
1679            two items were on will have disappeared; stop them dangling.
1680         */
1681         region_edit_menu_split_item = 0;
1682         region_edit_menu_split_multichannel_item = 0;
1683
1684         RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1685
1686         if (rtv) {
1687                 boost::shared_ptr<Track> tr;
1688                 boost::shared_ptr<Playlist> pl;
1689
1690                 if ((tr = rtv->track())) {
1691                         add_region_context_items (edit_items, tr);
1692                 }
1693         }
1694
1695         add_dstream_context_items (edit_items);
1696
1697         return &track_region_context_menu;
1698 }
1699
1700 void
1701 Editor::analyze_region_selection ()
1702 {
1703         if (analysis_window == 0) {
1704                 analysis_window = new AnalysisWindow();
1705
1706                 if (_session != 0)
1707                         analysis_window->set_session(_session);
1708
1709                 analysis_window->show_all();
1710         }
1711
1712         analysis_window->set_regionmode();
1713         analysis_window->analyze();
1714
1715         analysis_window->present();
1716 }
1717
1718 void
1719 Editor::analyze_range_selection()
1720 {
1721         if (analysis_window == 0) {
1722                 analysis_window = new AnalysisWindow();
1723
1724                 if (_session != 0)
1725                         analysis_window->set_session(_session);
1726
1727                 analysis_window->show_all();
1728         }
1729
1730         analysis_window->set_rangemode();
1731         analysis_window->analyze();
1732
1733         analysis_window->present();
1734 }
1735
1736 Menu*
1737 Editor::build_track_selection_context_menu ()
1738 {
1739         using namespace Menu_Helpers;
1740         MenuList& edit_items  = track_selection_context_menu.items();
1741         edit_items.clear ();
1742
1743         add_selection_context_items (edit_items);
1744         // edit_items.push_back (SeparatorElem());
1745         // add_dstream_context_items (edit_items);
1746
1747         return &track_selection_context_menu;
1748 }
1749
1750 void
1751 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1752 {
1753         using namespace Menu_Helpers;
1754
1755         /* OK, stick the region submenu at the top of the list, and then add
1756            the standard items.
1757         */
1758
1759         RegionSelection rs = get_regions_from_selection_and_entered ();
1760
1761         string::size_type pos = 0;
1762         string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1763
1764         /* we have to hack up the region name because "_" has a special
1765            meaning for menu titles.
1766         */
1767
1768         while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1769                 menu_item_name.replace (pos, 1, "__");
1770                 pos += 2;
1771         }
1772
1773         if (_popup_region_menu_item == 0) {
1774                 _popup_region_menu_item = new MenuItem (menu_item_name);
1775                 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1776                 _popup_region_menu_item->show ();
1777         } else {
1778                 _popup_region_menu_item->set_label (menu_item_name);
1779         }
1780
1781         const framepos_t position = get_preferred_edit_position (false, true);
1782
1783         edit_items.push_back (*_popup_region_menu_item);
1784         if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1785                 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1786         }
1787         edit_items.push_back (SeparatorElem());
1788 }
1789
1790 /** Add context menu items relevant to selection ranges.
1791  * @param edit_items List to add the items to.
1792  */
1793 void
1794 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1795 {
1796         using namespace Menu_Helpers;
1797
1798         edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1799         edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1800
1801         edit_items.push_back (SeparatorElem());
1802         edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1803
1804         edit_items.push_back (SeparatorElem());
1805         edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1806
1807         edit_items.push_back (SeparatorElem());
1808
1809         edit_items.push_back (
1810                 MenuElem (
1811                         _("Move Range Start to Previous Region Boundary"),
1812                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1813                         )
1814                 );
1815
1816         edit_items.push_back (
1817                 MenuElem (
1818                         _("Move Range Start to Next Region Boundary"),
1819                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1820                         )
1821                 );
1822
1823         edit_items.push_back (
1824                 MenuElem (
1825                         _("Move Range End to Previous Region Boundary"),
1826                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1827                         )
1828                 );
1829
1830         edit_items.push_back (
1831                 MenuElem (
1832                         _("Move Range End to Next Region Boundary"),
1833                         sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1834                         )
1835                 );
1836
1837         edit_items.push_back (SeparatorElem());
1838         edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1839         edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1840
1841         edit_items.push_back (SeparatorElem());
1842         edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1843
1844         edit_items.push_back (SeparatorElem());
1845         edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1846         edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1847
1848         edit_items.push_back (SeparatorElem());
1849         edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1850
1851         edit_items.push_back (SeparatorElem());
1852         edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1853         edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1854         edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1855
1856         edit_items.push_back (SeparatorElem());
1857         edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1858         edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1859         edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1860         edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1861         edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1862         if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1863                 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1864         }
1865 }
1866
1867
1868 void
1869 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1870 {
1871         using namespace Menu_Helpers;
1872
1873         /* Playback */
1874
1875         Menu *play_menu = manage (new Menu);
1876         MenuList& play_items = play_menu->items();
1877         play_menu->set_name ("ArdourContextMenu");
1878
1879         play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1880         play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1881         play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1882         play_items.push_back (SeparatorElem());
1883         play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1884
1885         edit_items.push_back (MenuElem (_("Play"), *play_menu));
1886
1887         /* Selection */
1888
1889         Menu *select_menu = manage (new Menu);
1890         MenuList& select_items = select_menu->items();
1891         select_menu->set_name ("ArdourContextMenu");
1892
1893         select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1894         select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1895         select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1896         select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1897         select_items.push_back (SeparatorElem());
1898         select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1899         select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1900         select_items.push_back (SeparatorElem());
1901         select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1902         select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1903         select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1904         select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1905         select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1906         select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1907         select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1908
1909         edit_items.push_back (MenuElem (_("Select"), *select_menu));
1910
1911         /* Cut-n-Paste */
1912
1913         Menu *cutnpaste_menu = manage (new Menu);
1914         MenuList& cutnpaste_items = cutnpaste_menu->items();
1915         cutnpaste_menu->set_name ("ArdourContextMenu");
1916
1917         cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1918         cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1919         cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1920
1921         cutnpaste_items.push_back (SeparatorElem());
1922
1923         cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1924         cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1925
1926         edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1927
1928         /* Adding new material */
1929
1930         edit_items.push_back (SeparatorElem());
1931         edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1932         edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1933
1934         /* Nudge track */
1935
1936         Menu *nudge_menu = manage (new Menu());
1937         MenuList& nudge_items = nudge_menu->items();
1938         nudge_menu->set_name ("ArdourContextMenu");
1939
1940         edit_items.push_back (SeparatorElem());
1941         nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1942         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1943         nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1944         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1945
1946         edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1947 }
1948
1949 void
1950 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1951 {
1952         using namespace Menu_Helpers;
1953
1954         /* Playback */
1955
1956         Menu *play_menu = manage (new Menu);
1957         MenuList& play_items = play_menu->items();
1958         play_menu->set_name ("ArdourContextMenu");
1959
1960         play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1961         play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1962         edit_items.push_back (MenuElem (_("Play"), *play_menu));
1963
1964         /* Selection */
1965
1966         Menu *select_menu = manage (new Menu);
1967         MenuList& select_items = select_menu->items();
1968         select_menu->set_name ("ArdourContextMenu");
1969
1970         select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1971         select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1972         select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1973         select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1974         select_items.push_back (SeparatorElem());
1975         select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1976         select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1977         select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1978         select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1979
1980         edit_items.push_back (MenuElem (_("Select"), *select_menu));
1981
1982         /* Cut-n-Paste */
1983
1984         Menu *cutnpaste_menu = manage (new Menu);
1985         MenuList& cutnpaste_items = cutnpaste_menu->items();
1986         cutnpaste_menu->set_name ("ArdourContextMenu");
1987
1988         cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1989         cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1990         cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1991
1992         Menu *nudge_menu = manage (new Menu());
1993         MenuList& nudge_items = nudge_menu->items();
1994         nudge_menu->set_name ("ArdourContextMenu");
1995
1996         edit_items.push_back (SeparatorElem());
1997         nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1998         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1999         nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2000         nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2001
2002         edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2003 }
2004
2005 SnapType
2006 Editor::snap_type() const
2007 {
2008         return _snap_type;
2009 }
2010
2011 SnapMode
2012 Editor::snap_mode() const
2013 {
2014         return _snap_mode;
2015 }
2016
2017 void
2018 Editor::set_snap_to (SnapType st)
2019 {
2020         unsigned int snap_ind = (unsigned int)st;
2021
2022         _snap_type = st;
2023
2024         if (snap_ind > snap_type_strings.size() - 1) {
2025                 snap_ind = 0;
2026                 _snap_type = (SnapType)snap_ind;
2027         }
2028
2029         string str = snap_type_strings[snap_ind];
2030
2031         if (str != snap_type_selector.get_text()) {
2032                 snap_type_selector.set_text (str);
2033         }
2034
2035         instant_save ();
2036
2037         switch (_snap_type) {
2038         case SnapToBeatDiv128:
2039         case SnapToBeatDiv64:
2040         case SnapToBeatDiv32:
2041         case SnapToBeatDiv28:
2042         case SnapToBeatDiv24:
2043         case SnapToBeatDiv20:
2044         case SnapToBeatDiv16:
2045         case SnapToBeatDiv14:
2046         case SnapToBeatDiv12:
2047         case SnapToBeatDiv10:
2048         case SnapToBeatDiv8:
2049         case SnapToBeatDiv7:
2050         case SnapToBeatDiv6:
2051         case SnapToBeatDiv5:
2052         case SnapToBeatDiv4:
2053         case SnapToBeatDiv3:
2054         case SnapToBeatDiv2: {
2055                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2056                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2057                 
2058                 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2059                                             current_bbt_points_begin, current_bbt_points_end);
2060                 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2061                                          current_bbt_points_begin, current_bbt_points_end);
2062                 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2063                 break;
2064         }
2065
2066         case SnapToRegionStart:
2067         case SnapToRegionEnd:
2068         case SnapToRegionSync:
2069         case SnapToRegionBoundary:
2070                 build_region_boundary_cache ();
2071                 break;
2072
2073         default:
2074                 /* relax */
2075                 break;
2076         }
2077
2078         SnapChanged (); /* EMIT SIGNAL */
2079 }
2080
2081 void
2082 Editor::set_snap_mode (SnapMode mode)
2083 {
2084         string str = snap_mode_strings[(int)mode];
2085
2086         if (_internal_editing) {
2087                 internal_snap_mode = mode;
2088         } else {
2089                 pre_internal_snap_mode = mode;
2090         }
2091
2092         _snap_mode = mode;
2093
2094         if (str != snap_mode_selector.get_text ()) {
2095                 snap_mode_selector.set_text (str);
2096         }
2097
2098         instant_save ();
2099 }
2100 void
2101 Editor::set_edit_point_preference (EditPoint ep, bool force)
2102 {
2103         bool changed = (_edit_point != ep);
2104
2105         _edit_point = ep;
2106         string str = edit_point_strings[(int)ep];
2107
2108         if (Profile->get_mixbus())
2109                 if (ep == EditAtSelectedMarker)
2110                         ep = EditAtPlayhead;
2111         
2112         if (str != edit_point_selector.get_text ()) {
2113                 edit_point_selector.set_text (str);
2114         }
2115
2116         reset_canvas_cursor ();
2117
2118         if (!force && !changed) {
2119                 return;
2120         }
2121
2122         const char* action=NULL;
2123
2124         switch (_edit_point) {
2125         case EditAtPlayhead:
2126                 action = "edit-at-playhead";
2127                 break;
2128         case EditAtSelectedMarker:
2129                 action = "edit-at-marker";
2130                 break;
2131         case EditAtMouse:
2132                 action = "edit-at-mouse";
2133                 break;
2134         }
2135
2136         Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2137         if (act) {
2138                 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2139         }
2140
2141         framepos_t foo;
2142         bool in_track_canvas;
2143
2144         if (!mouse_frame (foo, in_track_canvas)) {
2145                 in_track_canvas = false;
2146         }
2147
2148         reset_canvas_action_sensitivity (in_track_canvas);
2149
2150         instant_save ();
2151 }
2152
2153 int
2154 Editor::set_state (const XMLNode& node, int /*version*/)
2155 {
2156         const XMLProperty* prop;
2157         XMLNode* geometry;
2158         int x, y;
2159         Gdk::Geometry g;
2160
2161         set_id (node);
2162
2163         g.base_width = default_width;
2164         g.base_height = default_height;
2165         x = 1;
2166         y = 1;
2167
2168         if ((geometry = find_named_node (node, "geometry")) != 0) {
2169
2170                 XMLProperty* prop;
2171
2172                 if ((prop = geometry->property("x_size")) == 0) {
2173                         prop = geometry->property ("x-size");
2174                 }
2175                 if (prop) {
2176                         g.base_width = atoi(prop->value());
2177                 }
2178                 if ((prop = geometry->property("y_size")) == 0) {
2179                         prop = geometry->property ("y-size");
2180                 }
2181                 if (prop) {
2182                         g.base_height = atoi(prop->value());
2183                 }
2184
2185                 if ((prop = geometry->property ("x_pos")) == 0) {
2186                         prop = geometry->property ("x-pos");
2187                 }
2188                 if (prop) {
2189                         x = atoi (prop->value());
2190
2191                 }
2192                 if ((prop = geometry->property ("y_pos")) == 0) {
2193                         prop = geometry->property ("y-pos");
2194                 }
2195                 if (prop) {
2196                         y = atoi (prop->value());
2197                 }
2198         }
2199
2200         set_default_size (g.base_width, g.base_height);
2201         move (x, y);
2202
2203         if (_session && (prop = node.property ("playhead"))) {
2204                 framepos_t pos;
2205                 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2206                 playhead_cursor->set_position (pos);
2207         } else {
2208                 playhead_cursor->set_position (0);
2209         }
2210
2211         if ((prop = node.property ("mixer-width"))) {
2212                 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2213         }
2214
2215         if ((prop = node.property ("zoom-focus"))) {
2216                 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2217         }
2218
2219         if ((prop = node.property ("zoom"))) {
2220                 /* older versions of ardour used floating point samples_per_pixel */
2221                 double f = PBD::atof (prop->value());
2222                 reset_zoom (llrintf (f));
2223         } else {
2224                 reset_zoom (samples_per_pixel);
2225         }
2226
2227         if ((prop = node.property ("visible-track-count"))) {
2228                 set_visible_track_count (PBD::atoi (prop->value()));
2229         }
2230
2231         if ((prop = node.property ("snap-to"))) {
2232                 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2233         }
2234
2235         if ((prop = node.property ("snap-mode"))) {
2236                 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2237         }
2238
2239         if ((prop = node.property ("internal-snap-to"))) {
2240                 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2241         }
2242
2243         if ((prop = node.property ("internal-snap-mode"))) {
2244                 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2245         }
2246
2247         if ((prop = node.property ("pre-internal-snap-to"))) {
2248                 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2249         }
2250
2251
2252         if ((prop = node.property ("pre-internal-snap-mode"))) {
2253                 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2254         }
2255
2256         if ((prop = node.property ("mouse-mode"))) {
2257                 MouseMode m = str2mousemode(prop->value());
2258                 set_mouse_mode (m, true);
2259         } else {
2260                 set_mouse_mode (MouseObject, true);
2261         }
2262
2263         if ((prop = node.property ("left-frame")) != 0) {
2264                 framepos_t pos;
2265                 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2266                         if (pos < 0) {
2267                                 pos = 0;
2268                         }
2269                         reset_x_origin (pos);
2270                 }
2271         }
2272
2273         if ((prop = node.property ("y-origin")) != 0) {
2274                 reset_y_origin (atof (prop->value ()));
2275         }
2276
2277         if ((prop = node.property ("internal-edit"))) {
2278                 bool yn = string_is_affirmative (prop->value());
2279                 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2280                 if (act) {
2281                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2282                         tact->set_active (!yn);
2283                         tact->set_active (yn);
2284                 }
2285         }
2286
2287         if ((prop = node.property ("join-object-range"))) {
2288                 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2289                 bool yn = string_is_affirmative (prop->value());
2290                 if (act) {
2291                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2292                         tact->set_active (!yn);
2293                         tact->set_active (yn);
2294                 }
2295                 set_mouse_mode(mouse_mode, true);
2296         }
2297
2298         if ((prop = node.property ("edit-point"))) {
2299                 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2300         }
2301
2302         if ((prop = node.property ("show-measures"))) {
2303                 bool yn = string_is_affirmative (prop->value());
2304                 _show_measures = yn;
2305                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2306                 if (act) {
2307                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2308                         /* do it twice to force the change */
2309                         tact->set_active (!yn);
2310                         tact->set_active (yn);
2311                 }
2312         }
2313
2314         if ((prop = node.property ("follow-playhead"))) {
2315                 bool yn = string_is_affirmative (prop->value());
2316                 set_follow_playhead (yn);
2317                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2318                 if (act) {
2319                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2320                         if (tact->get_active() != yn) {
2321                                 tact->set_active (yn);
2322                         }
2323                 }
2324         }
2325
2326         if ((prop = node.property ("stationary-playhead"))) {
2327                 bool yn = string_is_affirmative (prop->value());
2328                 set_stationary_playhead (yn);
2329                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2330                 if (act) {
2331                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2332                         if (tact->get_active() != yn) {
2333                                 tact->set_active (yn);
2334                         }
2335                 }
2336         }
2337
2338         if ((prop = node.property ("region-list-sort-type"))) {
2339                 RegionListSortType st;
2340                 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2341         }
2342
2343         if ((prop = node.property ("show-editor-mixer"))) {
2344
2345                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2346                 assert (act);
2347
2348                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2349                 bool yn = string_is_affirmative (prop->value());
2350
2351                 /* do it twice to force the change */
2352
2353                 tact->set_active (!yn);
2354                 tact->set_active (yn);
2355         }
2356
2357         if ((prop = node.property ("show-editor-list"))) {
2358
2359                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2360                 assert (act);
2361
2362                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2363                 bool yn = string_is_affirmative (prop->value());
2364
2365                 /* do it twice to force the change */
2366
2367                 tact->set_active (!yn);
2368                 tact->set_active (yn);
2369         }
2370
2371         if ((prop = node.property (X_("editor-list-page")))) {
2372                 _the_notebook.set_current_page (atoi (prop->value ()));
2373         }
2374
2375         if ((prop = node.property (X_("show-marker-lines")))) {
2376                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2377                 assert (act);
2378                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2379                 bool yn = string_is_affirmative (prop->value ());
2380
2381                 tact->set_active (!yn);
2382                 tact->set_active (yn);
2383         }
2384
2385         XMLNodeList children = node.children ();
2386         for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2387                 selection->set_state (**i, Stateful::current_state_version);
2388                 _regions->set_state (**i);
2389         }
2390
2391         if ((prop = node.property ("maximised"))) {
2392                 bool yn = string_is_affirmative (prop->value());
2393                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2394                 assert (act);
2395                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2396                 bool fs = tact && tact->get_active();
2397                 if (yn ^ fs) {
2398                         ActionManager::do_action ("Common", "ToggleMaximalEditor");
2399                 }
2400         }
2401
2402         if ((prop = node.property ("nudge-clock-value"))) {
2403                 framepos_t f;
2404                 sscanf (prop->value().c_str(), "%" PRId64, &f);
2405                 nudge_clock->set (f);
2406         } else {
2407                 nudge_clock->set_mode (AudioClock::Timecode);
2408                 nudge_clock->set (_session->frame_rate() * 5, true);
2409         }
2410
2411         return 0;
2412 }
2413
2414 XMLNode&
2415 Editor::get_state ()
2416 {
2417         XMLNode* node = new XMLNode ("Editor");
2418         char buf[32];
2419
2420         id().print (buf, sizeof (buf));
2421         node->add_property ("id", buf);
2422
2423         if (is_realized()) {
2424                 Glib::RefPtr<Gdk::Window> win = get_window();
2425
2426                 int x, y, width, height;
2427                 win->get_root_origin(x, y);
2428                 win->get_size(width, height);
2429
2430                 XMLNode* geometry = new XMLNode ("geometry");
2431
2432                 snprintf(buf, sizeof(buf), "%d", width);
2433                 geometry->add_property("x-size", string(buf));
2434                 snprintf(buf, sizeof(buf), "%d", height);
2435                 geometry->add_property("y-size", string(buf));
2436                 snprintf(buf, sizeof(buf), "%d", x);
2437                 geometry->add_property("x-pos", string(buf));
2438                 snprintf(buf, sizeof(buf), "%d", y);
2439                 geometry->add_property("y-pos", string(buf));
2440                 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2441                 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2442                 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2443                 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2444                 geometry->add_property("edit-vertical-pane-pos", string(buf));
2445
2446                 node->add_child_nocopy (*geometry);
2447         }
2448
2449         maybe_add_mixer_strip_width (*node);
2450
2451         node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2452
2453         snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2454         node->add_property ("zoom", buf);
2455         node->add_property ("snap-to", enum_2_string (_snap_type));
2456         node->add_property ("snap-mode", enum_2_string (_snap_mode));
2457         node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2458         node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2459         node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2460         node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2461         node->add_property ("edit-point", enum_2_string (_edit_point));
2462         snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2463         node->add_property ("visible-track-count", buf);
2464
2465         snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2466         node->add_property ("playhead", buf);
2467         snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2468         node->add_property ("left-frame", buf);
2469         snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2470         node->add_property ("y-origin", buf);
2471
2472         node->add_property ("show-measures", _show_measures ? "yes" : "no");
2473         node->add_property ("maximised", _maximised ? "yes" : "no");
2474         node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2475         node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2476         node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2477         node->add_property ("mouse-mode", enum2str(mouse_mode));
2478         node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2479         node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2480
2481         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2482         if (act) {
2483                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2484                 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2485         }
2486
2487         act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2488         if (act) {
2489                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2490                 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2491         }
2492
2493         snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2494         node->add_property (X_("editor-list-page"), buf);
2495
2496         if (button_bindings) {
2497                 XMLNode* bb = new XMLNode (X_("Buttons"));
2498                 button_bindings->save (*bb);
2499                 node->add_child_nocopy (*bb);
2500         }
2501
2502         node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2503
2504         node->add_child_nocopy (selection->get_state ());
2505         node->add_child_nocopy (_regions->get_state ());
2506
2507         snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2508         node->add_property ("nudge-clock-value", buf);
2509
2510         return *node;
2511 }
2512
2513 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2514  *  if @param trackview_relative_offset is false, @param y y is a global canvas *  coordinate, in pixel units
2515  *
2516  *  @return pair: TimeAxisView that y is over, layer index.
2517  *
2518  *  TimeAxisView may be 0.  Layer index is the layer number if the TimeAxisView is valid and is
2519  *  in stacked or expanded region display mode, otherwise 0.
2520  */
2521 std::pair<TimeAxisView *, double>
2522 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2523 {
2524         if (!trackview_relative_offset) {
2525                 y -= _trackview_group->canvas_origin().y;
2526         }
2527
2528         if (y < 0) {
2529                 return std::make_pair ( (TimeAxisView *) 0, 0);
2530         }
2531
2532         for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2533                         
2534                 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2535                         
2536                 if (r.first) {
2537                         return r;
2538                 }
2539         }
2540
2541         return std::make_pair ( (TimeAxisView *) 0, 0);
2542 }
2543
2544 /** Snap a position to the grid, if appropriate, taking into account current
2545  *  grid settings and also the state of any snap modifier keys that may be pressed.
2546  *  @param start Position to snap.
2547  *  @param event Event to get current key modifier information from, or 0.
2548  */
2549 void
2550 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2551 {
2552         if (!_session || !event) {
2553                 return;
2554         }
2555
2556         if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2557                 if (_snap_mode == SnapOff) {
2558                         snap_to_internal (start, direction, for_mark);
2559                 }
2560         } else {
2561                 if (_snap_mode != SnapOff) {
2562                         snap_to_internal (start, direction, for_mark);
2563                 }
2564         }
2565 }
2566
2567 void
2568 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2569 {
2570         if (!_session || _snap_mode == SnapOff) {
2571                 return;
2572         }
2573
2574         snap_to_internal (start, direction, for_mark);
2575 }
2576
2577 void
2578 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2579 {
2580         const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2581         framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2582
2583         switch (_snap_type) {
2584         case SnapToTimecodeFrame:
2585                 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2586                         start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2587                 } else {
2588                         start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) *  _session->frames_per_timecode_frame());
2589                 }
2590                 break;
2591
2592         case SnapToTimecodeSeconds:
2593                 if (_session->config.get_timecode_offset_negative()) {
2594                         start += _session->config.get_timecode_offset ();
2595                 } else {
2596                         start -= _session->config.get_timecode_offset ();
2597                 }
2598                 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2599                         start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2600                 } else {
2601                         start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2602                 }
2603
2604                 if (_session->config.get_timecode_offset_negative()) {
2605                         start -= _session->config.get_timecode_offset ();
2606                 } else {
2607                         start += _session->config.get_timecode_offset ();
2608                 }
2609                 break;
2610
2611         case SnapToTimecodeMinutes:
2612                 if (_session->config.get_timecode_offset_negative()) {
2613                         start += _session->config.get_timecode_offset ();
2614                 } else {
2615                         start -= _session->config.get_timecode_offset ();
2616                 }
2617                 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2618                         start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2619                 } else {
2620                         start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2621                 }
2622                 if (_session->config.get_timecode_offset_negative()) {
2623                         start -= _session->config.get_timecode_offset ();
2624                 } else {
2625                         start += _session->config.get_timecode_offset ();
2626                 }
2627                 break;
2628         default:
2629                 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2630                 /*NOTREACHED*/
2631         }
2632 }
2633
2634 void
2635 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2636 {
2637         const framepos_t one_second = _session->frame_rate();
2638         const framepos_t one_minute = _session->frame_rate() * 60;
2639         framepos_t presnap = start;
2640         framepos_t before;
2641         framepos_t after;
2642
2643         switch (_snap_type) {
2644         case SnapToTimecodeFrame:
2645         case SnapToTimecodeSeconds:
2646         case SnapToTimecodeMinutes:
2647                 return timecode_snap_to_internal (start, direction, for_mark);
2648
2649         case SnapToCDFrame:
2650                 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2651                         start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2652                 } else {
2653                         start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2654                 }
2655                 break;
2656
2657         case SnapToSeconds:
2658                 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2659                         start = (framepos_t) ceil ((double) start / one_second) * one_second;
2660                 } else {
2661                         start = (framepos_t) floor ((double) start / one_second) * one_second;
2662                 }
2663                 break;
2664
2665         case SnapToMinutes:
2666                 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2667                         start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2668                 } else {
2669                         start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2670                 }
2671                 break;
2672
2673         case SnapToBar:
2674                 start = _session->tempo_map().round_to_bar (start, direction);
2675                 break;
2676
2677         case SnapToBeat:
2678                 start = _session->tempo_map().round_to_beat (start, direction);
2679                 break;
2680
2681         case SnapToBeatDiv128:
2682                 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2683                 break;
2684         case SnapToBeatDiv64:
2685                 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2686                 break;
2687         case SnapToBeatDiv32:
2688                 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2689                 break;
2690         case SnapToBeatDiv28:
2691                 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2692                 break;
2693         case SnapToBeatDiv24:
2694                 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2695                 break;
2696         case SnapToBeatDiv20:
2697                 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2698                 break;
2699         case SnapToBeatDiv16:
2700                 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2701                 break;
2702         case SnapToBeatDiv14:
2703                 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2704                 break;
2705         case SnapToBeatDiv12:
2706                 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2707                 break;
2708         case SnapToBeatDiv10:
2709                 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2710                 break;
2711         case SnapToBeatDiv8:
2712                 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2713                 break;
2714         case SnapToBeatDiv7:
2715                 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2716                 break;
2717         case SnapToBeatDiv6:
2718                 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2719                 break;
2720         case SnapToBeatDiv5:
2721                 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2722                 break;
2723         case SnapToBeatDiv4:
2724                 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2725                 break;
2726         case SnapToBeatDiv3:
2727                 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2728                 break;
2729         case SnapToBeatDiv2:
2730                 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2731                 break;
2732
2733         case SnapToMark:
2734                 if (for_mark) {
2735                         return;
2736                 }
2737
2738                 _session->locations()->marks_either_side (start, before, after);
2739
2740                 if (before == max_framepos && after == max_framepos) {
2741                         /* No marks to snap to, so just don't snap */
2742                         return;
2743                 } else if (before == max_framepos) {
2744                         start = after;
2745                 } else if (after == max_framepos) {
2746                         start = before;
2747                 } else if (before != max_framepos && after != max_framepos) {
2748                         /* have before and after */
2749                         if ((start - before) < (after - start)) {
2750                                 start = before;
2751                         } else {
2752                                 start = after;
2753                         }
2754                 }
2755
2756                 break;
2757
2758         case SnapToRegionStart:
2759         case SnapToRegionEnd:
2760         case SnapToRegionSync:
2761         case SnapToRegionBoundary:
2762                 if (!region_boundary_cache.empty()) {
2763
2764                         vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2765                         vector<framepos_t>::iterator next = region_boundary_cache.end ();
2766
2767                         if (direction > 0) {
2768                                 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2769                         } else {
2770                                 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2771                         }
2772
2773                         if (next != region_boundary_cache.begin ()) {
2774                                 prev = next;
2775                                 prev--;
2776                         }
2777
2778                         framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2779                         framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2780
2781                         if (start > (p + n) / 2) {
2782                                 start = n;
2783                         } else {
2784                                 start = p;
2785                         }
2786                 }
2787                 break;
2788         }
2789
2790         switch (_snap_mode) {
2791         case SnapNormal:
2792                 return;
2793
2794         case SnapMagnetic:
2795
2796                 if (presnap > start) {
2797                         if (presnap > (start + pixel_to_sample(snap_threshold))) {
2798                                 start = presnap;
2799                         }
2800
2801                 } else if (presnap < start) {
2802                         if (presnap < (start - pixel_to_sample(snap_threshold))) {
2803                                 start = presnap;
2804                         }
2805                 }
2806
2807         default:
2808                 /* handled at entry */
2809                 return;
2810
2811         }
2812 }
2813
2814
2815 void
2816 Editor::setup_toolbar ()
2817 {
2818         HBox* mode_box = manage(new HBox);
2819         mode_box->set_border_width (2);
2820         mode_box->set_spacing(2);
2821
2822         HBox* mouse_mode_box = manage (new HBox);
2823         HBox* mouse_mode_hbox = manage (new HBox);
2824         VBox* mouse_mode_vbox = manage (new VBox);
2825         Alignment* mouse_mode_align = manage (new Alignment);
2826
2827         Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2828         mouse_mode_size_group->add_widget (smart_mode_button);
2829         mouse_mode_size_group->add_widget (mouse_move_button);
2830         mouse_mode_size_group->add_widget (mouse_cut_button);
2831         mouse_mode_size_group->add_widget (mouse_select_button);
2832         mouse_mode_size_group->add_widget (mouse_zoom_button);
2833         mouse_mode_size_group->add_widget (mouse_gain_button);
2834         mouse_mode_size_group->add_widget (mouse_timefx_button);
2835         mouse_mode_size_group->add_widget (mouse_audition_button);
2836         mouse_mode_size_group->add_widget (mouse_draw_button);
2837         mouse_mode_size_group->add_widget (internal_edit_button);
2838
2839         mouse_mode_size_group->add_widget (zoom_in_button);
2840         mouse_mode_size_group->add_widget (zoom_out_button);
2841         mouse_mode_size_group->add_widget (zoom_preset_selector);
2842         mouse_mode_size_group->add_widget (zoom_out_full_button);
2843         mouse_mode_size_group->add_widget (zoom_focus_selector);
2844
2845         mouse_mode_size_group->add_widget (tav_shrink_button);
2846         mouse_mode_size_group->add_widget (tav_expand_button);
2847         mouse_mode_size_group->add_widget (visible_tracks_selector);
2848
2849         mouse_mode_size_group->add_widget (snap_type_selector);
2850         mouse_mode_size_group->add_widget (snap_mode_selector);
2851
2852         mouse_mode_size_group->add_widget (edit_point_selector);
2853         mouse_mode_size_group->add_widget (edit_mode_selector);
2854
2855         mouse_mode_size_group->add_widget (*nudge_clock);
2856         mouse_mode_size_group->add_widget (nudge_forward_button);
2857         mouse_mode_size_group->add_widget (nudge_backward_button);
2858
2859         mouse_mode_hbox->set_spacing (2);
2860
2861         if (!ARDOUR::Profile->get_trx()) {
2862                 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2863         }
2864
2865         mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2866         mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2867
2868         if (!ARDOUR::Profile->get_mixbus()) {
2869                 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2870                 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2871         }
2872         
2873         if (!ARDOUR::Profile->get_trx()) {
2874                 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2875                 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2876                 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2877                 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2878                 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 0);
2879         }
2880
2881         mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2882
2883         mouse_mode_align->add (*mouse_mode_vbox);
2884         mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2885
2886         mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2887
2888         edit_mode_selector.set_name ("mouse mode button");
2889
2890         if (!ARDOUR::Profile->get_trx()) {
2891                 mode_box->pack_start (edit_mode_selector, false, false);
2892         }
2893         mode_box->pack_start (*mouse_mode_box, false, false);
2894
2895         _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2896         _mouse_mode_tearoff->set_name ("MouseModeBase");
2897         _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2898
2899         if (Profile->get_sae() || Profile->get_mixbus() ) {
2900                 _mouse_mode_tearoff->set_can_be_torn_off (false);
2901         }
2902
2903         _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2904                                                          &_mouse_mode_tearoff->tearoff_window()));
2905         _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2906                                                          &_mouse_mode_tearoff->tearoff_window(), 1));
2907         _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2908                                                          &_mouse_mode_tearoff->tearoff_window()));
2909         _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2910                                                           &_mouse_mode_tearoff->tearoff_window(), 1));
2911
2912         /* Zoom */
2913
2914         _zoom_box.set_spacing (2);
2915         _zoom_box.set_border_width (2);
2916
2917         RefPtr<Action> act;
2918
2919         zoom_preset_selector.set_name ("zoom button");
2920         zoom_preset_selector.set_image(::get_icon ("time_exp"));
2921         zoom_preset_selector.set_size_request (42, -1);
2922
2923         zoom_in_button.set_name ("zoom button");
2924         zoom_in_button.set_image(::get_icon ("zoom_in"));
2925         act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2926         zoom_in_button.set_related_action (act);
2927
2928         zoom_out_button.set_name ("zoom button");
2929         zoom_out_button.set_image(::get_icon ("zoom_out"));
2930         act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2931         zoom_out_button.set_related_action (act);
2932
2933         zoom_out_full_button.set_name ("zoom button");
2934         zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2935         act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2936         zoom_out_full_button.set_related_action (act);
2937
2938         zoom_focus_selector.set_name ("zoom button");
2939
2940         if (ARDOUR::Profile->get_mixbus()) {
2941                 _zoom_box.pack_start (zoom_preset_selector, false, false);
2942         } else if (ARDOUR::Profile->get_trx()) {
2943                 mode_box->pack_start (zoom_out_button, false, false);
2944                 mode_box->pack_start (zoom_in_button, false, false);
2945         } else {
2946                 _zoom_box.pack_start (zoom_out_button, false, false);
2947                 _zoom_box.pack_start (zoom_in_button, false, false);
2948                 _zoom_box.pack_start (zoom_out_full_button, false, false);
2949                 _zoom_box.pack_start (zoom_focus_selector, false, false);
2950         }
2951
2952         /* Track zoom buttons */
2953         visible_tracks_selector.set_name ("zoom button");
2954         if (Profile->get_mixbus()) {
2955                 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2956                 visible_tracks_selector.set_size_request (42, -1);
2957         } else {
2958                 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
2959         }
2960
2961         tav_expand_button.set_name ("zoom button");
2962         tav_expand_button.set_image(::get_icon ("tav_exp"));
2963         act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2964         tav_expand_button.set_related_action (act);
2965
2966         tav_shrink_button.set_name ("zoom button");
2967         tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2968         act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2969         tav_shrink_button.set_related_action (act);
2970
2971         if (ARDOUR::Profile->get_mixbus()) {
2972                 _zoom_box.pack_start (visible_tracks_selector);
2973         } else if (ARDOUR::Profile->get_trx()) {
2974                 _zoom_box.pack_start (tav_shrink_button);
2975                 _zoom_box.pack_start (tav_expand_button);
2976         } else {
2977                 _zoom_box.pack_start (visible_tracks_selector);
2978                 _zoom_box.pack_start (tav_shrink_button);
2979                 _zoom_box.pack_start (tav_expand_button);
2980         }
2981
2982         if (!ARDOUR::Profile->get_trx()) {
2983                 _zoom_tearoff = manage (new TearOff (_zoom_box));
2984                 
2985                 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2986                                                            &_zoom_tearoff->tearoff_window()));
2987                 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2988                                                            &_zoom_tearoff->tearoff_window(), 0));
2989                 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2990                                                            &_zoom_tearoff->tearoff_window()));
2991                 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2992                                                             &_zoom_tearoff->tearoff_window(), 0));
2993         } 
2994
2995         if (Profile->get_sae() || Profile->get_mixbus() ) {
2996                 _zoom_tearoff->set_can_be_torn_off (false);
2997         }
2998
2999         snap_box.set_spacing (2);
3000         snap_box.set_border_width (2);
3001
3002         snap_type_selector.set_name ("mouse mode button");
3003
3004         snap_mode_selector.set_name ("mouse mode button");
3005
3006         edit_point_selector.set_name ("mouse mode button");
3007
3008         snap_box.pack_start (snap_mode_selector, false, false);
3009         snap_box.pack_start (snap_type_selector, false, false);
3010         snap_box.pack_start (edit_point_selector, false, false);
3011
3012         /* Nudge */
3013
3014         HBox *nudge_box = manage (new HBox);
3015         nudge_box->set_spacing (2);
3016         nudge_box->set_border_width (2);
3017
3018         nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3019         nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3020
3021         nudge_box->pack_start (nudge_backward_button, false, false);
3022         nudge_box->pack_start (nudge_forward_button, false, false);
3023         nudge_box->pack_start (*nudge_clock, false, false);
3024
3025
3026         /* Pack everything in... */
3027
3028         HBox* hbox = manage (new HBox);
3029         hbox->set_spacing(2);
3030
3031         _tools_tearoff = manage (new TearOff (*hbox));
3032         _tools_tearoff->set_name ("MouseModeBase");
3033         _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3034
3035         if (Profile->get_sae() || Profile->get_mixbus()) {
3036                 _tools_tearoff->set_can_be_torn_off (false);
3037         }
3038
3039         _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3040                                                     &_tools_tearoff->tearoff_window()));
3041         _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3042                                                     &_tools_tearoff->tearoff_window(), 0));
3043         _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3044                                                     &_tools_tearoff->tearoff_window()));
3045         _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3046                                                      &_tools_tearoff->tearoff_window(), 0));
3047
3048         toolbar_hbox.set_spacing (2);
3049         toolbar_hbox.set_border_width (1);
3050
3051         toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3052         if (!ARDOUR::Profile->get_trx()) {
3053                 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3054                 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3055         }
3056
3057         if (!ARDOUR::Profile->get_trx()) {
3058                 hbox->pack_start (snap_box, false, false);
3059                 if ( !Profile->get_small_screen() || Profile->get_mixbus() ) {
3060                         hbox->pack_start (*nudge_box, false, false);
3061                 } else {
3062                         ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3063                 }
3064         }
3065         hbox->pack_start (panic_box, false, false);
3066
3067         hbox->show_all ();
3068
3069         toolbar_base.set_name ("ToolBarBase");
3070         toolbar_base.add (toolbar_hbox);
3071
3072         _toolbar_viewport.add (toolbar_base);
3073         /* stick to the required height but allow width to vary if there's not enough room */
3074         _toolbar_viewport.set_size_request (1, -1);
3075
3076         toolbar_frame.set_shadow_type (SHADOW_OUT);
3077         toolbar_frame.set_name ("BaseFrame");
3078         toolbar_frame.add (_toolbar_viewport);
3079 }
3080
3081 void
3082 Editor::build_edit_point_menu ()
3083 {
3084         using namespace Menu_Helpers;
3085
3086         edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3087         if(!Profile->get_mixbus())
3088                 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3089         edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3090
3091         set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3092 }
3093
3094 void
3095 Editor::build_edit_mode_menu ()
3096 {
3097         using namespace Menu_Helpers;
3098         
3099         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3100 //      edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3101         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3102         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
3103
3104         set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3105 }
3106
3107 void
3108 Editor::build_snap_mode_menu ()
3109 {
3110         using namespace Menu_Helpers;
3111
3112         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3113         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3114         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3115
3116         set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3117 }
3118
3119 void
3120 Editor::build_snap_type_menu ()
3121 {
3122         using namespace Menu_Helpers;
3123
3124         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3125         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3126         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3127         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3128         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3129         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3130         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3131         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3132         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3133         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3134         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3135         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3136         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3137         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3138         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3139         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3140         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3141         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3142         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3143         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3144         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3145         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3146         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3147         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3148         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3149         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3150         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3151         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3152         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3153         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3154
3155         set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3156
3157 }
3158
3159 void
3160 Editor::setup_tooltips ()
3161 {
3162         ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3163         ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3164         ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
3165         ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3166         ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3167         ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3168         ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3169         ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3170         ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3171         ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3172         ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3173         ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3174         ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3175         ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3176         ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3177         ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3178         ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3179         ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3180         ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3181         ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3182         ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3183         ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3184         ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3185         ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3186         ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3187         ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3188 }
3189
3190 int
3191 Editor::convert_drop_to_paths (
3192                 vector<string>&                paths,
3193                 const RefPtr<Gdk::DragContext>& /*context*/,
3194                 gint                            /*x*/,
3195                 gint                            /*y*/,
3196                 const SelectionData&            data,
3197                 guint                           /*info*/,
3198                 guint                           /*time*/)
3199 {
3200         if (_session == 0) {
3201                 return -1;
3202         }
3203
3204         vector<string> uris = data.get_uris();
3205
3206         if (uris.empty()) {
3207
3208                 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3209                    are actually URI lists. So do it by hand.
3210                 */
3211
3212                 if (data.get_target() != "text/plain") {
3213                         return -1;
3214                 }
3215
3216                 /* Parse the "uri-list" format that Nautilus provides,
3217                    where each pathname is delimited by \r\n.
3218
3219                    THERE MAY BE NO NULL TERMINATING CHAR!!!
3220                 */
3221
3222                 string txt = data.get_text();
3223                 char* p;
3224                 const char* q;
3225
3226                 p = (char *) malloc (txt.length() + 1);
3227                 txt.copy (p, txt.length(), 0);
3228                 p[txt.length()] = '\0';
3229
3230                 while (p)
3231                 {
3232                         if (*p != '#')
3233                         {
3234                                 while (g_ascii_isspace (*p))
3235                                         p++;
3236
3237                                 q = p;
3238                                 while (*q && (*q != '\n') && (*q != '\r')) {
3239                                         q++;
3240                                 }
3241
3242                                 if (q > p)
3243                                 {
3244                                         q--;
3245                                         while (q > p && g_ascii_isspace (*q))
3246                                                 q--;
3247
3248                                         if (q > p)
3249                                         {
3250                                                 uris.push_back (string (p, q - p + 1));
3251                                         }
3252                                 }
3253                         }
3254                         p = strchr (p, '\n');
3255                         if (p)
3256                                 p++;
3257                 }
3258
3259                 free ((void*)p);
3260
3261                 if (uris.empty()) {
3262                         return -1;
3263                 }
3264         }
3265
3266         for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3267                 if ((*i).substr (0,7) == "file://") {
3268                         paths.push_back (Glib::filename_from_uri (*i));
3269                 }
3270         }
3271
3272         return 0;
3273 }
3274
3275 void
3276 Editor::new_tempo_section ()
3277 {
3278 }
3279
3280 void
3281 Editor::map_transport_state ()
3282 {
3283         ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3284
3285         if (_session && _session->transport_stopped()) {
3286                 have_pending_keyboard_selection = false;
3287         }
3288
3289         update_loop_range_view ();
3290 }
3291
3292 /* UNDO/REDO */
3293
3294 void
3295 Editor::begin_reversible_command (string name)
3296 {
3297         if (_session) {
3298                 _session->begin_reversible_command (name);
3299         }
3300 }
3301
3302 void
3303 Editor::begin_reversible_command (GQuark q)
3304 {
3305         if (_session) {
3306                 _session->begin_reversible_command (q);
3307         }
3308 }
3309
3310 void
3311 Editor::commit_reversible_command ()
3312 {
3313         if (_session) {
3314                 _session->commit_reversible_command ();
3315         }
3316 }
3317
3318 void
3319 Editor::history_changed ()
3320 {
3321         string label;
3322
3323         if (undo_action && _session) {
3324                 if (_session->undo_depth() == 0) {
3325                         label = S_("Command|Undo");
3326                 } else {
3327                         label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3328                 }
3329                 undo_action->property_label() = label;
3330         }
3331
3332         if (redo_action && _session) {
3333                 if (_session->redo_depth() == 0) {
3334                         label = _("Redo");
3335                 } else {
3336                         label = string_compose(_("Redo (%1)"), _session->next_redo());
3337                 }
3338                 redo_action->property_label() = label;
3339         }
3340 }
3341
3342 void
3343 Editor::duplicate_range (bool with_dialog)
3344 {
3345         float times = 1.0f;
3346
3347         RegionSelection rs = get_regions_from_selection_and_entered ();
3348
3349         if ( selection->time.length() == 0 && rs.empty()) {
3350                 return;
3351         }
3352
3353         if (with_dialog) {
3354
3355                 ArdourDialog win (_("Duplicate"));
3356                 Label label (_("Number of duplications:"));
3357                 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3358                 SpinButton spinner (adjustment, 0.0, 1);
3359                 HBox hbox;
3360
3361                 win.get_vbox()->set_spacing (12);
3362                 win.get_vbox()->pack_start (hbox);
3363                 hbox.set_border_width (6);
3364                 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3365
3366                 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3367                    place, visually. so do this by hand.
3368                 */
3369
3370                 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3371                 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3372                 spinner.grab_focus();
3373
3374                 hbox.show ();
3375                 label.show ();
3376                 spinner.show ();
3377
3378                 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3379                 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3380                 win.set_default_response (RESPONSE_ACCEPT);
3381
3382                 spinner.grab_focus ();
3383
3384                 switch (win.run ()) {
3385                 case RESPONSE_ACCEPT:
3386                         break;
3387                 default:
3388                         return;
3389                 }
3390
3391                 times = adjustment.get_value();
3392         }
3393
3394         if ((current_mouse_mode() == Editing::MouseRange)) {
3395                 if (selection->time.length()) {
3396                         duplicate_selection (times);
3397                 }
3398         } else if (get_smart_mode()) {
3399                 if (selection->time.length()) {
3400                         duplicate_selection (times);
3401                 } else 
3402                         duplicate_some_regions (rs, times);
3403         } else {
3404                 duplicate_some_regions (rs, times);
3405         }
3406 }
3407
3408 void
3409 Editor::set_edit_mode (EditMode m)
3410 {
3411         Config->set_edit_mode (m);
3412 }
3413
3414 void
3415 Editor::cycle_edit_mode ()
3416 {
3417         switch (Config->get_edit_mode()) {
3418         case Slide:
3419                 if (Profile->get_sae()) {
3420                         Config->set_edit_mode (Lock);
3421                 } else {
3422                         Config->set_edit_mode (Ripple);
3423                 }
3424                 break;
3425         case Splice:
3426         case Ripple:
3427                 Config->set_edit_mode (Lock);
3428                 break;
3429         case Lock:
3430                 Config->set_edit_mode (Slide);
3431                 break;
3432         }
3433 }
3434
3435 void
3436 Editor::edit_mode_selection_done ( EditMode m )
3437 {
3438         Config->set_edit_mode ( m );
3439 }
3440
3441 void
3442 Editor::snap_type_selection_done (SnapType snaptype)
3443 {
3444         RefPtr<RadioAction> ract = snap_type_action (snaptype);
3445         if (ract) {
3446                 ract->set_active ();
3447         }
3448 }
3449
3450 void
3451 Editor::snap_mode_selection_done (SnapMode mode)
3452 {
3453         RefPtr<RadioAction> ract = snap_mode_action (mode);
3454
3455         if (ract) {
3456                 ract->set_active (true);
3457         }
3458 }
3459
3460 void
3461 Editor::cycle_edit_point (bool with_marker)
3462 {
3463         if(Profile->get_mixbus())
3464                 with_marker = false;
3465
3466         switch (_edit_point) {
3467         case EditAtMouse:
3468                 set_edit_point_preference (EditAtPlayhead);
3469                 break;
3470         case EditAtPlayhead:
3471                 if (with_marker) {
3472                         set_edit_point_preference (EditAtSelectedMarker);
3473                 } else {
3474                         set_edit_point_preference (EditAtMouse);
3475                 }
3476                 break;
3477         case EditAtSelectedMarker:
3478                 set_edit_point_preference (EditAtMouse);
3479                 break;
3480         }
3481 }
3482
3483 void
3484 Editor::edit_point_selection_done (EditPoint ep)
3485 {
3486         set_edit_point_preference ( ep );
3487 }
3488
3489 void
3490 Editor::build_zoom_focus_menu ()
3491 {
3492         using namespace Menu_Helpers;
3493
3494         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3495         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3496         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3497         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3498         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3499         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3500
3501         set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3502 }
3503
3504 void
3505 Editor::zoom_focus_selection_done ( ZoomFocus f )
3506 {
3507         RefPtr<RadioAction> ract = zoom_focus_action (f);
3508         if (ract) {
3509                 ract->set_active ();
3510         }
3511 }
3512
3513 void
3514 Editor::build_track_count_menu ()
3515 {
3516         using namespace Menu_Helpers;
3517
3518         if (!Profile->get_mixbus()) {
3519                 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3520                 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3521                 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3522                 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3523                 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3524                 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3525                 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3526                 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3527                 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3528                 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3529                 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3530                 visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3531                 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3532         } else {
3533                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3534                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3535                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3536                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3537                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3538                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3539                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3540                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3541                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3542                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selected tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3543
3544                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3545                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3546                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3547                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3548                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3549                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3550                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3551                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3552                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3553                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3554                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3555         }
3556 }
3557
3558 void
3559 Editor::set_zoom_preset (int64_t ms)
3560 {
3561         if ( ms <= 0 ) {
3562                 temporal_zoom_session();
3563                 return;
3564         }
3565         
3566         ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3567         temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3568 }
3569
3570 void
3571 Editor::set_visible_track_count (int32_t n)
3572 {
3573         _visible_track_count = n;
3574
3575         /* if the canvas hasn't really been allocated any size yet, just
3576            record the desired number of visible tracks and return. when canvas
3577            allocation happens, we will get called again and then we can do the
3578            real work.
3579         */
3580         
3581         if (_visible_canvas_height <= 1) {
3582                 return;
3583         }
3584
3585         int h;
3586         string str;
3587         
3588         if (_visible_track_count > 0) {
3589                 h = trackviews_height() / _visible_track_count;
3590                 std::ostringstream s;
3591                 s << _visible_track_count;
3592                 str = s.str();
3593         } else if (_visible_track_count == 0) {
3594                 uint32_t n = 0;
3595                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3596                         if ((*i)->marked_for_display()) {
3597                                 ++n;
3598                         }
3599                 }
3600                 h = trackviews_height() / n;
3601                 str = _("All");
3602         } else {
3603                 /* negative value means that the visible track count has 
3604                    been overridden by explicit track height changes.
3605                 */
3606                 visible_tracks_selector.set_text (X_("*"));
3607                 return;
3608         }
3609
3610         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3611                 (*i)->set_height (h);
3612         }
3613         
3614         if (str != visible_tracks_selector.get_text()) {
3615                 visible_tracks_selector.set_text (str);
3616         }
3617 }
3618
3619 void
3620 Editor::override_visible_track_count ()
3621 {
3622         _visible_track_count = -1;
3623         visible_tracks_selector.set_text ( _("*") );
3624 }
3625
3626 bool
3627 Editor::edit_controls_button_release (GdkEventButton* ev)
3628 {
3629         if (Keyboard::is_context_menu_event (ev)) {
3630                 ARDOUR_UI::instance()->add_route (this);
3631         } else if (ev->button == 1) {
3632                 selection->clear_tracks ();
3633         }
3634
3635         return true;
3636 }
3637
3638 bool
3639 Editor::mouse_select_button_release (GdkEventButton* ev)
3640 {
3641         /* this handles just right-clicks */
3642
3643         if (ev->button != 3) {
3644                 return false;
3645         }
3646
3647         return true;
3648 }
3649
3650 void
3651 Editor::set_zoom_focus (ZoomFocus f)
3652 {
3653         string str = zoom_focus_strings[(int)f];
3654
3655         if (str != zoom_focus_selector.get_text()) {
3656                 zoom_focus_selector.set_text (str);
3657         }
3658
3659         if (zoom_focus != f) {
3660                 zoom_focus = f;
3661                 instant_save ();
3662         }
3663 }
3664
3665 void
3666 Editor::cycle_zoom_focus ()
3667 {
3668         switch (zoom_focus) {
3669         case ZoomFocusLeft:
3670                 set_zoom_focus (ZoomFocusRight);
3671                 break;
3672         case ZoomFocusRight:
3673                 set_zoom_focus (ZoomFocusCenter);
3674                 break;
3675         case ZoomFocusCenter:
3676                 set_zoom_focus (ZoomFocusPlayhead);
3677                 break;
3678         case ZoomFocusPlayhead:
3679                 set_zoom_focus (ZoomFocusMouse);
3680                 break;
3681         case ZoomFocusMouse:
3682                 set_zoom_focus (ZoomFocusEdit);
3683                 break;
3684         case ZoomFocusEdit:
3685                 set_zoom_focus (ZoomFocusLeft);
3686                 break;
3687         }
3688 }
3689
3690 void
3691 Editor::ensure_float (Window& win)
3692 {
3693         win.set_transient_for (*this);
3694 }
3695
3696 void
3697 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3698 {
3699         /* recover or initialize pane positions. do this here rather than earlier because
3700            we don't want the positions to change the child allocations, which they seem to do.
3701          */
3702
3703         int pos;
3704         XMLProperty* prop;
3705         char buf[32];
3706         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3707
3708         enum Pane {
3709                 Horizontal = 0x1,
3710                 Vertical = 0x2
3711         };
3712
3713         static Pane done;
3714
3715         XMLNode* geometry = find_named_node (*node, "geometry");
3716
3717         if (which == static_cast<Paned*> (&edit_pane)) {
3718
3719                 if (done & Horizontal) {
3720                         return;
3721                 }
3722
3723                 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3724                         _notebook_shrunk = string_is_affirmative (prop->value ());
3725                 }
3726
3727                 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3728                         /* initial allocation is 90% to canvas, 10% to notebook */
3729                         pos = (int) floor (alloc.get_width() * 0.90f);
3730                         snprintf (buf, sizeof(buf), "%d", pos);
3731                 } else {
3732                         pos = atoi (prop->value());
3733                 }
3734
3735                 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3736                         edit_pane.set_position (pos);
3737                 }
3738
3739                 done = (Pane) (done | Horizontal);
3740
3741         } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3742
3743                 if (done & Vertical) {
3744                         return;
3745                 }
3746
3747                 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3748                         /* initial allocation is 90% to canvas, 10% to summary */
3749                         pos = (int) floor (alloc.get_height() * 0.90f);
3750                         snprintf (buf, sizeof(buf), "%d", pos);
3751                 } else {
3752
3753                         pos = atoi (prop->value());
3754                 }
3755
3756                 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3757                         editor_summary_pane.set_position (pos);
3758                 }
3759
3760                 done = (Pane) (done | Vertical);
3761         }
3762 }
3763
3764 void
3765 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3766 {
3767         if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) && 
3768             (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) && 
3769             (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3770                 top_hbox.remove (toolbar_frame);
3771         }
3772 }
3773
3774 void
3775 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3776 {
3777         if (toolbar_frame.get_parent() == 0) {
3778                 top_hbox.pack_end (toolbar_frame);
3779         }
3780 }
3781
3782 void
3783 Editor::set_show_measures (bool yn)
3784 {
3785         if (_show_measures != yn) {
3786                 hide_measures ();
3787
3788                 if ((_show_measures = yn) == true) {
3789                         if (tempo_lines) {
3790                                 tempo_lines->show();
3791                         }
3792
3793                         ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3794                         ARDOUR::TempoMap::BBTPointList::const_iterator end;
3795                         
3796                         compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3797                         draw_measures (begin, end);
3798                 } 
3799
3800                 instant_save ();
3801         }
3802 }
3803
3804 void
3805 Editor::toggle_follow_playhead ()
3806 {
3807         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3808         if (act) {
3809                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3810                 set_follow_playhead (tact->get_active());
3811         }
3812 }
3813
3814 /** @param yn true to follow playhead, otherwise false.
3815  *  @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3816  */
3817 void
3818 Editor::set_follow_playhead (bool yn, bool catch_up)
3819 {
3820         if (_follow_playhead != yn) {
3821                 if ((_follow_playhead = yn) == true && catch_up) {
3822                         /* catch up */
3823                         reset_x_origin_to_follow_playhead ();
3824                 }
3825                 instant_save ();
3826         }
3827 }
3828
3829 void
3830 Editor::toggle_stationary_playhead ()
3831 {
3832         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3833         if (act) {
3834                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3835                 set_stationary_playhead (tact->get_active());
3836         }
3837 }
3838
3839 void
3840 Editor::set_stationary_playhead (bool yn)
3841 {
3842         if (_stationary_playhead != yn) {
3843                 if ((_stationary_playhead = yn) == true) {
3844                         /* catch up */
3845                         // FIXME need a 3.0 equivalent of this 2.X call
3846                         // update_current_screen ();
3847                 }
3848                 instant_save ();
3849         }
3850 }
3851
3852 PlaylistSelector&
3853 Editor::playlist_selector () const
3854 {
3855         return *_playlist_selector;
3856 }
3857
3858 Evoral::MusicalTime
3859 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3860 {
3861         success = true;
3862
3863         switch (_snap_type) {
3864         case SnapToBeat:
3865                 return 1.0;
3866                 break;
3867
3868         case SnapToBeatDiv128:
3869                 return 1.0/128.0;
3870                 break;
3871         case SnapToBeatDiv64:
3872                 return 1.0/64.0;
3873                 break;
3874         case SnapToBeatDiv32:
3875                 return 1.0/32.0;
3876                 break;
3877         case SnapToBeatDiv28:
3878                 return 1.0/28.0;
3879                 break;
3880         case SnapToBeatDiv24:
3881                 return 1.0/24.0;
3882                 break;
3883         case SnapToBeatDiv20:
3884                 return 1.0/20.0;
3885                 break;
3886         case SnapToBeatDiv16:
3887                 return 1.0/16.0;
3888                 break;
3889         case SnapToBeatDiv14:
3890                 return 1.0/14.0;
3891                 break;
3892         case SnapToBeatDiv12:
3893                 return 1.0/12.0;
3894                 break;
3895         case SnapToBeatDiv10:
3896                 return 1.0/10.0;
3897                 break;
3898         case SnapToBeatDiv8:
3899                 return 1.0/8.0;
3900                 break;
3901         case SnapToBeatDiv7:
3902                 return 1.0/7.0;
3903                 break;
3904         case SnapToBeatDiv6:
3905                 return 1.0/6.0;
3906                 break;
3907         case SnapToBeatDiv5:
3908                 return 1.0/5.0;
3909                 break;
3910         case SnapToBeatDiv4:
3911                 return 1.0/4.0;
3912                 break;
3913         case SnapToBeatDiv3:
3914                 return 1.0/3.0;
3915                 break;
3916         case SnapToBeatDiv2:
3917                 return 1.0/2.0;
3918                 break;
3919
3920         case SnapToBar:
3921                 if (_session) {
3922                         return _session->tempo_map().meter_at (position).divisions_per_bar();
3923                 }
3924                 break;
3925
3926         case SnapToCDFrame:
3927         case SnapToTimecodeFrame:
3928         case SnapToTimecodeSeconds:
3929         case SnapToTimecodeMinutes:
3930         case SnapToSeconds:
3931         case SnapToMinutes:
3932         case SnapToRegionStart:
3933         case SnapToRegionEnd:
3934         case SnapToRegionSync:
3935         case SnapToRegionBoundary:
3936         default:
3937                 success = false;
3938                 break;
3939         }
3940
3941         return 0.0;
3942 }
3943
3944 framecnt_t
3945 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3946 {
3947         framecnt_t ret;
3948
3949         ret = nudge_clock->current_duration (pos);
3950         next = ret + 1; /* XXXX fix me */
3951
3952         return ret;
3953 }
3954
3955 int
3956 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3957 {
3958         ArdourDialog dialog (_("Playlist Deletion"));
3959         Label  label (string_compose (_("Playlist %1 is currently unused.\n"
3960                                         "If it is kept, its audio files will not be cleaned.\n"
3961                                         "If it is deleted, audio files used by it alone will be cleaned."),
3962                                       pl->name()));
3963
3964         dialog.set_position (WIN_POS_CENTER);
3965         dialog.get_vbox()->pack_start (label);
3966
3967         label.show ();
3968
3969         dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3970         dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3971         dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3972
3973         switch (dialog.run ()) {
3974         case RESPONSE_ACCEPT:
3975                 /* delete the playlist */
3976                 return 0;
3977                 break;
3978
3979         case RESPONSE_REJECT:
3980                 /* keep the playlist */
3981                 return 1;
3982                 break;
3983
3984         default:
3985                 break;
3986         }
3987
3988         return -1;
3989 }
3990
3991 bool
3992 Editor::audio_region_selection_covers (framepos_t where)
3993 {
3994         for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3995                 if ((*a)->region()->covers (where)) {
3996                         return true;
3997                 }
3998         }
3999
4000         return false;
4001 }
4002
4003 void
4004 Editor::prepare_for_cleanup ()
4005 {
4006         cut_buffer->clear_regions ();
4007         cut_buffer->clear_playlists ();
4008
4009         selection->clear_regions ();
4010         selection->clear_playlists ();
4011
4012         _regions->suspend_redisplay ();
4013 }
4014
4015 void
4016 Editor::finish_cleanup ()
4017 {
4018         _regions->resume_redisplay ();
4019 }
4020
4021 Location*
4022 Editor::transport_loop_location()
4023 {
4024         if (_session) {
4025                 return _session->locations()->auto_loop_location();
4026         } else {
4027                 return 0;
4028         }
4029 }
4030
4031 Location*
4032 Editor::transport_punch_location()
4033 {
4034         if (_session) {
4035                 return _session->locations()->auto_punch_location();
4036         } else {
4037                 return 0;
4038         }
4039 }
4040
4041 bool
4042 Editor::control_layout_scroll (GdkEventScroll* ev)
4043 {
4044         /* Just forward to the normal canvas scroll method. The coordinate
4045            systems are different but since the canvas is always larger than the
4046            track headers, and aligned with the trackview area, this will work.
4047
4048            In the not too distant future this layout is going away anyway and
4049            headers will be on the canvas.
4050         */
4051         return canvas_scroll_event (ev, false);
4052 }
4053
4054 void
4055 Editor::session_state_saved (string)
4056 {
4057         update_title ();
4058         _snapshots->redisplay ();
4059 }
4060
4061 void
4062 Editor::update_tearoff_visibility()
4063 {
4064         bool visible = Config->get_keep_tearoffs();
4065         _mouse_mode_tearoff->set_visible (visible);
4066         _tools_tearoff->set_visible (visible);
4067         if (_zoom_tearoff) {
4068                 _zoom_tearoff->set_visible (visible);
4069         }
4070 }
4071
4072 void
4073 Editor::reattach_all_tearoffs ()
4074 {
4075         if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
4076         if (_tools_tearoff) _tools_tearoff->put_it_back ();
4077         if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
4078 }
4079
4080 void
4081 Editor::maximise_editing_space ()
4082 {
4083         if (_maximised) {
4084                 return;
4085         }
4086
4087         fullscreen ();
4088
4089         _maximised = true;
4090 }
4091
4092 void
4093 Editor::restore_editing_space ()
4094 {
4095         if (!_maximised) {
4096                 return;
4097         }
4098
4099         unfullscreen();
4100
4101         _maximised = false;
4102 }
4103
4104 /**
4105  *  Make new playlists for a given track and also any others that belong
4106  *  to the same active route group with the `select' property.
4107  *  @param v Track.
4108  */
4109
4110 void
4111 Editor::new_playlists (TimeAxisView* v)
4112 {
4113         begin_reversible_command (_("new playlists"));
4114         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4115         _session->playlists->get (playlists);
4116         mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4117         commit_reversible_command ();
4118 }
4119
4120 /**
4121  *  Use a copy of the current playlist for a given track and also any others that belong
4122  *  to the same active route group with the `select' property.
4123  *  @param v Track.
4124  */
4125
4126 void
4127 Editor::copy_playlists (TimeAxisView* v)
4128 {
4129         begin_reversible_command (_("copy playlists"));
4130         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4131         _session->playlists->get (playlists);
4132         mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4133         commit_reversible_command ();
4134 }
4135
4136 /** Clear the current playlist for a given track and also any others that belong
4137  *  to the same active route group with the `select' property.
4138  *  @param v Track.
4139  */
4140
4141 void
4142 Editor::clear_playlists (TimeAxisView* v)
4143 {
4144         begin_reversible_command (_("clear playlists"));
4145         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4146         _session->playlists->get (playlists);
4147         mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4148         commit_reversible_command ();
4149 }
4150
4151 void
4152 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4153 {
4154         atv.use_new_playlist (sz > 1 ? false : true, playlists);
4155 }
4156
4157 void
4158 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4159 {
4160         atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4161 }
4162
4163 void
4164 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4165 {
4166         atv.clear_playlist ();
4167 }
4168
4169 bool
4170 Editor::on_key_press_event (GdkEventKey* ev)
4171 {
4172         return key_press_focus_accelerator_handler (*this, ev);
4173 }
4174
4175 bool
4176 Editor::on_key_release_event (GdkEventKey* ev)
4177 {
4178         return Gtk::Window::on_key_release_event (ev);
4179         // return key_press_focus_accelerator_handler (*this, ev);
4180 }
4181
4182 /** Queue up a change to the viewport x origin.
4183  *  @param frame New x origin.
4184  */
4185 void
4186 Editor::reset_x_origin (framepos_t frame)
4187 {
4188         pending_visual_change.add (VisualChange::TimeOrigin);
4189         pending_visual_change.time_origin = frame;
4190         ensure_visual_change_idle_handler ();
4191 }
4192
4193 void
4194 Editor::reset_y_origin (double y)
4195 {
4196         pending_visual_change.add (VisualChange::YOrigin);
4197         pending_visual_change.y_origin = y;
4198         ensure_visual_change_idle_handler ();
4199 }
4200
4201 void
4202 Editor::reset_zoom (framecnt_t spp)
4203 {
4204         if (spp == samples_per_pixel) {
4205                 return;
4206         }
4207
4208         pending_visual_change.add (VisualChange::ZoomLevel);
4209         pending_visual_change.samples_per_pixel = spp;
4210         ensure_visual_change_idle_handler ();
4211 }
4212
4213 void
4214 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4215 {
4216         reset_x_origin (frame);
4217         reset_zoom (fpu);
4218
4219         if (!no_save_visual) {
4220                 undo_visual_stack.push_back (current_visual_state(false));
4221         }
4222 }
4223
4224 Editor::VisualState::VisualState (bool with_tracks)
4225         : gui_state (with_tracks ? new GUIObjectState : 0)
4226 {
4227 }
4228
4229 Editor::VisualState::~VisualState ()
4230 {
4231         delete gui_state;
4232 }
4233
4234 Editor::VisualState*
4235 Editor::current_visual_state (bool with_tracks)
4236 {
4237         VisualState* vs = new VisualState (with_tracks);
4238         vs->y_position = vertical_adjustment.get_value();
4239         vs->samples_per_pixel = samples_per_pixel;
4240         vs->leftmost_frame = leftmost_frame;
4241         vs->zoom_focus = zoom_focus;
4242
4243         if (with_tracks) {      
4244                 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4245         }
4246
4247         return vs;
4248 }
4249
4250 void
4251 Editor::undo_visual_state ()
4252 {
4253         if (undo_visual_stack.empty()) {
4254                 return;
4255         }
4256
4257         VisualState* vs = undo_visual_stack.back();
4258         undo_visual_stack.pop_back();
4259
4260
4261         redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4262
4263         use_visual_state (*vs);
4264 }
4265
4266 void
4267 Editor::redo_visual_state ()
4268 {
4269         if (redo_visual_stack.empty()) {
4270                 return;
4271         }
4272
4273         VisualState* vs = redo_visual_stack.back();
4274         redo_visual_stack.pop_back();
4275
4276         undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4277
4278         use_visual_state (*vs);
4279 }
4280
4281 void
4282 Editor::swap_visual_state ()
4283 {
4284         if (undo_visual_stack.empty()) {
4285                 redo_visual_state ();
4286         } else {
4287                 undo_visual_state ();
4288         }
4289 }
4290
4291 void
4292 Editor::use_visual_state (VisualState& vs)
4293 {
4294         PBD::Unwinder<bool> nsv (no_save_visual, true);
4295         DisplaySuspender ds;
4296
4297         vertical_adjustment.set_value (vs.y_position);
4298
4299         set_zoom_focus (vs.zoom_focus);
4300         reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4301         
4302         if (vs.gui_state) {
4303                 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4304                 
4305                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {    
4306                         (*i)->reset_visual_state ();
4307                 }
4308         }
4309
4310         _routes->update_visibility ();
4311 }
4312
4313 /** This is the core function that controls the zoom level of the canvas. It is called
4314  *  whenever one or more calls are made to reset_zoom().  It executes in an idle handler.
4315  *  @param spp new number of samples per pixel
4316  */
4317 void
4318 Editor::set_samples_per_pixel (framecnt_t spp)
4319 {
4320         if (spp < 1) {
4321                 return;
4322         }
4323
4324         const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4325         const framecnt_t lots_of_pixels = 4000;
4326
4327         /* if the zoom level is greater than what you'd get trying to display 3
4328          * days of audio on a really big screen, then it's too big.
4329          */
4330
4331         if (spp * lots_of_pixels > three_days) {
4332                 return;
4333         }
4334
4335         samples_per_pixel = spp;
4336
4337         if (tempo_lines) {
4338                 tempo_lines->tempo_map_changed();
4339         }
4340
4341         bool const showing_time_selection = selection->time.length() > 0;
4342
4343         if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4344                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4345                         (*i)->reshow_selection (selection->time);
4346                 }
4347         }
4348
4349         ZoomChanged (); /* EMIT_SIGNAL */
4350
4351         ArdourCanvas::GtkCanvasViewport* c;
4352
4353         c = get_track_canvas();
4354         if (c) {
4355                 c->canvas()->zoomed ();
4356         }
4357
4358         if (playhead_cursor) {
4359                 playhead_cursor->set_position (playhead_cursor->current_frame ());
4360         }
4361
4362         refresh_location_display();
4363         _summary->set_overlays_dirty ();
4364
4365         update_marker_labels ();
4366
4367         instant_save ();
4368 }
4369
4370 void
4371 Editor::queue_visual_videotimeline_update ()
4372 {
4373         /* TODO:
4374          * pending_visual_change.add (VisualChange::VideoTimeline);
4375          * or maybe even more specific: which videotimeline-image
4376          * currently it calls update_video_timeline() to update
4377          * _all outdated_ images on the video-timeline.
4378          * see 'exposeimg()' in video_image_frame.cc
4379          */
4380         ensure_visual_change_idle_handler ();
4381 }
4382
4383 void
4384 Editor::ensure_visual_change_idle_handler ()
4385 {
4386         if (pending_visual_change.idle_handler_id < 0) {
4387                 // see comment in add_to_idle_resize above.
4388                 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 20, _idle_visual_changer, this, NULL);
4389                 pending_visual_change.being_handled = false;
4390         }
4391 }
4392
4393 int
4394 Editor::_idle_visual_changer (void* arg)
4395 {
4396         return static_cast<Editor*>(arg)->idle_visual_changer ();
4397 }
4398
4399 int
4400 Editor::idle_visual_changer ()
4401 {
4402         /* set_horizontal_position() below (and maybe other calls) call
4403            gtk_main_iteration(), so it's possible that a signal will be handled
4404            half-way through this method.  If this signal wants an
4405            idle_visual_changer we must schedule another one after this one, so
4406            mark the idle_handler_id as -1 here to allow that.  Also make a note
4407            that we are doing the visual change, so that changes in response to
4408            super-rapid-screen-update can be dropped if we are still processing
4409            the last one.
4410         */
4411
4412         pending_visual_change.idle_handler_id = -1;
4413         pending_visual_change.being_handled = true;
4414         
4415         VisualChange vc = pending_visual_change;
4416
4417         pending_visual_change.pending = (VisualChange::Type) 0;
4418
4419         visual_changer (vc);
4420
4421         pending_visual_change.being_handled = false;
4422
4423         return 0; /* this is always a one-shot call */
4424 }
4425
4426 void
4427 Editor::visual_changer (const VisualChange& vc)
4428 {
4429         double const last_time_origin = horizontal_position ();
4430
4431         if (vc.pending & VisualChange::ZoomLevel) {
4432                 set_samples_per_pixel (vc.samples_per_pixel);
4433
4434                 compute_fixed_ruler_scale ();
4435
4436                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4437                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4438                 
4439                 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4440                                             current_bbt_points_begin, current_bbt_points_end);
4441                 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4442                                          current_bbt_points_begin, current_bbt_points_end);
4443                 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4444
4445                 update_video_timeline();
4446         }
4447
4448         if (vc.pending & VisualChange::TimeOrigin) {
4449                 set_horizontal_position (vc.time_origin / samples_per_pixel);
4450         }
4451
4452         if (vc.pending & VisualChange::YOrigin) {
4453                 vertical_adjustment.set_value (vc.y_origin);
4454         }
4455
4456         if (last_time_origin == horizontal_position ()) {
4457                 /* changed signal not emitted */
4458                 update_fixed_rulers ();
4459                 redisplay_tempo (true);
4460         }
4461
4462         if (!(vc.pending & VisualChange::ZoomLevel)) {
4463                 update_video_timeline();
4464         }
4465
4466         _summary->set_overlays_dirty ();
4467 }
4468
4469 struct EditorOrderTimeAxisSorter {
4470     bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4471             return a->order () < b->order ();
4472     }
4473 };
4474
4475 void
4476 Editor::sort_track_selection (TrackViewList& sel)
4477 {
4478         EditorOrderTimeAxisSorter cmp;
4479         sel.sort (cmp);
4480 }
4481
4482 framepos_t
4483 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4484 {
4485         bool ignored;
4486         framepos_t where = 0;
4487         EditPoint ep = _edit_point;
4488
4489         if(Profile->get_mixbus())
4490                 if (ep == EditAtSelectedMarker)
4491                         ep=EditAtPlayhead;
4492                 
4493         if (from_context_menu && (ep == EditAtMouse)) {
4494                 return  canvas_event_sample (&context_click_event, 0, 0);
4495         }
4496
4497         if (entered_marker) {
4498                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4499                 return entered_marker->position();
4500         }
4501
4502         if (ignore_playhead && ep == EditAtPlayhead) {
4503                 ep = EditAtSelectedMarker;
4504         }
4505
4506         switch (ep) {
4507         case EditAtPlayhead:
4508                 where = _session->audible_frame();
4509                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4510                 break;
4511
4512         case EditAtSelectedMarker:
4513                 if (!selection->markers.empty()) {
4514                         bool is_start;
4515                         Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4516                         if (loc) {
4517                                 if (is_start) {
4518                                         where =  loc->start();
4519                                 } else {
4520                                         where = loc->end();
4521                                 }
4522                                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4523                                 break;
4524                         }
4525                 }
4526                 /* fallthru */
4527
4528         default:
4529         case EditAtMouse:
4530                 if (!mouse_frame (where, ignored)) {
4531                         /* XXX not right but what can we do ? */
4532                         return 0;
4533                 }
4534                 snap_to (where);
4535                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4536                 break;
4537         }
4538
4539         return where;
4540 }
4541
4542 void
4543 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4544 {
4545         if (!_session) return;
4546
4547         begin_reversible_command (cmd);
4548
4549         Location* tll;
4550
4551         if ((tll = transport_loop_location()) == 0) {
4552                 Location* loc = new Location (*_session, start, end, _("Loop"),  Location::IsAutoLoop);
4553                 XMLNode &before = _session->locations()->get_state();
4554                 _session->locations()->add (loc, true);
4555                 _session->set_auto_loop_location (loc);
4556                 XMLNode &after = _session->locations()->get_state();
4557                 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4558         } else {
4559                 XMLNode &before = tll->get_state();
4560                 tll->set_hidden (false, this);
4561                 tll->set (start, end);
4562                 XMLNode &after = tll->get_state();
4563                 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4564         }
4565
4566         commit_reversible_command ();
4567 }
4568
4569 void
4570 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4571 {
4572         if (!_session) return;
4573
4574         begin_reversible_command (cmd);
4575
4576         Location* tpl;
4577
4578         if ((tpl = transport_punch_location()) == 0) {
4579                 Location* loc = new Location (*_session, start, end, _("Punch"),  Location::IsAutoPunch);
4580                 XMLNode &before = _session->locations()->get_state();
4581                 _session->locations()->add (loc, true);
4582                 _session->set_auto_punch_location (loc);
4583                 XMLNode &after = _session->locations()->get_state();
4584                 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4585         }
4586         else {
4587                 XMLNode &before = tpl->get_state();
4588                 tpl->set_hidden (false, this);
4589                 tpl->set (start, end);
4590                 XMLNode &after = tpl->get_state();
4591                 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4592         }
4593
4594         commit_reversible_command ();
4595 }
4596
4597 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4598  *  @param rs List to which found regions are added.
4599  *  @param where Time to look at.
4600  *  @param ts Tracks to look on; if this is empty, all tracks are examined.
4601  */
4602 void
4603 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4604 {
4605         const TrackViewList* tracks;
4606
4607         if (ts.empty()) {
4608                 tracks = &track_views;
4609         } else {
4610                 tracks = &ts;
4611         }
4612
4613         for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4614
4615                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4616
4617                 if (rtv) {
4618                         boost::shared_ptr<Track> tr;
4619                         boost::shared_ptr<Playlist> pl;
4620
4621                         if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4622
4623                                 boost::shared_ptr<RegionList> regions = pl->regions_at (
4624                                                 (framepos_t) floor ( (double) where * tr->speed()));
4625
4626                                 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4627                                         RegionView* rv = rtv->view()->find_view (*i);
4628                                         if (rv) {
4629                                                 rs.add (rv);
4630                                         }
4631                                 }
4632                         }
4633                 }
4634         }
4635 }
4636
4637 void
4638 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4639 {
4640         const TrackViewList* tracks;
4641
4642         if (ts.empty()) {
4643                 tracks = &track_views;
4644         } else {
4645                 tracks = &ts;
4646         }
4647
4648         for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4649                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4650                 if (rtv) {
4651                         boost::shared_ptr<Track> tr;
4652                         boost::shared_ptr<Playlist> pl;
4653
4654                         if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4655
4656                                 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4657                                         (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4658
4659                                 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4660
4661                                         RegionView* rv = rtv->view()->find_view (*i);
4662
4663                                         if (rv) {
4664                                                 rs.add (rv);
4665                                         }
4666                                 }
4667                         }
4668                 }
4669         }
4670 }
4671
4672 /** Get regions using the following method:
4673  *
4674  *  Make a region list using:
4675  *   (a) any selected regions
4676  *   (b) the intersection of any selected tracks and the edit point(*)
4677  *   (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4678  *
4679  *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4680  *
4681  *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4682  */
4683
4684 RegionSelection
4685 Editor::get_regions_from_selection_and_edit_point ()
4686 {
4687         RegionSelection regions;
4688
4689         if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4690                 regions.add (entered_regionview);
4691         } else {
4692                 regions = selection->regions;
4693         }
4694
4695         if ( regions.empty() ) {
4696                 TrackViewList tracks = selection->tracks;
4697
4698                 if (!tracks.empty()) {
4699                         /* no region selected or entered, but some selected tracks:
4700                          * act on all regions on the selected tracks at the edit point
4701                          */ 
4702                         framepos_t const where = get_preferred_edit_position ();
4703                         get_regions_at(regions, where, tracks);
4704                 }
4705         }
4706
4707         return regions;
4708 }
4709
4710 /** Get regions using the following method:
4711  *
4712  *  Make a region list using:
4713  *   (a) any selected regions
4714  *   (b) the intersection of any selected tracks and the edit point(*)
4715  *   (c) if neither exists, then whatever region is under the mouse
4716  *
4717  *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4718  *
4719  *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4720  */
4721 RegionSelection
4722 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4723 {
4724         RegionSelection regions;
4725
4726         if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4727                 regions.add (entered_regionview);
4728         } else {
4729                 regions = selection->regions;
4730         }
4731
4732         if ( regions.empty() ) {
4733                 TrackViewList tracks = selection->tracks;
4734
4735                 if (!tracks.empty()) {
4736                         /* no region selected or entered, but some selected tracks:
4737                          * act on all regions on the selected tracks at the edit point
4738                          */ 
4739                         get_regions_at(regions, pos, tracks);
4740                 }
4741         }
4742
4743         return regions;
4744 }
4745
4746 /** Start with regions that are selected, or the entered regionview if none are selected.
4747  *  Then add equivalent regions on tracks in the same active edit-enabled route group as any
4748  *  of the regions that we started with.
4749  */
4750
4751 RegionSelection
4752 Editor::get_regions_from_selection_and_entered ()
4753 {
4754         RegionSelection regions = selection->regions;
4755
4756         if (regions.empty() && entered_regionview) {
4757                 regions.add (entered_regionview);
4758         }
4759
4760         return regions;
4761 }
4762
4763 void
4764 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4765 {
4766         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4767
4768                 RouteTimeAxisView* tatv;
4769
4770                 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4771
4772                         boost::shared_ptr<Playlist> pl;
4773                         vector<boost::shared_ptr<Region> > results;
4774                         RegionView* marv;
4775                         boost::shared_ptr<Track> tr;
4776
4777                         if ((tr = tatv->track()) == 0) {
4778                                 /* bus */
4779                                 continue;
4780                         }
4781
4782                         if ((pl = (tr->playlist())) != 0) {
4783                                 if (src_comparison) {
4784                                         pl->get_source_equivalent_regions (region, results);
4785                                 } else {
4786                                         pl->get_region_list_equivalent_regions (region, results);
4787                                 }
4788                         }
4789
4790                         for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4791                                 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4792                                         regions.push_back (marv);
4793                                 }
4794                         }
4795
4796                 }
4797         }
4798 }
4799
4800 void
4801 Editor::show_rhythm_ferret ()
4802 {
4803         if (rhythm_ferret == 0) {
4804                 rhythm_ferret = new RhythmFerret(*this);
4805         }
4806
4807         rhythm_ferret->set_session (_session);
4808         rhythm_ferret->show ();
4809         rhythm_ferret->present ();
4810 }
4811
4812 void
4813 Editor::first_idle ()
4814 {
4815         MessageDialog* dialog = 0;
4816         
4817         if (track_views.size() > 1) {
4818                 dialog = new MessageDialog (
4819                         *this,
4820                         string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4821                         true
4822                         );
4823                 dialog->present ();
4824                 ARDOUR_UI::instance()->flush_pending ();
4825         }
4826
4827         for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4828                 (*t)->first_idle();
4829         }
4830
4831         // first idle adds route children (automation tracks), so we need to redisplay here
4832         _routes->redisplay ();
4833
4834         delete dialog;
4835         _have_idled = true;
4836 }
4837
4838 gboolean
4839 Editor::_idle_resize (gpointer arg)
4840 {
4841         return ((Editor*)arg)->idle_resize ();
4842 }
4843
4844 void
4845 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4846 {
4847         if (resize_idle_id < 0) {
4848                 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
4849                  * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
4850                  * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
4851                  */
4852                 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
4853                 _pending_resize_amount = 0;
4854         }
4855
4856         /* make a note of the smallest resulting height, so that we can clamp the
4857            lower limit at TimeAxisView::hSmall */
4858
4859         int32_t min_resulting = INT32_MAX;
4860
4861         _pending_resize_amount += h;
4862         _pending_resize_view = view;
4863
4864         min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4865
4866         if (selection->tracks.contains (_pending_resize_view)) {
4867                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4868                         min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4869                 }
4870         }
4871
4872         if (min_resulting < 0) {
4873                 min_resulting = 0;
4874         }
4875
4876         /* clamp */
4877         if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4878                 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4879         }
4880 }
4881
4882 /** Handle pending resizing of tracks */
4883 bool
4884 Editor::idle_resize ()
4885 {
4886         _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4887
4888         if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4889             selection->tracks.contains (_pending_resize_view)) {
4890
4891                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4892                         if (*i != _pending_resize_view) {
4893                                 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4894                         }
4895                 }
4896         }
4897
4898         _pending_resize_amount = 0;
4899         _group_tabs->set_dirty ();
4900         resize_idle_id = -1;
4901
4902         return false;
4903 }
4904
4905 void
4906 Editor::located ()
4907 {
4908         ENSURE_GUI_THREAD (*this, &Editor::located);
4909
4910         if (_session) {
4911                 playhead_cursor->set_position (_session->audible_frame ());
4912                 if (_follow_playhead && !_pending_initial_locate) {
4913                         reset_x_origin_to_follow_playhead ();
4914                 }
4915         }
4916
4917         _pending_locate_request = false;
4918         _pending_initial_locate = false;
4919 }
4920
4921 void
4922 Editor::region_view_added (RegionView *)
4923 {
4924         _summary->set_background_dirty ();
4925 }
4926
4927 void
4928 Editor::region_view_removed ()
4929 {
4930         _summary->set_background_dirty ();
4931 }
4932
4933 RouteTimeAxisView*
4934 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4935 {
4936         TrackViewList::const_iterator j = track_views.begin ();
4937         while (j != track_views.end()) {
4938                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4939                 if (rtv && rtv->route() == r) {
4940                         return rtv;
4941                 }
4942                 ++j;
4943         }
4944
4945         return 0;
4946 }
4947
4948
4949 TrackViewList
4950 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4951 {
4952         TrackViewList t;
4953
4954         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4955                 TimeAxisView* tv = axis_view_from_route (*i);
4956                 if (tv) {
4957                         t.push_back (tv);
4958                 }
4959         }
4960
4961         return t;
4962 }
4963
4964 void
4965 Editor::suspend_route_redisplay ()
4966 {
4967         if (_routes) {
4968                 _routes->suspend_redisplay();
4969         }
4970 }
4971
4972 void
4973 Editor::resume_route_redisplay ()
4974 {
4975         if (_routes) {
4976                 _routes->resume_redisplay();
4977         }
4978 }
4979
4980 void
4981 Editor::add_routes (RouteList& routes)
4982 {
4983         ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4984
4985         RouteTimeAxisView *rtv;
4986         list<RouteTimeAxisView*> new_views;
4987
4988         for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4989                 boost::shared_ptr<Route> route = (*x);
4990
4991                 if (route->is_auditioner() || route->is_monitor()) {
4992                         continue;
4993                 }
4994
4995                 DataType dt = route->input()->default_type();
4996
4997                 if (dt == ARDOUR::DataType::AUDIO) {
4998                         rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4999                         rtv->set_route (route);
5000                 } else if (dt == ARDOUR::DataType::MIDI) {
5001                         rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5002                         rtv->set_route (route);
5003                 } else {
5004                         throw unknown_type();
5005                 }
5006
5007                 new_views.push_back (rtv);
5008                 track_views.push_back (rtv);
5009
5010                 rtv->effective_gain_display ();
5011
5012                 if (internal_editing()) {
5013                         rtv->enter_internal_edit_mode ();
5014                 } else {
5015                         rtv->leave_internal_edit_mode ();
5016                 }
5017
5018                 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5019                 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5020         }
5021
5022         if (new_views.size() > 0) {
5023                 _routes->routes_added (new_views);
5024                 _summary->routes_added (new_views);
5025         }
5026
5027         if (show_editor_mixer_when_tracks_arrive) {
5028                 show_editor_mixer (true);
5029         }
5030
5031         editor_list_button.set_sensitive (true);
5032 }
5033
5034 void
5035 Editor::timeaxisview_deleted (TimeAxisView *tv)
5036 {
5037         if (tv == entered_track) {
5038                 entered_track = 0;
5039         }
5040
5041         if (_session && _session->deletion_in_progress()) {
5042                 /* the situation is under control */
5043                 return;
5044         }
5045
5046         ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5047
5048         RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5049
5050         _routes->route_removed (tv);
5051
5052         TimeAxisView::Children c = tv->get_child_list ();
5053         for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5054                 if (entered_track == i->get()) {
5055                         entered_track = 0;
5056                 }
5057         }
5058
5059         /* remove it from the list of track views */
5060
5061         TrackViewList::iterator i;
5062
5063         if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5064                 i = track_views.erase (i);
5065         }
5066
5067         /* update whatever the current mixer strip is displaying, if revelant */
5068
5069         boost::shared_ptr<Route> route;
5070
5071         if (rtav) {
5072                 route = rtav->route ();
5073         }
5074
5075         if (current_mixer_strip && current_mixer_strip->route() == route) {
5076
5077                 TimeAxisView* next_tv;
5078
5079                 if (track_views.empty()) {
5080                         next_tv = 0;
5081                 } else if (i == track_views.end()) {
5082                         next_tv = track_views.front();
5083                 } else {
5084                         next_tv = (*i);
5085                 }
5086
5087
5088                 if (next_tv) {
5089                         set_selected_mixer_strip (*next_tv);
5090                 } else {
5091                         /* make the editor mixer strip go away setting the
5092                          * button to inactive (which also unticks the menu option)
5093                          */
5094
5095                         ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5096                 }
5097         }
5098 }
5099
5100 void
5101 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5102 {
5103         if (apply_to_selection) {
5104                 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5105
5106                         TrackSelection::iterator j = i;
5107                         ++j;
5108
5109                         hide_track_in_display (*i, false);
5110
5111                         i = j;
5112                 }
5113         } else {
5114                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5115
5116                 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5117                         // this will hide the mixer strip
5118                         set_selected_mixer_strip (*tv);
5119                 }
5120
5121                 _routes->hide_track_in_display (*tv);
5122         }
5123 }
5124
5125 bool
5126 Editor::sync_track_view_list_and_routes ()
5127 {
5128         track_views = TrackViewList (_routes->views ());
5129
5130         _summary->set_dirty ();
5131         _group_tabs->set_dirty ();
5132
5133         return false; // do not call again (until needed)
5134 }
5135
5136 void
5137 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5138 {
5139         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5140                 theslot (**i);
5141         }
5142 }
5143
5144 /** Find a RouteTimeAxisView by the ID of its route */
5145 RouteTimeAxisView*
5146 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5147 {
5148         RouteTimeAxisView* v;
5149
5150         for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5151                 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5152                         if(v->route()->id() == id) {
5153                                 return v;
5154                         }
5155                 }
5156         }
5157
5158         return 0;
5159 }
5160
5161 void
5162 Editor::fit_route_group (RouteGroup *g)
5163 {
5164         TrackViewList ts = axis_views_from_routes (g->route_list ());
5165         fit_tracks (ts);
5166 }
5167
5168 void
5169 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5170 {
5171         boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5172
5173         if (r == 0) {
5174                 _session->cancel_audition ();
5175                 return;
5176         }
5177
5178         if (_session->is_auditioning()) {
5179                 _session->cancel_audition ();
5180                 if (r == last_audition_region) {
5181                         return;
5182                 }
5183         }
5184
5185         _session->audition_region (r);
5186         last_audition_region = r;
5187 }
5188
5189
5190 void
5191 Editor::hide_a_region (boost::shared_ptr<Region> r)
5192 {
5193         r->set_hidden (true);
5194 }
5195
5196 void
5197 Editor::show_a_region (boost::shared_ptr<Region> r)
5198 {
5199         r->set_hidden (false);
5200 }
5201
5202 void
5203 Editor::audition_region_from_region_list ()
5204 {
5205         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5206 }
5207
5208 void
5209 Editor::hide_region_from_region_list ()
5210 {
5211         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5212 }
5213
5214 void
5215 Editor::show_region_in_region_list ()
5216 {
5217         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5218 }
5219
5220 void
5221 Editor::step_edit_status_change (bool yn)
5222 {
5223         if (yn) {
5224                 start_step_editing ();
5225         } else {
5226                 stop_step_editing ();
5227         }
5228 }
5229
5230 void
5231 Editor::start_step_editing ()
5232 {
5233         step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5234 }
5235
5236 void
5237 Editor::stop_step_editing ()
5238 {
5239         step_edit_connection.disconnect ();
5240 }
5241
5242 bool
5243 Editor::check_step_edit ()
5244 {
5245         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5246                 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5247                 if (mtv) {
5248                         mtv->check_step_edit ();
5249                 }
5250         }
5251
5252         return true; // do it again, till we stop
5253 }
5254
5255 bool
5256 Editor::scroll_press (Direction dir)
5257 {
5258         ++_scroll_callbacks;
5259
5260         if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5261                 /* delay the first auto-repeat */
5262                 return true;
5263         }
5264
5265         switch (dir) {
5266         case LEFT:
5267                 scroll_backward (1);
5268                 break;
5269
5270         case RIGHT:
5271                 scroll_forward (1);
5272                 break;
5273
5274         case UP:
5275                 scroll_up_one_track ();
5276                 break;
5277
5278         case DOWN:
5279                 scroll_down_one_track ();
5280                 break;
5281         }
5282
5283         /* do hacky auto-repeat */
5284         if (!_scroll_connection.connected ()) {
5285
5286                 _scroll_connection = Glib::signal_timeout().connect (
5287                         sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5288                         );
5289
5290                 _scroll_callbacks = 0;
5291         }
5292
5293         return true;
5294 }
5295
5296 void
5297 Editor::scroll_release ()
5298 {
5299         _scroll_connection.disconnect ();
5300 }
5301
5302 /** Queue a change for the Editor viewport x origin to follow the playhead */
5303 void
5304 Editor::reset_x_origin_to_follow_playhead ()
5305 {
5306         framepos_t const frame = playhead_cursor->current_frame ();
5307
5308         if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5309
5310                 if (_session->transport_speed() < 0) {
5311
5312                         if (frame > (current_page_samples() / 2)) {
5313                                 center_screen (frame-(current_page_samples()/2));
5314                         } else {
5315                                 center_screen (current_page_samples()/2);
5316                         }
5317
5318                 } else {
5319
5320                         framepos_t l = 0;
5321                         
5322                         if (frame < leftmost_frame) {
5323                                 /* moving left */
5324                                 if (_session->transport_rolling()) {
5325                                         /* rolling; end up with the playhead at the right of the page */
5326                                         l = frame - current_page_samples ();
5327                                 } else {
5328                                         /* not rolling: end up with the playhead 1/4 of the way along the page */
5329                                         l = frame - current_page_samples() / 4;
5330                                 }
5331                         } else {
5332                                 /* moving right */
5333                                 if (_session->transport_rolling()) {
5334                                         /* rolling: end up with the playhead on the left of the page */
5335                                         l = frame;
5336                                 } else {
5337                                         /* not rolling: end up with the playhead 3/4 of the way along the page */
5338                                         l = frame - 3 * current_page_samples() / 4;
5339                                 }
5340                         }
5341
5342                         if (l < 0) {
5343                                 l = 0;
5344                         }
5345                         
5346                         center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5347                 }
5348         }
5349 }
5350
5351 void
5352 Editor::super_rapid_screen_update ()
5353 {
5354         if (!_session || !_session->engine().running()) {
5355                 return;
5356         }
5357
5358         /* METERING / MIXER STRIPS */
5359
5360         /* update track meters, if required */
5361         if (is_mapped() && meters_running) {
5362                 RouteTimeAxisView* rtv;
5363                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5364                         if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5365                                 rtv->fast_update ();
5366                         }
5367                 }
5368         }
5369
5370         /* and any current mixer strip */
5371         if (current_mixer_strip) {
5372                 current_mixer_strip->fast_update ();
5373         }
5374
5375         /* PLAYHEAD AND VIEWPORT */
5376
5377         framepos_t const frame = _session->audible_frame();
5378
5379         /* There are a few reasons why we might not update the playhead / viewport stuff:
5380          *
5381          * 1.  we don't update things when there's a pending locate request, otherwise
5382          *     when the editor requests a locate there is a chance that this method
5383          *     will move the playhead before the locate request is processed, causing
5384          *     a visual glitch.
5385          * 2.  if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5386          * 3.  if we're still at the same frame that we were last time, there's nothing to do.
5387          */
5388
5389         if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5390
5391                 last_update_frame = frame;
5392
5393                 if (!_dragging_playhead) {
5394                         playhead_cursor->set_position (frame);
5395                 }
5396
5397                 if (!_stationary_playhead) {
5398
5399                         if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5400                                 /* We only do this if we aren't already
5401                                    handling a visual change (ie if
5402                                    pending_visual_change.being_handled is
5403                                    false) so that these requests don't stack
5404                                    up there are too many of them to handle in
5405                                    time.
5406                                 */
5407                                 reset_x_origin_to_follow_playhead ();
5408                         }
5409
5410                 } else {
5411
5412                         /* don't do continuous scroll till the new position is in the rightmost quarter of the
5413                            editor canvas
5414                         */
5415 #if 0
5416                         // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5417                         double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5418                         if (target <= 0.0) {
5419                                 target = 0.0;
5420                         }
5421                         if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5422                                 target = (target * 0.15) + (current * 0.85);
5423                         } else {
5424                                 /* relax */
5425                         }
5426
5427                         current = target;
5428                         set_horizontal_position (current);
5429 #endif
5430                 }
5431
5432         }
5433 }
5434
5435
5436 void
5437 Editor::session_going_away ()
5438 {
5439         _have_idled = false;
5440
5441         _session_connections.drop_connections ();
5442
5443         super_rapid_screen_update_connection.disconnect ();
5444
5445         selection->clear ();
5446         cut_buffer->clear ();
5447
5448         clicked_regionview = 0;
5449         clicked_axisview = 0;
5450         clicked_routeview = 0;
5451         entered_regionview = 0;
5452         entered_track = 0;
5453         last_update_frame = 0;
5454         _drags->abort ();
5455
5456         playhead_cursor->hide ();
5457
5458         /* rip everything out of the list displays */
5459
5460         _regions->clear ();
5461         _routes->clear ();
5462         _route_groups->clear ();
5463
5464         /* do this first so that deleting a track doesn't reset cms to null
5465            and thus cause a leak.
5466         */
5467
5468         if (current_mixer_strip) {
5469                 if (current_mixer_strip->get_parent() != 0) {
5470                         global_hpacker.remove (*current_mixer_strip);
5471                 }
5472                 delete current_mixer_strip;
5473                 current_mixer_strip = 0;
5474         }
5475
5476         /* delete all trackviews */
5477
5478         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5479                 delete *i;
5480         }
5481         track_views.clear ();
5482
5483         nudge_clock->set_session (0);
5484
5485         editor_list_button.set_active(false);
5486         editor_list_button.set_sensitive(false);
5487
5488         /* clear tempo/meter rulers */
5489         remove_metric_marks ();
5490         hide_measures ();
5491         clear_marker_display ();
5492
5493         stop_step_editing ();
5494         
5495         /* get rid of any existing editor mixer strip */
5496
5497         WindowTitle title(Glib::get_application_name());
5498         title += _("Editor");
5499
5500         set_title (title.get_string());
5501
5502         SessionHandlePtr::session_going_away ();
5503 }
5504
5505
5506 void
5507 Editor::show_editor_list (bool yn)
5508 {
5509         if (yn) {
5510                 _the_notebook.show ();
5511         } else {
5512                 _the_notebook.hide ();
5513         }
5514 }
5515
5516 void
5517 Editor::change_region_layering_order (bool from_context_menu)
5518 {
5519         const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5520
5521         if (!clicked_routeview) {
5522                 if (layering_order_editor) {
5523                         layering_order_editor->hide ();
5524                 }
5525                 return;
5526         }
5527
5528         boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5529
5530         if (!track) {
5531                 return;
5532         }
5533
5534         boost::shared_ptr<Playlist> pl = track->playlist();
5535
5536         if (!pl) {
5537                 return;
5538         }
5539
5540         if (layering_order_editor == 0) {
5541                 layering_order_editor = new RegionLayeringOrderEditor (*this);
5542         }
5543
5544         layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5545         layering_order_editor->maybe_present ();
5546 }
5547
5548 void
5549 Editor::update_region_layering_order_editor ()
5550 {
5551         if (layering_order_editor && layering_order_editor->is_visible ()) {
5552                 change_region_layering_order (true);
5553         }
5554 }
5555
5556 void
5557 Editor::setup_fade_images ()
5558 {
5559         _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5560         _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5561         _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5562         _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5563         _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5564
5565         _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5566         _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5567         _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5568         _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5569         _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5570         
5571         _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5572         _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5573         _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5574         _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5575         _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5576
5577         _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5578         _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5579         _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5580         _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5581         _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5582
5583 }
5584
5585 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5586 Gtk::MenuItem&
5587 Editor::action_menu_item (std::string const & name)
5588 {
5589         Glib::RefPtr<Action> a = editor_actions->get_action (name);
5590         assert (a);
5591
5592         return *manage (a->create_menu_item ());
5593 }
5594
5595 void
5596 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5597 {
5598         EventBox* b = manage (new EventBox);
5599         b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5600         Label* l = manage (new Label (name));
5601         l->set_angle (-90);
5602         b->add (*l);
5603         b->show_all ();
5604         _the_notebook.append_page (widget, *b);
5605 }
5606
5607 bool
5608 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5609 {
5610         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5611                 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5612         }
5613
5614         if (ev->type == GDK_2BUTTON_PRESS) {
5615
5616                 /* double-click on a notebook tab shrinks or expands the notebook */
5617
5618                 if (_notebook_shrunk) {
5619                         if (pre_notebook_shrink_pane_width) {
5620                                 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5621                         }
5622                         _notebook_shrunk = false;
5623                 } else {
5624                         pre_notebook_shrink_pane_width = edit_pane.get_position();
5625
5626                         /* this expands the LHS of the edit pane to cover the notebook
5627                            PAGE but leaves the tabs visible.
5628                          */
5629                         edit_pane.set_position (edit_pane.get_position() + page->get_width());
5630                         _notebook_shrunk = true;
5631                 }
5632         }
5633
5634         return true;
5635 }
5636
5637 void
5638 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5639 {
5640         using namespace Menu_Helpers;
5641         
5642         MenuList& items = _control_point_context_menu.items ();
5643         items.clear ();
5644         
5645         items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5646         items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5647         if (!can_remove_control_point (item)) {
5648                 items.back().set_sensitive (false);
5649         }
5650
5651         _control_point_context_menu.popup (event->button.button, event->button.time);
5652 }
5653
5654 void
5655 Editor::zoom_vertical_modifier_released()
5656 {
5657         _stepping_axis_view = 0;
5658 }
5659
5660 void
5661 Editor::ui_parameter_changed (string parameter)
5662 {
5663         if (parameter == "icon-set") {
5664                 while (!_cursor_stack.empty()) {
5665                         _cursor_stack.pop();
5666                 }
5667                 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5668         } else if (parameter == "draggable-playhead") {
5669                 if (_verbose_cursor) {
5670                         playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());
5671                 }
5672         }
5673 }