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