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