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