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