fix the visible_tracks_selector to show * when user tweaks a track height. various...
[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         mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2811         mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2812         
2813         if (!ARDOUR::Profile->get_trx()) {
2814                 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2815                 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2816                 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2817                 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2818                 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 4);
2819         }
2820
2821         mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2822
2823         mouse_mode_align->add (*mouse_mode_vbox);
2824         mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2825
2826         mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2827
2828         edit_mode_selector.set_name ("mouse mode button");
2829         edit_mode_selector.add_elements (ArdourButton::Inset);
2830
2831         if (!ARDOUR::Profile->get_trx()) {
2832                 mode_box->pack_start (edit_mode_selector, false, false);
2833         }
2834         mode_box->pack_start (*mouse_mode_box, false, false);
2835
2836         _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2837         _mouse_mode_tearoff->set_name ("MouseModeBase");
2838         _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2839
2840         if (Profile->get_sae() || Profile->get_mixbus() ) {
2841                 _mouse_mode_tearoff->set_can_be_torn_off (false);
2842         }
2843
2844         _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2845                                                          &_mouse_mode_tearoff->tearoff_window()));
2846         _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2847                                                          &_mouse_mode_tearoff->tearoff_window(), 1));
2848         _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2849                                                          &_mouse_mode_tearoff->tearoff_window()));
2850         _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2851                                                           &_mouse_mode_tearoff->tearoff_window(), 1));
2852
2853         /* Zoom */
2854
2855         _zoom_box.set_spacing (2);
2856         _zoom_box.set_border_width (2);
2857
2858         RefPtr<Action> act;
2859
2860         zoom_preset_selector.set_name ("zoom button");
2861         zoom_preset_selector.set_image(::get_icon ("time_exp"));
2862         zoom_preset_selector.set_size_request (42, -1);
2863
2864         zoom_in_button.set_name ("zoom button");
2865 //      zoom_in_button.add_elements ( ArdourButton::Inset );
2866         zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2867         zoom_in_button.set_image(::get_icon ("zoom_in"));
2868         act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2869         zoom_in_button.set_related_action (act);
2870
2871         zoom_out_button.set_name ("zoom button");
2872 //      zoom_out_button.add_elements ( ArdourButton::Inset );
2873         zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2874         zoom_out_button.set_image(::get_icon ("zoom_out"));
2875         act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2876         zoom_out_button.set_related_action (act);
2877
2878         zoom_out_full_button.set_name ("zoom button");
2879 //      zoom_out_full_button.add_elements ( ArdourButton::Inset );
2880         zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2881         zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2882         act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2883         zoom_out_full_button.set_related_action (act);
2884
2885         zoom_focus_selector.set_name ("zoom button");
2886 //      zoom_focus_selector.add_elements (ArdourButton::Inset);
2887
2888         if (ARDOUR::Profile->get_mixbus()) {
2889                 _zoom_box.pack_start (zoom_preset_selector, false, false);
2890         } else if (ARDOUR::Profile->get_trx()) {
2891                 mode_box->pack_start (zoom_out_button, false, false);
2892                 mode_box->pack_start (zoom_in_button, false, false);
2893         } else {
2894                 _zoom_box.pack_start (zoom_out_button, false, false);
2895                 _zoom_box.pack_start (zoom_in_button, false, false);
2896                 _zoom_box.pack_start (zoom_out_full_button, false, false);
2897                 _zoom_box.pack_start (zoom_focus_selector, false, false);
2898         }
2899
2900         /* Track zoom buttons */
2901         visible_tracks_selector.set_name ("zoom button");
2902 //      visible_tracks_selector.add_elements ( ArdourButton::Inset );
2903         if (Profile->get_mixbus()) {
2904                 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2905                 visible_tracks_selector.set_size_request (42, -1);
2906         } else {
2907                 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 40, 2);
2908         }
2909
2910         tav_expand_button.set_name ("zoom button");
2911 //      tav_expand_button.add_elements ( ArdourButton::FlatFace );
2912         tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2913         tav_expand_button.set_size_request (-1, 20);
2914         tav_expand_button.set_image(::get_icon ("tav_exp"));
2915         act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2916         tav_expand_button.set_related_action (act);
2917
2918         tav_shrink_button.set_name ("zoom button");
2919 //      tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2920         tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2921         tav_shrink_button.set_size_request (-1, 20);
2922         tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2923         act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2924         tav_shrink_button.set_related_action (act);
2925
2926         if (ARDOUR::Profile->get_mixbus()) {
2927                 _zoom_box.pack_start (visible_tracks_selector);
2928         } else if (ARDOUR::Profile->get_trx()) {
2929                 _zoom_box.pack_start (tav_shrink_button);
2930                 _zoom_box.pack_start (tav_expand_button);
2931         } else {
2932                 _zoom_box.pack_start (visible_tracks_selector);
2933                 _zoom_box.pack_start (tav_shrink_button);
2934                 _zoom_box.pack_start (tav_expand_button);
2935         }
2936
2937         if (!ARDOUR::Profile->get_trx()) {
2938                 _zoom_tearoff = manage (new TearOff (_zoom_box));
2939                 
2940                 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2941                                                            &_zoom_tearoff->tearoff_window()));
2942                 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2943                                                            &_zoom_tearoff->tearoff_window(), 0));
2944                 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2945                                                            &_zoom_tearoff->tearoff_window()));
2946                 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2947                                                             &_zoom_tearoff->tearoff_window(), 0));
2948         } 
2949
2950         if (Profile->get_sae() || Profile->get_mixbus() ) {
2951                 _zoom_tearoff->set_can_be_torn_off (false);
2952         }
2953
2954         snap_box.set_spacing (2);
2955         snap_box.set_border_width (2);
2956
2957         snap_type_selector.set_name ("mouse mode button");
2958         snap_type_selector.add_elements (ArdourButton::Inset);
2959
2960         snap_mode_selector.set_name ("mouse mode button");
2961         snap_mode_selector.add_elements (ArdourButton::Inset);
2962
2963         edit_point_selector.set_name ("mouse mode button");
2964         edit_point_selector.add_elements (ArdourButton::Inset);
2965
2966         snap_box.pack_start (snap_mode_selector, false, false);
2967         snap_box.pack_start (snap_type_selector, false, false);
2968         snap_box.pack_start (edit_point_selector, false, false);
2969
2970         /* Nudge */
2971
2972         HBox *nudge_box = manage (new HBox);
2973         nudge_box->set_spacing (2);
2974         nudge_box->set_border_width (2);
2975
2976         nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
2977         nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
2978
2979         nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2980         nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2981
2982         nudge_box->pack_start (nudge_backward_button, false, false);
2983         nudge_box->pack_start (nudge_forward_button, false, false);
2984         nudge_box->pack_start (*nudge_clock, false, false);
2985
2986
2987         /* Pack everything in... */
2988
2989         HBox* hbox = manage (new HBox);
2990         hbox->set_spacing(2);
2991
2992         _tools_tearoff = manage (new TearOff (*hbox));
2993         _tools_tearoff->set_name ("MouseModeBase");
2994         _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
2995
2996         if (Profile->get_sae() || Profile->get_mixbus()) {
2997                 _tools_tearoff->set_can_be_torn_off (false);
2998         }
2999
3000         _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3001                                                     &_tools_tearoff->tearoff_window()));
3002         _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3003                                                     &_tools_tearoff->tearoff_window(), 0));
3004         _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3005                                                     &_tools_tearoff->tearoff_window()));
3006         _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3007                                                      &_tools_tearoff->tearoff_window(), 0));
3008
3009         toolbar_hbox.set_spacing (2);
3010         toolbar_hbox.set_border_width (1);
3011
3012         toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3013         if (!ARDOUR::Profile->get_trx()) {
3014                 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3015                 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3016         }
3017
3018         if (!ARDOUR::Profile->get_trx()) {
3019                 hbox->pack_start (snap_box, false, false);
3020                 if (!Profile->get_small_screen()) {
3021                         hbox->pack_start (*nudge_box, false, false);
3022                 } else {
3023                         ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3024                 }
3025         }
3026         hbox->pack_start (panic_box, false, false);
3027
3028         hbox->show_all ();
3029
3030         toolbar_base.set_name ("ToolBarBase");
3031         toolbar_base.add (toolbar_hbox);
3032
3033         _toolbar_viewport.add (toolbar_base);
3034         /* stick to the required height but allow width to vary if there's not enough room */
3035         _toolbar_viewport.set_size_request (1, -1);
3036
3037         toolbar_frame.set_shadow_type (SHADOW_OUT);
3038         toolbar_frame.set_name ("BaseFrame");
3039         toolbar_frame.add (_toolbar_viewport);
3040 }
3041
3042 void
3043 Editor::build_edit_point_menu ()
3044 {
3045         using namespace Menu_Helpers;
3046
3047         edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3048         if(!Profile->get_mixbus())
3049                 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3050         edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3051
3052         set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, 30, 2);
3053 }
3054
3055 void
3056 Editor::build_edit_mode_menu ()
3057 {
3058         using namespace Menu_Helpers;
3059         
3060         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3061 //      edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3062         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3063         edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode)  Lock)));
3064
3065         set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, 30, 2);
3066 }
3067
3068 void
3069 Editor::build_snap_mode_menu ()
3070 {
3071         using namespace Menu_Helpers;
3072
3073         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3074         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3075         snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3076
3077         set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, 34, 2);
3078 }
3079
3080 void
3081 Editor::build_snap_type_menu ()
3082 {
3083         using namespace Menu_Helpers;
3084
3085         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3086         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3087         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3088         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3089         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3090         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3091         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3092         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3093         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3094         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3095         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3096         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3097         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3098         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3099         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3100         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3101         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3102         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3103         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3104         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3105         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3106         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3107         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3108         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3109         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3110         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3111         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3112         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3113         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3114         snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3115
3116         set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, 34, 2);
3117
3118 }
3119
3120 void
3121 Editor::setup_tooltips ()
3122 {
3123         ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3124         ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3125         ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
3126         ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3127         ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3128         ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3129         ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3130         ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3131         ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3132         ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3133         ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3134         ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3135         ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3136         ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3137         ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3138         ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3139         ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3140         ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3141         ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3142         ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3143         ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3144         ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3145         ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3146         ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3147         ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3148         ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3149 }
3150
3151 int
3152 Editor::convert_drop_to_paths (
3153                 vector<string>&                paths,
3154                 const RefPtr<Gdk::DragContext>& /*context*/,
3155                 gint                            /*x*/,
3156                 gint                            /*y*/,
3157                 const SelectionData&            data,
3158                 guint                           /*info*/,
3159                 guint                           /*time*/)
3160 {
3161         if (_session == 0) {
3162                 return -1;
3163         }
3164
3165         vector<string> uris = data.get_uris();
3166
3167         if (uris.empty()) {
3168
3169                 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3170                    are actually URI lists. So do it by hand.
3171                 */
3172
3173                 if (data.get_target() != "text/plain") {
3174                         return -1;
3175                 }
3176
3177                 /* Parse the "uri-list" format that Nautilus provides,
3178                    where each pathname is delimited by \r\n.
3179
3180                    THERE MAY BE NO NULL TERMINATING CHAR!!!
3181                 */
3182
3183                 string txt = data.get_text();
3184                 char* p;
3185                 const char* q;
3186
3187                 p = (char *) malloc (txt.length() + 1);
3188                 txt.copy (p, txt.length(), 0);
3189                 p[txt.length()] = '\0';
3190
3191                 while (p)
3192                 {
3193                         if (*p != '#')
3194                         {
3195                                 while (g_ascii_isspace (*p))
3196                                         p++;
3197
3198                                 q = p;
3199                                 while (*q && (*q != '\n') && (*q != '\r')) {
3200                                         q++;
3201                                 }
3202
3203                                 if (q > p)
3204                                 {
3205                                         q--;
3206                                         while (q > p && g_ascii_isspace (*q))
3207                                                 q--;
3208
3209                                         if (q > p)
3210                                         {
3211                                                 uris.push_back (string (p, q - p + 1));
3212                                         }
3213                                 }
3214                         }
3215                         p = strchr (p, '\n');
3216                         if (p)
3217                                 p++;
3218                 }
3219
3220                 free ((void*)p);
3221
3222                 if (uris.empty()) {
3223                         return -1;
3224                 }
3225         }
3226
3227         for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3228                 if ((*i).substr (0,7) == "file://") {
3229                         paths.push_back (Glib::filename_from_uri (*i));
3230                 }
3231         }
3232
3233         return 0;
3234 }
3235
3236 void
3237 Editor::new_tempo_section ()
3238 {
3239 }
3240
3241 void
3242 Editor::map_transport_state ()
3243 {
3244         ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3245
3246         if (_session && _session->transport_stopped()) {
3247                 have_pending_keyboard_selection = false;
3248         }
3249
3250         update_loop_range_view ();
3251 }
3252
3253 /* UNDO/REDO */
3254
3255 void
3256 Editor::begin_reversible_command (string name)
3257 {
3258         if (_session) {
3259                 _session->begin_reversible_command (name);
3260         }
3261 }
3262
3263 void
3264 Editor::begin_reversible_command (GQuark q)
3265 {
3266         if (_session) {
3267                 _session->begin_reversible_command (q);
3268         }
3269 }
3270
3271 void
3272 Editor::commit_reversible_command ()
3273 {
3274         if (_session) {
3275                 _session->commit_reversible_command ();
3276         }
3277 }
3278
3279 void
3280 Editor::history_changed ()
3281 {
3282         string label;
3283
3284         if (undo_action && _session) {
3285                 if (_session->undo_depth() == 0) {
3286                         label = S_("Command|Undo");
3287                 } else {
3288                         label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3289                 }
3290                 undo_action->property_label() = label;
3291         }
3292
3293         if (redo_action && _session) {
3294                 if (_session->redo_depth() == 0) {
3295                         label = _("Redo");
3296                 } else {
3297                         label = string_compose(_("Redo (%1)"), _session->next_redo());
3298                 }
3299                 redo_action->property_label() = label;
3300         }
3301 }
3302
3303 void
3304 Editor::duplicate_range (bool with_dialog)
3305 {
3306         float times = 1.0f;
3307
3308         RegionSelection rs = get_regions_from_selection_and_entered ();
3309
3310         if ( selection->time.length() == 0 && rs.empty()) {
3311                 return;
3312         }
3313
3314         if (with_dialog) {
3315
3316                 ArdourDialog win (_("Duplicate"));
3317                 Label label (_("Number of duplications:"));
3318                 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3319                 SpinButton spinner (adjustment, 0.0, 1);
3320                 HBox hbox;
3321
3322                 win.get_vbox()->set_spacing (12);
3323                 win.get_vbox()->pack_start (hbox);
3324                 hbox.set_border_width (6);
3325                 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3326
3327                 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3328                    place, visually. so do this by hand.
3329                 */
3330
3331                 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3332                 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3333                 spinner.grab_focus();
3334
3335                 hbox.show ();
3336                 label.show ();
3337                 spinner.show ();
3338
3339                 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3340                 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3341                 win.set_default_response (RESPONSE_ACCEPT);
3342
3343                 spinner.grab_focus ();
3344
3345                 switch (win.run ()) {
3346                 case RESPONSE_ACCEPT:
3347                         break;
3348                 default:
3349                         return;
3350                 }
3351
3352                 times = adjustment.get_value();
3353         }
3354
3355         if ((current_mouse_mode() == Editing::MouseRange)) {
3356                 if (selection->time.length()) {
3357                         duplicate_selection (times);
3358                 }
3359         } else if (get_smart_mode()) {
3360                 if (selection->time.length()) {
3361                         duplicate_selection (times);
3362                 } else 
3363                         duplicate_some_regions (rs, times);
3364         } else {
3365                 duplicate_some_regions (rs, times);
3366         }
3367 }
3368
3369 void
3370 Editor::set_edit_mode (EditMode m)
3371 {
3372         Config->set_edit_mode (m);
3373 }
3374
3375 void
3376 Editor::cycle_edit_mode ()
3377 {
3378         switch (Config->get_edit_mode()) {
3379         case Slide:
3380                 if (Profile->get_sae()) {
3381                         Config->set_edit_mode (Lock);
3382                 } else {
3383                         Config->set_edit_mode (Ripple);
3384                 }
3385                 break;
3386         case Splice:
3387         case Ripple:
3388                 Config->set_edit_mode (Lock);
3389                 break;
3390         case Lock:
3391                 Config->set_edit_mode (Slide);
3392                 break;
3393         }
3394 }
3395
3396 void
3397 Editor::edit_mode_selection_done ( EditMode m )
3398 {
3399         Config->set_edit_mode ( m );
3400 }
3401
3402 void
3403 Editor::snap_type_selection_done (SnapType snaptype)
3404 {
3405         RefPtr<RadioAction> ract = snap_type_action (snaptype);
3406         if (ract) {
3407                 ract->set_active ();
3408         }
3409 }
3410
3411 void
3412 Editor::snap_mode_selection_done (SnapMode mode)
3413 {
3414         RefPtr<RadioAction> ract = snap_mode_action (mode);
3415
3416         if (ract) {
3417                 ract->set_active (true);
3418         }
3419 }
3420
3421 void
3422 Editor::cycle_edit_point (bool with_marker)
3423 {
3424         if(Profile->get_mixbus())
3425                 with_marker = false;
3426
3427         switch (_edit_point) {
3428         case EditAtMouse:
3429                 set_edit_point_preference (EditAtPlayhead);
3430                 break;
3431         case EditAtPlayhead:
3432                 if (with_marker) {
3433                         set_edit_point_preference (EditAtSelectedMarker);
3434                 } else {
3435                         set_edit_point_preference (EditAtMouse);
3436                 }
3437                 break;
3438         case EditAtSelectedMarker:
3439                 set_edit_point_preference (EditAtMouse);
3440                 break;
3441         }
3442 }
3443
3444 void
3445 Editor::edit_point_selection_done (EditPoint ep)
3446 {
3447         set_edit_point_preference ( ep );
3448 }
3449
3450 void
3451 Editor::build_zoom_focus_menu ()
3452 {
3453         using namespace Menu_Helpers;
3454
3455         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3456         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3457         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3458         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3459         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3460         zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3461
3462         set_size_request_to_display_given_text (zoom_focus_selector, longest (zoom_focus_strings), 30, 2);
3463 }
3464
3465 void
3466 Editor::zoom_focus_selection_done ( ZoomFocus f )
3467 {
3468         RefPtr<RadioAction> ract = zoom_focus_action (f);
3469         if (ract) {
3470                 ract->set_active ();
3471         }
3472 }
3473
3474 void
3475 Editor::build_track_count_menu ()
3476 {
3477         using namespace Menu_Helpers;
3478
3479         if (!Profile->get_mixbus()) {
3480                 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3481                 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3482                 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3483                 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3484                 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3485                 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3486                 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3487                 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3488                 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3489                 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3490                 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3491                 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3492         } else {
3493                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit current tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3494                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3495                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3496                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3497                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3498                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3499                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3500                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3501                 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3502
3503                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), -1)));
3504                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3505                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3506                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3507                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3508                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3509                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3510                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3511                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3512                 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3513         }
3514 }
3515
3516 void
3517 Editor::set_zoom_preset (int64_t ms)
3518 {
3519         if ( ms <= 0 ) {
3520                 temporal_zoom_session();
3521                 return;
3522         }
3523         
3524         ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3525         temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3526 }
3527
3528 void
3529 Editor::set_visible_track_count (int32_t n)
3530 {
3531         _visible_track_count = n;
3532
3533         /* if the canvas hasn't really been allocated any size yet, just
3534            record the desired number of visible tracks and return. when canvas
3535            allocation happens, we will get called again and then we can do the
3536            real work.
3537         */
3538         
3539         if (_visible_canvas_height <= 1) {
3540                 return;
3541         }
3542
3543         int h;
3544         string str;
3545
3546         if (_visible_track_count > 0) {
3547                 h = _visible_canvas_height / _visible_track_count;
3548                 std::ostringstream s;
3549                 s << _visible_track_count;
3550                 str = s.str();
3551         } else if (_visible_track_count == 0) {
3552                 h = _visible_canvas_height / track_views.size();
3553                 str = _("all");
3554         } else {
3555                 /* negative value means that the visible track count has 
3556                    been overridden by explicit track height changes.
3557                 */
3558                 visible_tracks_selector.set_text (X_("*"));
3559                 return;
3560         }
3561
3562         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3563                 (*i)->set_height (h);
3564         }
3565         
3566         if (str != visible_tracks_selector.get_text()) {
3567                 visible_tracks_selector.set_text (str);
3568         }
3569 }
3570
3571 void
3572 Editor::override_visible_track_count ()
3573 {
3574         _visible_track_count = -_visible_track_count;
3575         visible_tracks_selector.set_text ( _("*") );
3576 }
3577
3578 bool
3579 Editor::edit_controls_button_release (GdkEventButton* ev)
3580 {
3581         if (Keyboard::is_context_menu_event (ev)) {
3582                 ARDOUR_UI::instance()->add_route (this);
3583         } else if (ev->button == 1) {
3584                 selection->clear_tracks ();
3585         }
3586
3587         return true;
3588 }
3589
3590 bool
3591 Editor::mouse_select_button_release (GdkEventButton* ev)
3592 {
3593         /* this handles just right-clicks */
3594
3595         if (ev->button != 3) {
3596                 return false;
3597         }
3598
3599         return true;
3600 }
3601
3602 void
3603 Editor::set_zoom_focus (ZoomFocus f)
3604 {
3605         string str = zoom_focus_strings[(int)f];
3606
3607         if (str != zoom_focus_selector.get_text()) {
3608                 zoom_focus_selector.set_text (str);
3609         }
3610
3611         if (zoom_focus != f) {
3612                 zoom_focus = f;
3613                 instant_save ();
3614         }
3615 }
3616
3617 void
3618 Editor::cycle_zoom_focus ()
3619 {
3620         switch (zoom_focus) {
3621         case ZoomFocusLeft:
3622                 set_zoom_focus (ZoomFocusRight);
3623                 break;
3624         case ZoomFocusRight:
3625                 set_zoom_focus (ZoomFocusCenter);
3626                 break;
3627         case ZoomFocusCenter:
3628                 set_zoom_focus (ZoomFocusPlayhead);
3629                 break;
3630         case ZoomFocusPlayhead:
3631                 set_zoom_focus (ZoomFocusMouse);
3632                 break;
3633         case ZoomFocusMouse:
3634                 set_zoom_focus (ZoomFocusEdit);
3635                 break;
3636         case ZoomFocusEdit:
3637                 set_zoom_focus (ZoomFocusLeft);
3638                 break;
3639         }
3640 }
3641
3642 void
3643 Editor::ensure_float (Window& win)
3644 {
3645         win.set_transient_for (*this);
3646 }
3647
3648 void
3649 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3650 {
3651         /* recover or initialize pane positions. do this here rather than earlier because
3652            we don't want the positions to change the child allocations, which they seem to do.
3653          */
3654
3655         int pos;
3656         XMLProperty* prop;
3657         char buf[32];
3658         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3659
3660         enum Pane {
3661                 Horizontal = 0x1,
3662                 Vertical = 0x2
3663         };
3664
3665         static Pane done;
3666
3667         XMLNode* geometry = find_named_node (*node, "geometry");
3668
3669         if (which == static_cast<Paned*> (&edit_pane)) {
3670
3671                 if (done & Horizontal) {
3672                         return;
3673                 }
3674
3675                 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3676                         _notebook_shrunk = string_is_affirmative (prop->value ());
3677                 }
3678
3679                 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3680                         /* initial allocation is 90% to canvas, 10% to notebook */
3681                         pos = (int) floor (alloc.get_width() * 0.90f);
3682                         snprintf (buf, sizeof(buf), "%d", pos);
3683                 } else {
3684                         pos = atoi (prop->value());
3685                 }
3686
3687                 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3688                         edit_pane.set_position (pos);
3689                 }
3690
3691                 done = (Pane) (done | Horizontal);
3692
3693         } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3694
3695                 if (done & Vertical) {
3696                         return;
3697                 }
3698
3699                 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3700                         /* initial allocation is 90% to canvas, 10% to summary */
3701                         pos = (int) floor (alloc.get_height() * 0.90f);
3702                         snprintf (buf, sizeof(buf), "%d", pos);
3703                 } else {
3704
3705                         pos = atoi (prop->value());
3706                 }
3707
3708                 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3709                         editor_summary_pane.set_position (pos);
3710                 }
3711
3712                 done = (Pane) (done | Vertical);
3713         }
3714 }
3715
3716 void
3717 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3718 {
3719         if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) && 
3720             (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) && 
3721             (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3722                 top_hbox.remove (toolbar_frame);
3723         }
3724 }
3725
3726 void
3727 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3728 {
3729         if (toolbar_frame.get_parent() == 0) {
3730                 top_hbox.pack_end (toolbar_frame);
3731         }
3732 }
3733
3734 void
3735 Editor::set_show_measures (bool yn)
3736 {
3737         if (_show_measures != yn) {
3738                 hide_measures ();
3739
3740                 if ((_show_measures = yn) == true) {
3741                         if (tempo_lines) {
3742                                 tempo_lines->show();
3743                         }
3744
3745                         ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3746                         ARDOUR::TempoMap::BBTPointList::const_iterator end;
3747                         
3748                         compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3749                         draw_measures (begin, end);
3750                 } 
3751
3752                 instant_save ();
3753         }
3754 }
3755
3756 void
3757 Editor::toggle_follow_playhead ()
3758 {
3759         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3760         if (act) {
3761                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3762                 set_follow_playhead (tact->get_active());
3763         }
3764 }
3765
3766 /** @param yn true to follow playhead, otherwise false.
3767  *  @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3768  */
3769 void
3770 Editor::set_follow_playhead (bool yn, bool catch_up)
3771 {
3772         if (_follow_playhead != yn) {
3773                 if ((_follow_playhead = yn) == true && catch_up) {
3774                         /* catch up */
3775                         reset_x_origin_to_follow_playhead ();
3776                 }
3777                 instant_save ();
3778         }
3779 }
3780
3781 void
3782 Editor::toggle_stationary_playhead ()
3783 {
3784         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3785         if (act) {
3786                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3787                 set_stationary_playhead (tact->get_active());
3788         }
3789 }
3790
3791 void
3792 Editor::set_stationary_playhead (bool yn)
3793 {
3794         if (_stationary_playhead != yn) {
3795                 if ((_stationary_playhead = yn) == true) {
3796                         /* catch up */
3797                         // FIXME need a 3.0 equivalent of this 2.X call
3798                         // update_current_screen ();
3799                 }
3800                 instant_save ();
3801         }
3802 }
3803
3804 PlaylistSelector&
3805 Editor::playlist_selector () const
3806 {
3807         return *_playlist_selector;
3808 }
3809
3810 Evoral::MusicalTime
3811 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3812 {
3813         success = true;
3814
3815         switch (_snap_type) {
3816         case SnapToBeat:
3817                 return 1.0;
3818                 break;
3819
3820         case SnapToBeatDiv128:
3821                 return 1.0/128.0;
3822                 break;
3823         case SnapToBeatDiv64:
3824                 return 1.0/64.0;
3825                 break;
3826         case SnapToBeatDiv32:
3827                 return 1.0/32.0;
3828                 break;
3829         case SnapToBeatDiv28:
3830                 return 1.0/28.0;
3831                 break;
3832         case SnapToBeatDiv24:
3833                 return 1.0/24.0;
3834                 break;
3835         case SnapToBeatDiv20:
3836                 return 1.0/20.0;
3837                 break;
3838         case SnapToBeatDiv16:
3839                 return 1.0/16.0;
3840                 break;
3841         case SnapToBeatDiv14:
3842                 return 1.0/14.0;
3843                 break;
3844         case SnapToBeatDiv12:
3845                 return 1.0/12.0;
3846                 break;
3847         case SnapToBeatDiv10:
3848                 return 1.0/10.0;
3849                 break;
3850         case SnapToBeatDiv8:
3851                 return 1.0/8.0;
3852                 break;
3853         case SnapToBeatDiv7:
3854                 return 1.0/7.0;
3855                 break;
3856         case SnapToBeatDiv6:
3857                 return 1.0/6.0;
3858                 break;
3859         case SnapToBeatDiv5:
3860                 return 1.0/5.0;
3861                 break;
3862         case SnapToBeatDiv4:
3863                 return 1.0/4.0;
3864                 break;
3865         case SnapToBeatDiv3:
3866                 return 1.0/3.0;
3867                 break;
3868         case SnapToBeatDiv2:
3869                 return 1.0/2.0;
3870                 break;
3871
3872         case SnapToBar:
3873                 if (_session) {
3874                         return _session->tempo_map().meter_at (position).divisions_per_bar();
3875                 }
3876                 break;
3877
3878         case SnapToCDFrame:
3879         case SnapToTimecodeFrame:
3880         case SnapToTimecodeSeconds:
3881         case SnapToTimecodeMinutes:
3882         case SnapToSeconds:
3883         case SnapToMinutes:
3884         case SnapToRegionStart:
3885         case SnapToRegionEnd:
3886         case SnapToRegionSync:
3887         case SnapToRegionBoundary:
3888         default:
3889                 success = false;
3890                 break;
3891         }
3892
3893         return 0.0;
3894 }
3895
3896 framecnt_t
3897 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3898 {
3899         framecnt_t ret;
3900
3901         ret = nudge_clock->current_duration (pos);
3902         next = ret + 1; /* XXXX fix me */
3903
3904         return ret;
3905 }
3906
3907 int
3908 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3909 {
3910         ArdourDialog dialog (_("Playlist Deletion"));
3911         Label  label (string_compose (_("Playlist %1 is currently unused.\n"
3912                                         "If it is kept, its audio files will not be cleaned.\n"
3913                                         "If it is deleted, audio files used by it alone will be cleaned."),
3914                                       pl->name()));
3915
3916         dialog.set_position (WIN_POS_CENTER);
3917         dialog.get_vbox()->pack_start (label);
3918
3919         label.show ();
3920
3921         dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3922         dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3923         dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3924
3925         switch (dialog.run ()) {
3926         case RESPONSE_ACCEPT:
3927                 /* delete the playlist */
3928                 return 0;
3929                 break;
3930
3931         case RESPONSE_REJECT:
3932                 /* keep the playlist */
3933                 return 1;
3934                 break;
3935
3936         default:
3937                 break;
3938         }
3939
3940         return -1;
3941 }
3942
3943 bool
3944 Editor::audio_region_selection_covers (framepos_t where)
3945 {
3946         for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3947                 if ((*a)->region()->covers (where)) {
3948                         return true;
3949                 }
3950         }
3951
3952         return false;
3953 }
3954
3955 void
3956 Editor::prepare_for_cleanup ()
3957 {
3958         cut_buffer->clear_regions ();
3959         cut_buffer->clear_playlists ();
3960
3961         selection->clear_regions ();
3962         selection->clear_playlists ();
3963
3964         _regions->suspend_redisplay ();
3965 }
3966
3967 void
3968 Editor::finish_cleanup ()
3969 {
3970         _regions->resume_redisplay ();
3971 }
3972
3973 Location*
3974 Editor::transport_loop_location()
3975 {
3976         if (_session) {
3977                 return _session->locations()->auto_loop_location();
3978         } else {
3979                 return 0;
3980         }
3981 }
3982
3983 Location*
3984 Editor::transport_punch_location()
3985 {
3986         if (_session) {
3987                 return _session->locations()->auto_punch_location();
3988         } else {
3989                 return 0;
3990         }
3991 }
3992
3993 bool
3994 Editor::control_layout_scroll (GdkEventScroll* ev)
3995 {
3996         /* Just forward to the normal canvas scroll method. The coordinate
3997            systems are different but since the canvas is always larger than the
3998            track headers, and aligned with the trackview area, this will work.
3999
4000            In the not too distant future this layout is going away anyway and
4001            headers will be on the canvas.
4002         */
4003         return canvas_scroll_event (ev, false);
4004 }
4005
4006 void
4007 Editor::session_state_saved (string)
4008 {
4009         update_title ();
4010         _snapshots->redisplay ();
4011 }
4012
4013 void
4014 Editor::update_tearoff_visibility()
4015 {
4016         bool visible = Config->get_keep_tearoffs();
4017         _mouse_mode_tearoff->set_visible (visible);
4018         _tools_tearoff->set_visible (visible);
4019         if (_zoom_tearoff) {
4020                 _zoom_tearoff->set_visible (visible);
4021         }
4022 }
4023
4024 void
4025 Editor::maximise_editing_space ()
4026 {
4027         if (_maximised) {
4028                 return;
4029         }
4030
4031         fullscreen ();
4032
4033         _maximised = true;
4034 }
4035
4036 void
4037 Editor::restore_editing_space ()
4038 {
4039         if (!_maximised) {
4040                 return;
4041         }
4042
4043         unfullscreen();
4044
4045         _maximised = false;
4046 }
4047
4048 /**
4049  *  Make new playlists for a given track and also any others that belong
4050  *  to the same active route group with the `select' property.
4051  *  @param v Track.
4052  */
4053
4054 void
4055 Editor::new_playlists (TimeAxisView* v)
4056 {
4057         begin_reversible_command (_("new playlists"));
4058         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4059         _session->playlists->get (playlists);
4060         mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4061         commit_reversible_command ();
4062 }
4063
4064 /**
4065  *  Use a copy of the current playlist for a given track and also any others that belong
4066  *  to the same active route group with the `select' property.
4067  *  @param v Track.
4068  */
4069
4070 void
4071 Editor::copy_playlists (TimeAxisView* v)
4072 {
4073         begin_reversible_command (_("copy playlists"));
4074         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4075         _session->playlists->get (playlists);
4076         mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4077         commit_reversible_command ();
4078 }
4079
4080 /** Clear the current playlist for a given track and also any others that belong
4081  *  to the same active route group with the `select' property.
4082  *  @param v Track.
4083  */
4084
4085 void
4086 Editor::clear_playlists (TimeAxisView* v)
4087 {
4088         begin_reversible_command (_("clear playlists"));
4089         vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4090         _session->playlists->get (playlists);
4091         mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4092         commit_reversible_command ();
4093 }
4094
4095 void
4096 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4097 {
4098         atv.use_new_playlist (sz > 1 ? false : true, playlists);
4099 }
4100
4101 void
4102 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4103 {
4104         atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4105 }
4106
4107 void
4108 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4109 {
4110         atv.clear_playlist ();
4111 }
4112
4113 bool
4114 Editor::on_key_press_event (GdkEventKey* ev)
4115 {
4116         return key_press_focus_accelerator_handler (*this, ev);
4117 }
4118
4119 bool
4120 Editor::on_key_release_event (GdkEventKey* ev)
4121 {
4122         return Gtk::Window::on_key_release_event (ev);
4123         // return key_press_focus_accelerator_handler (*this, ev);
4124 }
4125
4126 /** Queue up a change to the viewport x origin.
4127  *  @param frame New x origin.
4128  */
4129 void
4130 Editor::reset_x_origin (framepos_t frame)
4131 {
4132         pending_visual_change.add (VisualChange::TimeOrigin);
4133         pending_visual_change.time_origin = frame;
4134         ensure_visual_change_idle_handler ();
4135 }
4136
4137 void
4138 Editor::reset_y_origin (double y)
4139 {
4140         pending_visual_change.add (VisualChange::YOrigin);
4141         pending_visual_change.y_origin = y;
4142         ensure_visual_change_idle_handler ();
4143 }
4144
4145 void
4146 Editor::reset_zoom (framecnt_t spp)
4147 {
4148         if (spp == samples_per_pixel) {
4149                 return;
4150         }
4151
4152         pending_visual_change.add (VisualChange::ZoomLevel);
4153         pending_visual_change.samples_per_pixel = spp;
4154         ensure_visual_change_idle_handler ();
4155 }
4156
4157 void
4158 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4159 {
4160         reset_x_origin (frame);
4161         reset_zoom (fpu);
4162
4163         if (!no_save_visual) {
4164                 undo_visual_stack.push_back (current_visual_state(false));
4165         }
4166 }
4167
4168 Editor::VisualState::VisualState (bool with_tracks)
4169         : gui_state (with_tracks ? new GUIObjectState : 0)
4170 {
4171 }
4172
4173 Editor::VisualState::~VisualState ()
4174 {
4175         delete gui_state;
4176 }
4177
4178 Editor::VisualState*
4179 Editor::current_visual_state (bool with_tracks)
4180 {
4181         VisualState* vs = new VisualState (with_tracks);
4182         vs->y_position = vertical_adjustment.get_value();
4183         vs->samples_per_pixel = samples_per_pixel;
4184         vs->leftmost_frame = leftmost_frame;
4185         vs->zoom_focus = zoom_focus;
4186
4187         if (with_tracks) {      
4188                 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4189         }
4190
4191         return vs;
4192 }
4193
4194 void
4195 Editor::undo_visual_state ()
4196 {
4197         if (undo_visual_stack.empty()) {
4198                 return;
4199         }
4200
4201         VisualState* vs = undo_visual_stack.back();
4202         undo_visual_stack.pop_back();
4203
4204
4205         redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4206
4207         use_visual_state (*vs);
4208 }
4209
4210 void
4211 Editor::redo_visual_state ()
4212 {
4213         if (redo_visual_stack.empty()) {
4214                 return;
4215         }
4216
4217         VisualState* vs = redo_visual_stack.back();
4218         redo_visual_stack.pop_back();
4219
4220         undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4221
4222         use_visual_state (*vs);
4223 }
4224
4225 void
4226 Editor::swap_visual_state ()
4227 {
4228         if (undo_visual_stack.empty()) {
4229                 redo_visual_state ();
4230         } else {
4231                 undo_visual_state ();
4232         }
4233 }
4234
4235 void
4236 Editor::use_visual_state (VisualState& vs)
4237 {
4238         PBD::Unwinder<bool> nsv (no_save_visual, true);
4239         DisplaySuspender ds;
4240
4241         vertical_adjustment.set_value (vs.y_position);
4242
4243         set_zoom_focus (vs.zoom_focus);
4244         reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4245         
4246         if (vs.gui_state) {
4247                 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4248                 
4249                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {    
4250                         (*i)->reset_visual_state ();
4251                 }
4252         }
4253
4254         _routes->update_visibility ();
4255 }
4256
4257 /** This is the core function that controls the zoom level of the canvas. It is called
4258  *  whenever one or more calls are made to reset_zoom().  It executes in an idle handler.
4259  *  @param spp new number of samples per pixel
4260  */
4261 void
4262 Editor::set_samples_per_pixel (framecnt_t spp)
4263 {
4264         if (spp < 1) {
4265                 return;
4266         }
4267
4268         const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4269         const framecnt_t lots_of_pixels = 4000;
4270
4271         /* if the zoom level is greater than what you'd get trying to display 3
4272          * days of audio on a really big screen, then it's too big.
4273          */
4274
4275         if (spp * lots_of_pixels > three_days) {
4276                 return;
4277         }
4278
4279         samples_per_pixel = spp;
4280
4281         if (tempo_lines) {
4282                 tempo_lines->tempo_map_changed();
4283         }
4284
4285         bool const showing_time_selection = selection->time.length() > 0;
4286
4287         if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4288                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4289                         (*i)->reshow_selection (selection->time);
4290                 }
4291         }
4292
4293         ZoomChanged (); /* EMIT_SIGNAL */
4294
4295         ArdourCanvas::GtkCanvasViewport* c;
4296
4297         c = get_track_canvas();
4298         if (c) {
4299                 c->canvas()->zoomed ();
4300         }
4301
4302         if (playhead_cursor) {
4303                 playhead_cursor->set_position (playhead_cursor->current_frame ());
4304         }
4305
4306         refresh_location_display();
4307         _summary->set_overlays_dirty ();
4308
4309         update_marker_labels ();
4310
4311         instant_save ();
4312 }
4313
4314 void
4315 Editor::queue_visual_videotimeline_update ()
4316 {
4317         /* TODO:
4318          * pending_visual_change.add (VisualChange::VideoTimeline);
4319          * or maybe even more specific: which videotimeline-image
4320          * currently it calls update_video_timeline() to update
4321          * _all outdated_ images on the video-timeline.
4322          * see 'exposeimg()' in video_image_frame.cc
4323          */
4324         ensure_visual_change_idle_handler ();
4325 }
4326
4327 void
4328 Editor::ensure_visual_change_idle_handler ()
4329 {
4330         if (pending_visual_change.idle_handler_id < 0) {
4331                 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4332                 pending_visual_change.being_handled = false;
4333         }
4334 }
4335
4336 int
4337 Editor::_idle_visual_changer (void* arg)
4338 {
4339         return static_cast<Editor*>(arg)->idle_visual_changer ();
4340 }
4341
4342 int
4343 Editor::idle_visual_changer ()
4344 {
4345         /* set_horizontal_position() below (and maybe other calls) call
4346            gtk_main_iteration(), so it's possible that a signal will be handled
4347            half-way through this method.  If this signal wants an
4348            idle_visual_changer we must schedule another one after this one, so
4349            mark the idle_handler_id as -1 here to allow that.  Also make a note
4350            that we are doing the visual change, so that changes in response to
4351            super-rapid-screen-update can be dropped if we are still processing
4352            the last one.
4353         */
4354
4355         pending_visual_change.idle_handler_id = -1;
4356         pending_visual_change.being_handled = true;
4357         
4358         VisualChange vc = pending_visual_change;
4359
4360         pending_visual_change.pending = (VisualChange::Type) 0;
4361
4362         visual_changer (vc);
4363
4364         pending_visual_change.being_handled = false;
4365
4366         return 0; /* this is always a one-shot call */
4367 }
4368
4369 void
4370 Editor::visual_changer (const VisualChange& vc)
4371 {
4372         double const last_time_origin = horizontal_position ();
4373
4374         if (vc.pending & VisualChange::ZoomLevel) {
4375                 set_samples_per_pixel (vc.samples_per_pixel);
4376
4377                 compute_fixed_ruler_scale ();
4378
4379                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4380                 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4381                 
4382                 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4383                                             current_bbt_points_begin, current_bbt_points_end);
4384                 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4385                                          current_bbt_points_begin, current_bbt_points_end);
4386                 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4387
4388                 update_video_timeline();
4389         }
4390
4391         if (vc.pending & VisualChange::TimeOrigin) {
4392                 set_horizontal_position (vc.time_origin / samples_per_pixel);
4393         }
4394
4395         if (vc.pending & VisualChange::YOrigin) {
4396                 vertical_adjustment.set_value (vc.y_origin);
4397         }
4398
4399         if (last_time_origin == horizontal_position ()) {
4400                 /* changed signal not emitted */
4401                 update_fixed_rulers ();
4402                 redisplay_tempo (true);
4403         }
4404
4405         if (!(vc.pending & VisualChange::ZoomLevel)) {
4406                 update_video_timeline();
4407         }
4408
4409         _summary->set_overlays_dirty ();
4410 }
4411
4412 struct EditorOrderTimeAxisSorter {
4413     bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4414             return a->order () < b->order ();
4415     }
4416 };
4417
4418 void
4419 Editor::sort_track_selection (TrackViewList& sel)
4420 {
4421         EditorOrderTimeAxisSorter cmp;
4422         sel.sort (cmp);
4423 }
4424
4425 framepos_t
4426 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4427 {
4428         bool ignored;
4429         framepos_t where = 0;
4430         EditPoint ep = _edit_point;
4431
4432         if(Profile->get_mixbus())
4433                 if (ep == EditAtSelectedMarker)
4434                         ep=EditAtPlayhead;
4435                 
4436         if (from_context_menu && (ep == EditAtMouse)) {
4437                 return  canvas_event_sample (&context_click_event, 0, 0);
4438         }
4439
4440         if (entered_marker) {
4441                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4442                 return entered_marker->position();
4443         }
4444
4445         if (ignore_playhead && ep == EditAtPlayhead) {
4446                 ep = EditAtSelectedMarker;
4447         }
4448
4449         switch (ep) {
4450         case EditAtPlayhead:
4451                 where = _session->audible_frame();
4452                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4453                 break;
4454
4455         case EditAtSelectedMarker:
4456                 if (!selection->markers.empty()) {
4457                         bool is_start;
4458                         Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4459                         if (loc) {
4460                                 if (is_start) {
4461                                         where =  loc->start();
4462                                 } else {
4463                                         where = loc->end();
4464                                 }
4465                                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4466                                 break;
4467                         }
4468                 }
4469                 /* fallthru */
4470
4471         default:
4472         case EditAtMouse:
4473                 if (!mouse_frame (where, ignored)) {
4474                         /* XXX not right but what can we do ? */
4475                         return 0;
4476                 }
4477                 snap_to (where);
4478                 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4479                 break;
4480         }
4481
4482         return where;
4483 }
4484
4485 void
4486 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4487 {
4488         if (!_session) return;
4489
4490         begin_reversible_command (cmd);
4491
4492         Location* tll;
4493
4494         if ((tll = transport_loop_location()) == 0) {
4495                 Location* loc = new Location (*_session, start, end, _("Loop"),  Location::IsAutoLoop);
4496                 XMLNode &before = _session->locations()->get_state();
4497                 _session->locations()->add (loc, true);
4498                 _session->set_auto_loop_location (loc);
4499                 XMLNode &after = _session->locations()->get_state();
4500                 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4501         } else {
4502                 XMLNode &before = tll->get_state();
4503                 tll->set_hidden (false, this);
4504                 tll->set (start, end);
4505                 XMLNode &after = tll->get_state();
4506                 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4507         }
4508
4509         commit_reversible_command ();
4510 }
4511
4512 void
4513 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4514 {
4515         if (!_session) return;
4516
4517         begin_reversible_command (cmd);
4518
4519         Location* tpl;
4520
4521         if ((tpl = transport_punch_location()) == 0) {
4522                 Location* loc = new Location (*_session, start, end, _("Punch"),  Location::IsAutoPunch);
4523                 XMLNode &before = _session->locations()->get_state();
4524                 _session->locations()->add (loc, true);
4525                 _session->set_auto_punch_location (loc);
4526                 XMLNode &after = _session->locations()->get_state();
4527                 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4528         }
4529         else {
4530                 XMLNode &before = tpl->get_state();
4531                 tpl->set_hidden (false, this);
4532                 tpl->set (start, end);
4533                 XMLNode &after = tpl->get_state();
4534                 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4535         }
4536
4537         commit_reversible_command ();
4538 }
4539
4540 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4541  *  @param rs List to which found regions are added.
4542  *  @param where Time to look at.
4543  *  @param ts Tracks to look on; if this is empty, all tracks are examined.
4544  */
4545 void
4546 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4547 {
4548         const TrackViewList* tracks;
4549
4550         if (ts.empty()) {
4551                 tracks = &track_views;
4552         } else {
4553                 tracks = &ts;
4554         }
4555
4556         for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4557
4558                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4559
4560                 if (rtv) {
4561                         boost::shared_ptr<Track> tr;
4562                         boost::shared_ptr<Playlist> pl;
4563
4564                         if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4565
4566                                 boost::shared_ptr<RegionList> regions = pl->regions_at (
4567                                                 (framepos_t) floor ( (double) where * tr->speed()));
4568
4569                                 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4570                                         RegionView* rv = rtv->view()->find_view (*i);
4571                                         if (rv) {
4572                                                 rs.add (rv);
4573                                         }
4574                                 }
4575                         }
4576                 }
4577         }
4578 }
4579
4580 void
4581 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4582 {
4583         const TrackViewList* tracks;
4584
4585         if (ts.empty()) {
4586                 tracks = &track_views;
4587         } else {
4588                 tracks = &ts;
4589         }
4590
4591         for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4592                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4593                 if (rtv) {
4594                         boost::shared_ptr<Track> tr;
4595                         boost::shared_ptr<Playlist> pl;
4596
4597                         if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4598
4599                                 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4600                                         (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4601
4602                                 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4603
4604                                         RegionView* rv = rtv->view()->find_view (*i);
4605
4606                                         if (rv) {
4607                                                 rs.add (rv);
4608                                         }
4609                                 }
4610                         }
4611                 }
4612         }
4613 }
4614
4615 /** Get regions using the following method:
4616  *
4617  *  Make a region list using:
4618  *   (a) any selected regions
4619  *   (b) the intersection of any selected tracks and the edit point(*)
4620  *   (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4621  *
4622  *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4623  *
4624  *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4625  */
4626
4627 RegionSelection
4628 Editor::get_regions_from_selection_and_edit_point ()
4629 {
4630         RegionSelection regions;
4631
4632         if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4633                 regions.add (entered_regionview);
4634         } else {
4635                 regions = selection->regions;
4636         }
4637
4638         if ( regions.empty() ) {
4639                 TrackViewList tracks = selection->tracks;
4640
4641                 if (!tracks.empty()) {
4642                         /* no region selected or entered, but some selected tracks:
4643                          * act on all regions on the selected tracks at the edit point
4644                          */ 
4645                         framepos_t const where = get_preferred_edit_position ();
4646                         get_regions_at(regions, where, tracks);
4647                 }
4648         }
4649
4650         return regions;
4651 }
4652
4653 /** Get regions using the following method:
4654  *
4655  *  Make a region list using:
4656  *   (a) any selected regions
4657  *   (b) the intersection of any selected tracks and the edit point(*)
4658  *   (c) if neither exists, then whatever region is under the mouse
4659  *
4660  *  (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4661  *
4662  *  Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4663  */
4664 RegionSelection
4665 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4666 {
4667         RegionSelection regions;
4668
4669         if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4670                 regions.add (entered_regionview);
4671         } else {
4672                 regions = selection->regions;
4673         }
4674
4675         if ( regions.empty() ) {
4676                 TrackViewList tracks = selection->tracks;
4677
4678                 if (!tracks.empty()) {
4679                         /* no region selected or entered, but some selected tracks:
4680                          * act on all regions on the selected tracks at the edit point
4681                          */ 
4682                         get_regions_at(regions, pos, tracks);
4683                 }
4684         }
4685
4686         return regions;
4687 }
4688
4689 /** Start with regions that are selected, or the entered regionview if none are selected.
4690  *  Then add equivalent regions on tracks in the same active edit-enabled route group as any
4691  *  of the regions that we started with.
4692  */
4693
4694 RegionSelection
4695 Editor::get_regions_from_selection_and_entered ()
4696 {
4697         RegionSelection regions = selection->regions;
4698
4699         if (regions.empty() && entered_regionview) {
4700                 regions.add (entered_regionview);
4701         }
4702
4703         return regions;
4704 }
4705
4706 void
4707 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4708 {
4709         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4710
4711                 RouteTimeAxisView* tatv;
4712
4713                 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4714
4715                         boost::shared_ptr<Playlist> pl;
4716                         vector<boost::shared_ptr<Region> > results;
4717                         RegionView* marv;
4718                         boost::shared_ptr<Track> tr;
4719
4720                         if ((tr = tatv->track()) == 0) {
4721                                 /* bus */
4722                                 continue;
4723                         }
4724
4725                         if ((pl = (tr->playlist())) != 0) {
4726                                 if (src_comparison) {
4727                                         pl->get_source_equivalent_regions (region, results);
4728                                 } else {
4729                                         pl->get_region_list_equivalent_regions (region, results);
4730                                 }
4731                         }
4732
4733                         for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4734                                 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4735                                         regions.push_back (marv);
4736                                 }
4737                         }
4738
4739                 }
4740         }
4741 }
4742
4743 void
4744 Editor::show_rhythm_ferret ()
4745 {
4746         if (rhythm_ferret == 0) {
4747                 rhythm_ferret = new RhythmFerret(*this);
4748         }
4749
4750         rhythm_ferret->set_session (_session);
4751         rhythm_ferret->show ();
4752         rhythm_ferret->present ();
4753 }
4754
4755 void
4756 Editor::first_idle ()
4757 {
4758         MessageDialog* dialog = 0;
4759         
4760         if (track_views.size() > 1) {
4761                 dialog = new MessageDialog (
4762                         *this,
4763                         string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4764                         true
4765                         );
4766                 dialog->present ();
4767                 ARDOUR_UI::instance()->flush_pending ();
4768         }
4769
4770         for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4771                 (*t)->first_idle();
4772         }
4773
4774         // first idle adds route children (automation tracks), so we need to redisplay here
4775         _routes->redisplay ();
4776
4777         delete dialog;
4778         _have_idled = true;
4779 }
4780
4781 gboolean
4782 Editor::_idle_resize (gpointer arg)
4783 {
4784         return ((Editor*)arg)->idle_resize ();
4785 }
4786
4787 void
4788 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4789 {
4790         if (resize_idle_id < 0) {
4791                 resize_idle_id = g_idle_add (_idle_resize, this);
4792                 _pending_resize_amount = 0;
4793         }
4794
4795         /* make a note of the smallest resulting height, so that we can clamp the
4796            lower limit at TimeAxisView::hSmall */
4797
4798         int32_t min_resulting = INT32_MAX;
4799
4800         _pending_resize_amount += h;
4801         _pending_resize_view = view;
4802
4803         min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4804
4805         if (selection->tracks.contains (_pending_resize_view)) {
4806                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4807                         min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4808                 }
4809         }
4810
4811         if (min_resulting < 0) {
4812                 min_resulting = 0;
4813         }
4814
4815         /* clamp */
4816         if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4817                 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4818         }
4819 }
4820
4821 /** Handle pending resizing of tracks */
4822 bool
4823 Editor::idle_resize ()
4824 {
4825         _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4826
4827         if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4828             selection->tracks.contains (_pending_resize_view)) {
4829
4830                 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4831                         if (*i != _pending_resize_view) {
4832                                 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4833                         }
4834                 }
4835         }
4836
4837         _pending_resize_amount = 0;
4838         _group_tabs->set_dirty ();
4839         resize_idle_id = -1;
4840
4841         return false;
4842 }
4843
4844 void
4845 Editor::located ()
4846 {
4847         ENSURE_GUI_THREAD (*this, &Editor::located);
4848
4849         if (_session) {
4850                 playhead_cursor->set_position (_session->audible_frame ());
4851                 if (_follow_playhead && !_pending_initial_locate) {
4852                         reset_x_origin_to_follow_playhead ();
4853                 }
4854         }
4855
4856         _pending_locate_request = false;
4857         _pending_initial_locate = false;
4858 }
4859
4860 void
4861 Editor::region_view_added (RegionView *)
4862 {
4863         _summary->set_background_dirty ();
4864 }
4865
4866 void
4867 Editor::region_view_removed ()
4868 {
4869         _summary->set_background_dirty ();
4870 }
4871
4872 RouteTimeAxisView*
4873 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4874 {
4875         TrackViewList::const_iterator j = track_views.begin ();
4876         while (j != track_views.end()) {
4877                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4878                 if (rtv && rtv->route() == r) {
4879                         return rtv;
4880                 }
4881                 ++j;
4882         }
4883
4884         return 0;
4885 }
4886
4887
4888 TrackViewList
4889 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4890 {
4891         TrackViewList t;
4892
4893         for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4894                 TimeAxisView* tv = axis_view_from_route (*i);
4895                 if (tv) {
4896                         t.push_back (tv);
4897                 }
4898         }
4899
4900         return t;
4901 }
4902
4903 void
4904 Editor::suspend_route_redisplay ()
4905 {
4906         if (_routes) {
4907                 _routes->suspend_redisplay();
4908         }
4909 }
4910
4911 void
4912 Editor::resume_route_redisplay ()
4913 {
4914         if (_routes) {
4915                 _routes->resume_redisplay();
4916         }
4917 }
4918
4919 void
4920 Editor::add_routes (RouteList& routes)
4921 {
4922         ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4923
4924         RouteTimeAxisView *rtv;
4925         list<RouteTimeAxisView*> new_views;
4926
4927         for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4928                 boost::shared_ptr<Route> route = (*x);
4929
4930                 if (route->is_auditioner() || route->is_monitor()) {
4931                         continue;
4932                 }
4933
4934                 DataType dt = route->input()->default_type();
4935
4936                 if (dt == ARDOUR::DataType::AUDIO) {
4937                         rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4938                         rtv->set_route (route);
4939                 } else if (dt == ARDOUR::DataType::MIDI) {
4940                         rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
4941                         rtv->set_route (route);
4942                 } else {
4943                         throw unknown_type();
4944                 }
4945
4946                 new_views.push_back (rtv);
4947                 track_views.push_back (rtv);
4948
4949                 rtv->effective_gain_display ();
4950
4951                 if (internal_editing()) {
4952                         rtv->enter_internal_edit_mode ();
4953                 } else {
4954                         rtv->leave_internal_edit_mode ();
4955                 }
4956
4957                 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4958                 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4959         }
4960
4961         if (new_views.size() > 0) {
4962                 _routes->routes_added (new_views);
4963                 _summary->routes_added (new_views);
4964         }
4965
4966         if (show_editor_mixer_when_tracks_arrive) {
4967                 show_editor_mixer (true);
4968         }
4969
4970         editor_list_button.set_sensitive (true);
4971 }
4972
4973 void
4974 Editor::timeaxisview_deleted (TimeAxisView *tv)
4975 {
4976         if (tv == entered_track) {
4977                 entered_track = 0;
4978         }
4979
4980         if (_session && _session->deletion_in_progress()) {
4981                 /* the situation is under control */
4982                 return;
4983         }
4984
4985         ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
4986
4987         RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
4988
4989         _routes->route_removed (tv);
4990
4991         TimeAxisView::Children c = tv->get_child_list ();
4992         for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
4993                 if (entered_track == i->get()) {
4994                         entered_track = 0;
4995                 }
4996         }
4997
4998         /* remove it from the list of track views */
4999
5000         TrackViewList::iterator i;
5001
5002         if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5003                 i = track_views.erase (i);
5004         }
5005
5006         /* update whatever the current mixer strip is displaying, if revelant */
5007
5008         boost::shared_ptr<Route> route;
5009
5010         if (rtav) {
5011                 route = rtav->route ();
5012         }
5013
5014         if (current_mixer_strip && current_mixer_strip->route() == route) {
5015
5016                 TimeAxisView* next_tv;
5017
5018                 if (track_views.empty()) {
5019                         next_tv = 0;
5020                 } else if (i == track_views.end()) {
5021                         next_tv = track_views.front();
5022                 } else {
5023                         next_tv = (*i);
5024                 }
5025
5026
5027                 if (next_tv) {
5028                         set_selected_mixer_strip (*next_tv);
5029                 } else {
5030                         /* make the editor mixer strip go away setting the
5031                          * button to inactive (which also unticks the menu option)
5032                          */
5033
5034                         ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5035                 }
5036         }
5037 }
5038
5039 void
5040 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5041 {
5042         if (apply_to_selection) {
5043                 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5044
5045                         TrackSelection::iterator j = i;
5046                         ++j;
5047
5048                         hide_track_in_display (*i, false);
5049
5050                         i = j;
5051                 }
5052         } else {
5053                 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5054
5055                 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5056                         // this will hide the mixer strip
5057                         set_selected_mixer_strip (*tv);
5058                 }
5059
5060                 _routes->hide_track_in_display (*tv);
5061         }
5062 }
5063
5064 bool
5065 Editor::sync_track_view_list_and_routes ()
5066 {
5067         track_views = TrackViewList (_routes->views ());
5068
5069         _summary->set_dirty ();
5070         _group_tabs->set_dirty ();
5071
5072         return false; // do not call again (until needed)
5073 }
5074
5075 void
5076 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5077 {
5078         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5079                 theslot (**i);
5080         }
5081 }
5082
5083 /** Find a RouteTimeAxisView by the ID of its route */
5084 RouteTimeAxisView*
5085 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5086 {
5087         RouteTimeAxisView* v;
5088
5089         for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5090                 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5091                         if(v->route()->id() == id) {
5092                                 return v;
5093                         }
5094                 }
5095         }
5096
5097         return 0;
5098 }
5099
5100 void
5101 Editor::fit_route_group (RouteGroup *g)
5102 {
5103         TrackViewList ts = axis_views_from_routes (g->route_list ());
5104         fit_tracks (ts);
5105 }
5106
5107 void
5108 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5109 {
5110         boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5111
5112         if (r == 0) {
5113                 _session->cancel_audition ();
5114                 return;
5115         }
5116
5117         if (_session->is_auditioning()) {
5118                 _session->cancel_audition ();
5119                 if (r == last_audition_region) {
5120                         return;
5121                 }
5122         }
5123
5124         _session->audition_region (r);
5125         last_audition_region = r;
5126 }
5127
5128
5129 void
5130 Editor::hide_a_region (boost::shared_ptr<Region> r)
5131 {
5132         r->set_hidden (true);
5133 }
5134
5135 void
5136 Editor::show_a_region (boost::shared_ptr<Region> r)
5137 {
5138         r->set_hidden (false);
5139 }
5140
5141 void
5142 Editor::audition_region_from_region_list ()
5143 {
5144         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5145 }
5146
5147 void
5148 Editor::hide_region_from_region_list ()
5149 {
5150         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5151 }
5152
5153 void
5154 Editor::show_region_in_region_list ()
5155 {
5156         _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5157 }
5158
5159 void
5160 Editor::step_edit_status_change (bool yn)
5161 {
5162         if (yn) {
5163                 start_step_editing ();
5164         } else {
5165                 stop_step_editing ();
5166         }
5167 }
5168
5169 void
5170 Editor::start_step_editing ()
5171 {
5172         step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5173 }
5174
5175 void
5176 Editor::stop_step_editing ()
5177 {
5178         step_edit_connection.disconnect ();
5179 }
5180
5181 bool
5182 Editor::check_step_edit ()
5183 {
5184         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5185                 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5186                 if (mtv) {
5187                         mtv->check_step_edit ();
5188                 }
5189         }
5190
5191         return true; // do it again, till we stop
5192 }
5193
5194 bool
5195 Editor::scroll_press (Direction dir)
5196 {
5197         ++_scroll_callbacks;
5198
5199         if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5200                 /* delay the first auto-repeat */
5201                 return true;
5202         }
5203
5204         switch (dir) {
5205         case LEFT:
5206                 scroll_backward (1);
5207                 break;
5208
5209         case RIGHT:
5210                 scroll_forward (1);
5211                 break;
5212
5213         case UP:
5214                 scroll_tracks_up_line ();
5215                 break;
5216
5217         case DOWN:
5218                 scroll_tracks_down_line ();
5219                 break;
5220         }
5221
5222         /* do hacky auto-repeat */
5223         if (!_scroll_connection.connected ()) {
5224
5225                 _scroll_connection = Glib::signal_timeout().connect (
5226                         sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5227                         );
5228
5229                 _scroll_callbacks = 0;
5230         }
5231
5232         return true;
5233 }
5234
5235 void
5236 Editor::scroll_release ()
5237 {
5238         _scroll_connection.disconnect ();
5239 }
5240
5241 /** Queue a change for the Editor viewport x origin to follow the playhead */
5242 void
5243 Editor::reset_x_origin_to_follow_playhead ()
5244 {
5245         framepos_t const frame = playhead_cursor->current_frame ();
5246
5247         if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5248
5249                 if (_session->transport_speed() < 0) {
5250
5251                         if (frame > (current_page_samples() / 2)) {
5252                                 center_screen (frame-(current_page_samples()/2));
5253                         } else {
5254                                 center_screen (current_page_samples()/2);
5255                         }
5256
5257                 } else {
5258
5259                         framepos_t l = 0;
5260                         
5261                         if (frame < leftmost_frame) {
5262                                 /* moving left */
5263                                 if (_session->transport_rolling()) {
5264                                         /* rolling; end up with the playhead at the right of the page */
5265                                         l = frame - current_page_samples ();
5266                                 } else {
5267                                         /* not rolling: end up with the playhead 1/4 of the way along the page */
5268                                         l = frame - current_page_samples() / 4;
5269                                 }
5270                         } else {
5271                                 /* moving right */
5272                                 if (_session->transport_rolling()) {
5273                                         /* rolling: end up with the playhead on the left of the page */
5274                                         l = frame;
5275                                 } else {
5276                                         /* not rolling: end up with the playhead 3/4 of the way along the page */
5277                                         l = frame - 3 * current_page_samples() / 4;
5278                                 }
5279                         }
5280
5281                         if (l < 0) {
5282                                 l = 0;
5283                         }
5284                         
5285                         center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5286                 }
5287         }
5288 }
5289
5290 void
5291 Editor::super_rapid_screen_update ()
5292 {
5293         if (!_session || !_session->engine().running()) {
5294                 return;
5295         }
5296
5297         /* METERING / MIXER STRIPS */
5298
5299         /* update track meters, if required */
5300         if (is_mapped() && meters_running) {
5301                 RouteTimeAxisView* rtv;
5302                 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5303                         if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5304                                 rtv->fast_update ();
5305                         }
5306                 }
5307         }
5308
5309         /* and any current mixer strip */
5310         if (current_mixer_strip) {
5311                 current_mixer_strip->fast_update ();
5312         }
5313
5314         /* PLAYHEAD AND VIEWPORT */
5315
5316         framepos_t const frame = _session->audible_frame();
5317
5318         /* There are a few reasons why we might not update the playhead / viewport stuff:
5319          *
5320          * 1.  we don't update things when there's a pending locate request, otherwise
5321          *     when the editor requests a locate there is a chance that this method
5322          *     will move the playhead before the locate request is processed, causing
5323          *     a visual glitch.
5324          * 2.  if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5325          * 3.  if we're still at the same frame that we were last time, there's nothing to do.
5326          */
5327
5328         if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5329
5330                 last_update_frame = frame;
5331
5332                 if (!_dragging_playhead) {
5333                         playhead_cursor->set_position (frame);
5334                 }
5335
5336                 if (!_stationary_playhead) {
5337
5338                         if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5339                                 /* We only do this if we aren't already
5340                                    handling a visual change (ie if
5341                                    pending_visual_change.being_handled is
5342                                    false) so that these requests don't stack
5343                                    up there are too many of them to handle in
5344                                    time.
5345                                 */
5346                                 reset_x_origin_to_follow_playhead ();
5347                         }
5348
5349                 } else {
5350
5351                         /* don't do continuous scroll till the new position is in the rightmost quarter of the
5352                            editor canvas
5353                         */
5354 #if 0
5355                         // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5356                         double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5357                         if (target <= 0.0) {
5358                                 target = 0.0;
5359                         }
5360                         if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5361                                 target = (target * 0.15) + (current * 0.85);
5362                         } else {
5363                                 /* relax */
5364                         }
5365
5366                         current = target;
5367                         set_horizontal_position (current);
5368 #endif
5369                 }
5370
5371         }
5372 }
5373
5374
5375 void
5376 Editor::session_going_away ()
5377 {
5378         _have_idled = false;
5379
5380         _session_connections.drop_connections ();
5381
5382         super_rapid_screen_update_connection.disconnect ();
5383
5384         selection->clear ();
5385         cut_buffer->clear ();
5386
5387         clicked_regionview = 0;
5388         clicked_axisview = 0;
5389         clicked_routeview = 0;
5390         entered_regionview = 0;
5391         entered_track = 0;
5392         last_update_frame = 0;
5393         _drags->abort ();
5394
5395         playhead_cursor->hide ();
5396
5397         /* rip everything out of the list displays */
5398
5399         _regions->clear ();
5400         _routes->clear ();
5401         _route_groups->clear ();
5402
5403         /* do this first so that deleting a track doesn't reset cms to null
5404            and thus cause a leak.
5405         */
5406
5407         if (current_mixer_strip) {
5408                 if (current_mixer_strip->get_parent() != 0) {
5409                         global_hpacker.remove (*current_mixer_strip);
5410                 }
5411                 delete current_mixer_strip;
5412                 current_mixer_strip = 0;
5413         }
5414
5415         /* delete all trackviews */
5416
5417         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5418                 delete *i;
5419         }
5420         track_views.clear ();
5421
5422         nudge_clock->set_session (0);
5423
5424         editor_list_button.set_active(false);
5425         editor_list_button.set_sensitive(false);
5426
5427         /* clear tempo/meter rulers */
5428         remove_metric_marks ();
5429         hide_measures ();
5430         clear_marker_display ();
5431
5432         stop_step_editing ();
5433         
5434         /* get rid of any existing editor mixer strip */
5435
5436         WindowTitle title(Glib::get_application_name());
5437         title += _("Editor");
5438
5439         set_title (title.get_string());
5440
5441         SessionHandlePtr::session_going_away ();
5442 }
5443
5444
5445 void
5446 Editor::show_editor_list (bool yn)
5447 {
5448         if (yn) {
5449                 _the_notebook.show ();
5450         } else {
5451                 _the_notebook.hide ();
5452         }
5453 }
5454
5455 void
5456 Editor::change_region_layering_order (bool from_context_menu)
5457 {
5458         const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5459
5460         if (!clicked_routeview) {
5461                 if (layering_order_editor) {
5462                         layering_order_editor->hide ();
5463                 }
5464                 return;
5465         }
5466
5467         boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5468
5469         if (!track) {
5470                 return;
5471         }
5472
5473         boost::shared_ptr<Playlist> pl = track->playlist();
5474
5475         if (!pl) {
5476                 return;
5477         }
5478
5479         if (layering_order_editor == 0) {
5480                 layering_order_editor = new RegionLayeringOrderEditor (*this);
5481         }
5482
5483         layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5484         layering_order_editor->maybe_present ();
5485 }
5486
5487 void
5488 Editor::update_region_layering_order_editor ()
5489 {
5490         if (layering_order_editor && layering_order_editor->is_visible ()) {
5491                 change_region_layering_order (true);
5492         }
5493 }
5494
5495 void
5496 Editor::setup_fade_images ()
5497 {
5498         _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5499         _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5500         _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5501         _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5502         _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5503
5504         _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5505         _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5506         _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5507         _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5508         _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5509         
5510         _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5511         _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5512         _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5513         _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5514         _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5515
5516         _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5517         _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5518         _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5519         _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5520         _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5521
5522 }
5523
5524 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5525 Gtk::MenuItem&
5526 Editor::action_menu_item (std::string const & name)
5527 {
5528         Glib::RefPtr<Action> a = editor_actions->get_action (name);
5529         assert (a);
5530
5531         return *manage (a->create_menu_item ());
5532 }
5533
5534 void
5535 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5536 {
5537         EventBox* b = manage (new EventBox);
5538         b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5539         Label* l = manage (new Label (name));
5540         l->set_angle (-90);
5541         b->add (*l);
5542         b->show_all ();
5543         _the_notebook.append_page (widget, *b);
5544 }
5545
5546 bool
5547 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5548 {
5549         if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5550                 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5551         }
5552
5553         if (ev->type == GDK_2BUTTON_PRESS) {
5554
5555                 /* double-click on a notebook tab shrinks or expands the notebook */
5556
5557                 if (_notebook_shrunk) {
5558                         if (pre_notebook_shrink_pane_width) {
5559                                 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5560                         }
5561                         _notebook_shrunk = false;
5562                 } else {
5563                         pre_notebook_shrink_pane_width = edit_pane.get_position();
5564
5565                         /* this expands the LHS of the edit pane to cover the notebook
5566                            PAGE but leaves the tabs visible.
5567                          */
5568                         edit_pane.set_position (edit_pane.get_position() + page->get_width());
5569                         _notebook_shrunk = true;
5570                 }
5571         }
5572
5573         return true;
5574 }
5575
5576 void
5577 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5578 {
5579         using namespace Menu_Helpers;
5580         
5581         MenuList& items = _control_point_context_menu.items ();
5582         items.clear ();
5583         
5584         items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5585         items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5586         if (!can_remove_control_point (item)) {
5587                 items.back().set_sensitive (false);
5588         }
5589
5590         _control_point_context_menu.popup (event->button.button, event->button.time);
5591 }
5592
5593 void
5594 Editor::zoom_vertical_modifier_released()
5595 {
5596         _stepping_axis_view = 0;
5597 }
5598
5599 void
5600 Editor::ui_parameter_changed (string parameter)
5601 {
5602         if (parameter == "icon-set") {
5603                 while (!_cursor_stack.empty()) {
5604                         _cursor_stack.pop();
5605                 }
5606                 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5607         } else if (parameter == "draggable-playhead") {
5608                 if (_verbose_cursor) {
5609                         playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());
5610                 }
5611         }
5612 }