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