fix up meter thread management when JACK client starts/stops/is halted ; put focus...
[ardour.git] / gtk2_ardour / editor.cc
1 /*
2     Copyright (C) 2000-2007 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 #include <sys/time.h>
21 #include <unistd.h>
22 #include <cstdlib>
23 #include <cmath>
24 #include <string>
25 #include <algorithm>
26
27 #include <boost/none.hpp>
28
29 #include <sigc++/bind.h>
30
31 #include <pbd/convert.h>
32 #include <pbd/error.h>
33 #include <pbd/enumwriter.h>
34 #include <pbd/memento_command.h>
35
36 #include <glibmm/miscutils.h>
37 #include <gtkmm/image.h>
38 #include <gdkmm/color.h>
39 #include <gdkmm/bitmap.h>
40
41 #include <gtkmm2ext/grouped_buttons.h>
42 #include <gtkmm2ext/gtk_ui.h>
43 #include <gtkmm2ext/tearoff.h>
44 #include <gtkmm2ext/utils.h>
45 #include <gtkmm2ext/window_title.h>
46 #include <gtkmm2ext/choice.h>
47
48 #include <ardour/audio_track.h>
49 #include <ardour/audio_diskstream.h>
50 #include <ardour/plugin_manager.h>
51 #include <ardour/location.h>
52 #include <ardour/audioplaylist.h>
53 #include <ardour/audioregion.h>
54 #include <ardour/region.h>
55 #include <ardour/session_route.h>
56 #include <ardour/tempo.h>
57 #include <ardour/utils.h>
58 #include <ardour/profile.h>
59
60 #include <control_protocol/control_protocol.h>
61
62 #include "ardour_ui.h"
63 #include "editor.h"
64 #include "keyboard.h"
65 #include "marker.h"
66 #include "playlist_selector.h"
67 #include "audio_region_view.h"
68 #include "rgb_macros.h"
69 #include "selection.h"
70 #include "audio_streamview.h"
71 #include "time_axis_view.h"
72 #include "audio_time_axis.h"
73 #include "utils.h"
74 #include "crossfade_view.h"
75 #include "editing.h"
76 #include "public_editor.h"
77 #include "crossfade_edit.h"
78 #include "canvas_impl.h"
79 #include "actions.h"
80 #include "gui_thread.h"
81 #include "sfdb_ui.h"
82 #include "rhythm_ferret.h"
83
84 #ifdef FFT_ANALYSIS
85 #include "analysis_window.h"
86 #endif
87
88 #include "i18n.h"
89
90 /* <CMT Additions> */
91 #include "imageframe_socket_handler.h"
92 /* </CMT Additions> */
93
94 using namespace std;
95 using namespace sigc;
96 using namespace ARDOUR;
97 using namespace PBD;
98 using namespace Gtk;
99 using namespace Glib;
100 using namespace Gtkmm2ext;
101 using namespace Editing;
102
103 using PBD::atoi;
104
105 const double Editor::timebar_height = 15.0;
106
107 #include "editor_xpms"
108
109 static const gchar *_snap_type_strings[] = {
110         N_("CD Frames"),
111         N_("SMPTE Frames"),
112         N_("SMPTE Seconds"),
113         N_("SMPTE Minutes"),
114         N_("Seconds"),
115         N_("Minutes"),
116         N_("Beats/32"),
117         N_("Beats/16"),
118         N_("Beats/8"),
119         N_("Beats/4"),
120         N_("Beats/3"),
121         N_("Beats"),
122         N_("Bars"),
123         N_("Marks"),
124         N_("Region starts"),
125         N_("Region ends"),
126         N_("Region syncs"),
127         N_("Region bounds"),
128         0
129 };
130
131 static const gchar *_snap_mode_strings[] = {
132         N_("No Grid"),
133         N_("Grid"),
134         N_("Magnetic"),
135         0
136 };
137
138 static const gchar *_edit_point_strings[] = {
139         N_("Playhead"),
140         N_("Marker"),
141         N_("Mouse"),
142         0
143 };
144
145 static const gchar *_zoom_focus_strings[] = {
146         N_("Left"),
147         N_("Right"),
148         N_("Center"),
149         N_("Playhead"),
150         N_("Mouse"),
151         N_("Active Mark"),
152         0
153 };
154
155 #ifdef USE_RUBBERBAND
156 static const gchar *_rb_opt_strings[] = {
157         N_("Mushy"),
158         N_("Smooth"),
159         N_("Balanced multitimbral mixture"),
160         N_("Unpitched percussion with stable notes"),
161         N_("Crisp monophonic instrumental"),
162         N_("Unpitched solo percussion"),
163         0
164 };
165 #endif
166
167 /* Soundfile  drag-n-drop */
168
169 Gdk::Cursor* Editor::cross_hair_cursor = 0;
170 Gdk::Cursor* Editor::selector_cursor = 0;
171 Gdk::Cursor* Editor::trimmer_cursor = 0;
172 Gdk::Cursor* Editor::grabber_cursor = 0;
173 Gdk::Cursor* Editor::grabber_edit_point_cursor = 0;
174 Gdk::Cursor* Editor::zoom_cursor = 0;
175 Gdk::Cursor* Editor::time_fx_cursor = 0;
176 Gdk::Cursor* Editor::fader_cursor = 0;
177 Gdk::Cursor* Editor::speaker_cursor = 0;
178 Gdk::Cursor* Editor::wait_cursor = 0;
179 Gdk::Cursor* Editor::timebar_cursor = 0;
180 Gdk::Cursor* Editor::transparent_cursor = 0;
181
182 void
183 show_me_the_size (Requisition* r, const char* what)
184 {
185         cerr << "size of " << what << " = " << r->width << " x " << r->height << endl;
186 }
187
188 Editor::Editor ()
189         : 
190           /* time display buttons */
191           minsec_label (_("Mins:Secs")),
192           bbt_label (_("Bars:Beats")),
193           smpte_label (_("Timecode")),
194           frame_label (_("Samples")),
195           tempo_label (_("Tempo")),
196           meter_label (_("Meter")),
197           mark_label (_("Location Markers")),
198           range_mark_label (_("Range Markers")),
199           transport_mark_label (_("Loop/Punch Ranges")),
200           cd_mark_label (_("CD Markers")),
201
202           edit_packer (3, 3, true),
203
204           /* the values here don't matter: layout widgets
205              reset them as needed.
206           */
207
208           vertical_adjustment (0.0, 0.0, 10.0, 400.0),
209           horizontal_adjustment (0.0, 0.0, 20.0, 1200.0),
210
211           /* tool bar related */
212
213           edit_point_clock (X_("editpoint"), false, X_("EditPointClock"), true),
214           zoom_range_clock (X_("zoomrange"), false, X_("ZoomRangeClock"), true, true),
215           
216           toolbar_selection_clock_table (2,3),
217           
218           automation_mode_button (_("mode")),
219           global_automation_button (_("automation")),
220
221           /* <CMT Additions> */
222           image_socket_listener(0),
223           /* </CMT Additions> */
224
225           /* nudge */
226
227           nudge_clock (X_("nudge"), false, X_("NudgeClock"), true, true),
228           meters_running(false)
229
230 {
231         constructed = false;
232
233         /* we are a singleton */
234
235         PublicEditor::_instance = this;
236
237         session = 0;
238         _have_idled = false;
239
240         selection = new Selection;
241         cut_buffer = new Selection;
242
243         selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
244         selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
245         selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
246         selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
247         selection->MarkersChanged.connect (mem_fun(*this, &Editor::marker_selection_changed));
248
249         clicked_regionview = 0;
250         clicked_trackview = 0;
251         clicked_audio_trackview = 0;
252         clicked_crossfadeview = 0;
253         clicked_control_point = 0;
254         last_update_frame = 0;
255         drag_info.item = 0;
256         current_mixer_strip = 0;
257         current_bbt_points = 0;
258         
259         snap_type_strings =  I18N (_snap_type_strings);
260         snap_mode_strings =  I18N (_snap_mode_strings);
261         zoom_focus_strings = I18N (_zoom_focus_strings);
262         edit_point_strings = I18N (_edit_point_strings);
263 #ifdef USE_RUBBERBAND
264         rb_opt_strings = I18N (_rb_opt_strings);
265 #endif
266         
267         snap_threshold = 5.0;
268         bbt_beat_subdivision = 4;
269         canvas_width = 0;
270         canvas_height = 0;
271         autoscroll_active = false;
272         autoscroll_timeout_tag = -1;
273         interthread_progress_window = 0;
274         logo_item = 0;
275
276 #ifdef FFT_ANALYSIS
277         analysis_window = 0;
278 #endif
279
280         current_interthread_info = 0;
281         _show_measures = true;
282         _show_waveforms = true;
283         _show_waveforms_recording = true;
284         first_action_message = 0;
285         export_dialog = 0;
286         export_range_markers_dialog = 0;
287         show_gain_after_trim = false;
288         ignore_route_list_reorder = false;
289         no_route_list_redisplay = false;
290         verbose_cursor_on = true;
291         route_removal = false;
292         show_automatic_regions_in_region_list = true;
293         last_item_entered = 0;
294         last_item_entered_n = 0;
295
296         region_list_sort_type = (Editing::RegionListSortType) 0;
297         have_pending_keyboard_selection = false;
298         _follow_playhead = true;
299         _xfade_visibility = true;
300         editor_ruler_menu = 0;
301         no_ruler_shown_update = false;
302         edit_group_list_menu = 0;
303         route_list_menu = 0;
304         region_list_menu = 0;
305         marker_menu = 0;
306         start_end_marker_menu = 0;
307         range_marker_menu = 0;
308         marker_menu_item = 0;
309         tm_marker_menu = 0;
310         transport_marker_menu = 0;
311         new_transport_marker_menu = 0;
312         editor_mixer_strip_width = Wide;
313         show_editor_mixer_when_tracks_arrive = false;
314         region_edit_menu_split_item = 0;
315         temp_location = 0;
316         region_edit_menu_split_multichannel_item = 0;
317         leftmost_frame = 0;
318         ignore_mouse_mode_toggle = false;
319         current_stepping_trackview = 0;
320         entered_track = 0;
321         entered_regionview = 0;
322         entered_marker = 0;
323         clear_entered_track = false;
324         _new_regionviews_show_envelope = false;
325         current_timefx = 0;
326         in_edit_group_row_change = false;
327         last_canvas_frame = 0;
328         playhead_cursor = 0;
329         button_release_can_deselect = true;
330         canvas_idle_queued = false;
331         _dragging_playhead = false;
332         _dragging_edit_point = false;
333         _dragging_hscrollbar = false;
334         select_new_marker = false;
335         zoomed_to_region = false;
336         rhythm_ferret = 0;
337
338         _scrubbing = false;
339         scrubbing_direction = 0;
340
341         sfbrowser = 0;
342         ignore_route_order_sync = false;
343
344         location_marker_color = ARDOUR_UI::config()->canvasvar_LocationMarker.get();
345         location_range_color = ARDOUR_UI::config()->canvasvar_LocationRange.get();
346         location_cd_marker_color = ARDOUR_UI::config()->canvasvar_LocationCDMarker.get();
347         location_loop_color = ARDOUR_UI::config()->canvasvar_LocationLoop.get();
348         location_punch_color = ARDOUR_UI::config()->canvasvar_LocationPunch.get();
349
350         range_marker_drag_rect = 0;
351         marker_drag_line = 0;
352         
353         set_mouse_mode (MouseObject, true);
354
355         last_visual_state.frames_per_unit = 0;
356
357         frames_per_unit = 2048; /* too early to use reset_zoom () */
358         reset_hscrollbar_stepping ();
359         
360         zoom_focus = ZoomFocusLeft;
361         set_zoom_focus (ZoomFocusLeft);
362         zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
363
364         initialize_rulers ();
365         initialize_canvas ();
366
367         edit_controls_vbox.set_spacing (0);
368         horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled), false);
369         vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling), true);
370         
371         track_canvas.set_hadjustment (horizontal_adjustment);
372         track_canvas.set_vadjustment (vertical_adjustment);
373         time_canvas.set_hadjustment (horizontal_adjustment);
374
375         track_canvas.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
376         time_canvas.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
377         
378         controls_layout.add (edit_controls_vbox);
379         controls_layout.set_name ("EditControlsBase");
380         controls_layout.add_events (Gdk::SCROLL_MASK);
381         controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false);
382         
383         controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
384         controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
385         controls_layout.signal_size_request().connect (mem_fun (*this, &Editor::controls_layout_size_request));
386
387         edit_vscrollbar.set_adjustment (vertical_adjustment);
388         edit_hscrollbar.set_adjustment (horizontal_adjustment);
389
390         edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscrollbar_button_press), false);
391         edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release), false);
392         edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate));
393
394         edit_hscrollbar.set_name ("EditorHScrollbar");
395
396         build_cursors ();
397         setup_toolbar ();
398
399         edit_point_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_point_clock_changed));
400         
401         time_canvas_vbox.pack_start (*_ruler_separator, false, false);
402         time_canvas_vbox.pack_start (*minsec_ruler, false, false);
403         time_canvas_vbox.pack_start (*smpte_ruler, false, false);
404         time_canvas_vbox.pack_start (*frames_ruler, false, false);
405         time_canvas_vbox.pack_start (*bbt_ruler, false, false);
406         time_canvas_vbox.pack_start (time_canvas, true, true);
407         time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2);
408
409         bbt_label.set_name ("EditorTimeButton");
410         bbt_label.set_size_request (-1, (int)timebar_height);
411         bbt_label.set_alignment (1.0, 0.5);
412         bbt_label.set_padding (5,0);
413         minsec_label.set_name ("EditorTimeButton");
414         minsec_label.set_size_request (-1, (int)timebar_height);
415         minsec_label.set_alignment (1.0, 0.5);
416         minsec_label.set_padding (5,0);
417         smpte_label.set_name ("EditorTimeButton");
418         smpte_label.set_size_request (-1, (int)timebar_height);
419         smpte_label.set_alignment (1.0, 0.5);
420         smpte_label.set_padding (5,0);
421         frame_label.set_name ("EditorTimeButton");
422         frame_label.set_size_request (-1, (int)timebar_height);
423         frame_label.set_alignment (1.0, 0.5);
424         frame_label.set_padding (5,0);
425         tempo_label.set_name ("EditorTimeButton");
426         tempo_label.set_size_request (-1, (int)timebar_height);
427         tempo_label.set_alignment (1.0, 0.5);
428         tempo_label.set_padding (5,0);
429         meter_label.set_name ("EditorTimeButton");
430         meter_label.set_size_request (-1, (int)timebar_height);
431         meter_label.set_alignment (1.0, 0.5);
432         meter_label.set_padding (5,0);
433         mark_label.set_name ("EditorTimeButton");
434         mark_label.set_size_request (-1, (int)timebar_height);
435         mark_label.set_alignment (1.0, 0.5);
436         mark_label.set_padding (5,0);
437         cd_mark_label.set_name ("EditorTimeButton");
438         cd_mark_label.set_size_request (-1, (int)timebar_height);
439         cd_mark_label.set_alignment (1.0, 0.5);
440         cd_mark_label.set_padding (5,0);
441         range_mark_label.set_name ("EditorTimeButton");
442         range_mark_label.set_size_request (-1, (int)timebar_height);
443         range_mark_label.set_alignment (1.0, 0.5);
444         range_mark_label.set_padding (5,0);
445         transport_mark_label.set_name ("EditorTimeButton");
446         transport_mark_label.set_size_request (-1, (int)timebar_height);
447         transport_mark_label.set_alignment (1.0, 0.5);
448         transport_mark_label.set_padding (5,0);
449         
450         time_button_vbox.pack_start (minsec_label, false, false);
451         time_button_vbox.pack_start (smpte_label, false, false);
452         time_button_vbox.pack_start (frame_label, false, false);
453         time_button_vbox.pack_start (bbt_label, false, false);
454         time_button_vbox.pack_start (meter_label, false, false);
455         time_button_vbox.pack_start (tempo_label, false, false);
456         time_button_vbox.pack_start (mark_label, false, false);
457
458         time_button_event_box.add (time_button_vbox);
459         
460         time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
461         time_button_event_box.set_name ("TimebarLabelBase");
462         time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
463
464         time_button_frame.add(time_button_event_box);
465         time_button_frame.property_shadow_type() = Gtk::SHADOW_OUT;
466
467         /* these enable us to have a dedicated window (for cursor setting, etc.) 
468            for the canvas areas.
469         */
470
471         track_canvas_event_box.add (track_canvas);
472
473         time_canvas_event_box.add (time_canvas_vbox);
474         time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
475         
476         edit_packer.set_col_spacings (0);
477         edit_packer.set_row_spacings (0);
478         edit_packer.set_homogeneous (false);
479         edit_packer.set_border_width (0);
480         edit_packer.set_name ("EditorWindow");
481         
482         edit_packer.attach (edit_vscrollbar,         0, 1, 1, 3,    FILL,        FILL|EXPAND, 0, 0);
483
484         edit_packer.attach (time_button_frame,       0, 2, 0, 1,    FILL,        FILL, 0, 0);
485         edit_packer.attach (time_canvas_event_box,   2, 3, 0, 1,    FILL|EXPAND, FILL, 0, 0);
486
487         edit_packer.attach (controls_layout,         1, 2, 1, 2,    FILL,        FILL|EXPAND, 0, 0);
488         edit_packer.attach (track_canvas_event_box,  2, 3, 1, 2,    FILL|EXPAND, FILL|EXPAND, 0, 0);
489
490         edit_packer.attach (zoom_box,                1, 2, 2, 3,    FILL,         FILL, 0, 0);
491         edit_packer.attach (edit_hscrollbar,         2, 3, 2, 3,    FILL|EXPAND,  FILL, 0, 0);
492
493         bottom_hbox.set_border_width (2);
494         bottom_hbox.set_spacing (3);
495
496         route_display_model = ListStore::create(route_display_columns);
497         route_list_display.set_model (route_display_model);
498         route_list_display.append_column (_("Show"), route_display_columns.visible);
499         route_list_display.append_column (_("Name"), route_display_columns.text);
500         route_list_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
501         route_list_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
502         route_list_display.set_headers_visible (true);
503         route_list_display.set_name ("TrackListDisplay");
504         route_list_display.get_selection()->set_mode (SELECTION_NONE);
505         route_list_display.set_reorderable (true);
506         route_list_display.set_size_request (100,-1);
507
508         CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (0));
509         route_list_visible_cell->property_activatable() = true;
510         route_list_visible_cell->property_radio() = false;
511
512         route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete));
513         route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change));
514         route_display_model->signal_rows_reordered().connect (mem_fun (*this, &Editor::track_list_reorder));
515
516         route_list_display.signal_button_press_event().connect (mem_fun (*this, &Editor::route_list_display_button_press), false);
517
518         route_list_scroller.add (route_list_display);
519         route_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
520
521         group_model = ListStore::create(group_columns);
522         edit_group_display.set_model (group_model);
523         edit_group_display.append_column (_("Name"), group_columns.text);
524         edit_group_display.append_column (_("Active"), group_columns.is_active);
525         edit_group_display.append_column (_("Show"), group_columns.is_visible);
526         edit_group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
527         edit_group_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
528         edit_group_display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
529         edit_group_display.get_column (0)->set_expand (true);
530         edit_group_display.get_column (1)->set_expand (false);
531         edit_group_display.get_column (2)->set_expand (false);
532         edit_group_display.set_headers_visible (true);
533
534         /* name is directly editable */
535
536         CellRendererText* name_cell = dynamic_cast<CellRendererText*>(edit_group_display.get_column_cell_renderer (0));
537         name_cell->property_editable() = true;
538         name_cell->signal_edited().connect (mem_fun (*this, &Editor::edit_group_name_edit));
539
540         /* use checkbox for the active + visible columns */
541
542         CellRendererToggle* active_cell = dynamic_cast<CellRendererToggle*>(edit_group_display.get_column_cell_renderer (1));
543         active_cell->property_activatable() = true;
544         active_cell->property_radio() = false;
545
546         active_cell = dynamic_cast<CellRendererToggle*>(edit_group_display.get_column_cell_renderer (1));
547         active_cell->property_activatable() = true;
548         active_cell->property_radio() = false;
549
550         group_model->signal_row_changed().connect (mem_fun (*this, &Editor::edit_group_row_change));
551
552         edit_group_display.set_name ("EditGroupList");
553         edit_group_display.get_selection()->set_mode (SELECTION_SINGLE);
554         edit_group_display.set_headers_visible (true);
555         edit_group_display.set_reorderable (false);
556         edit_group_display.set_rules_hint (true);
557         edit_group_display.set_size_request (75, -1);
558
559         edit_group_display_scroller.add (edit_group_display);
560         edit_group_display_scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
561
562         edit_group_display.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event), false);
563
564         VBox* edit_group_display_packer = manage (new VBox());
565         HBox* edit_group_display_button_box = manage (new HBox());
566         edit_group_display_button_box->set_homogeneous (true);
567
568         Button* edit_group_add_button = manage (new Button ());
569         Button* edit_group_remove_button = manage (new Button ());
570
571         Widget* w;
572
573         w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
574         w->show();
575         edit_group_add_button->add (*w);
576
577         w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
578         w->show();
579         edit_group_remove_button->add (*w);
580
581         edit_group_add_button->signal_clicked().connect (mem_fun (*this, &Editor::new_edit_group));
582         edit_group_remove_button->signal_clicked().connect (mem_fun (*this, &Editor::remove_selected_edit_group));
583         
584         edit_group_display_button_box->pack_start (*edit_group_add_button);
585         edit_group_display_button_box->pack_start (*edit_group_remove_button);
586
587         edit_group_display_packer->pack_start (edit_group_display_scroller, true, true);
588         edit_group_display_packer->pack_start (*edit_group_display_button_box, false, false);
589
590         region_list_display.set_size_request (100, -1);
591         region_list_display.set_name ("RegionListDisplay");
592
593         region_list_model = TreeStore::create (region_list_columns);
594         region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
595         region_list_model->set_sort_column (0, SORT_ASCENDING);
596
597         region_list_display.set_model (region_list_model);
598         region_list_display.append_column (_("Regions"), region_list_columns.name);
599         region_list_display.set_headers_visible (false);
600
601         CellRendererText* region_name_cell = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
602         region_name_cell->property_editable() = true;
603         region_name_cell->signal_edited().connect (mem_fun (*this, &Editor::region_name_edit));
604
605         region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter));
606         
607         TreeViewColumn* tv_col = region_list_display.get_column(0);
608         CellRendererText* renderer = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
609         tv_col->add_attribute(renderer->property_text(), region_list_columns.name);
610         tv_col->add_attribute(renderer->property_foreground_gdk(), region_list_columns.color_);
611         
612         region_list_display.get_selection()->set_mode (SELECTION_MULTIPLE);
613         region_list_display.add_object_drag (region_list_columns.region.index(), "regions");
614
615         /* setup DnD handling */
616         
617         list<TargetEntry> region_list_target_table;
618         
619         region_list_target_table.push_back (TargetEntry ("text/plain"));
620         region_list_target_table.push_back (TargetEntry ("text/uri-list"));
621         region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
622         
623         region_list_display.add_drop_targets (region_list_target_table);
624         region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
625
626         region_list_scroller.add (region_list_display);
627         region_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
628
629         region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
630         region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
631         region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press), false);
632         region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
633         region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
634         // region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0));
635         
636         named_selection_scroller.add (named_selection_display);
637         named_selection_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
638
639         named_selection_model = TreeStore::create (named_selection_columns);
640         named_selection_display.set_model (named_selection_model);
641         named_selection_display.append_column (_("Chunks"), named_selection_columns.text);
642         named_selection_display.set_headers_visible (false);
643         named_selection_display.set_size_request (100, -1);
644         named_selection_display.set_name ("NamedSelectionDisplay");
645         
646         named_selection_display.get_selection()->set_mode (SELECTION_SINGLE);
647         named_selection_display.set_size_request (100, -1);
648         named_selection_display.signal_button_release_event().connect (mem_fun(*this, &Editor::named_selection_display_button_release), false);
649         named_selection_display.signal_key_release_event().connect (mem_fun(*this, &Editor::named_selection_display_key_release), false);
650         named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
651
652         /* SNAPSHOTS */
653
654         snapshot_display_model = ListStore::create (snapshot_display_columns);
655         snapshot_display.set_model (snapshot_display_model);
656         snapshot_display.append_column (X_("snapshot"), snapshot_display_columns.visible_name);
657         snapshot_display.set_name ("SnapshotDisplay");
658         snapshot_display.set_size_request (75, -1);
659         snapshot_display.set_headers_visible (false);
660         snapshot_display.set_reorderable (false);
661         snapshot_display_scroller.add (snapshot_display);
662         snapshot_display_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
663
664         snapshot_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::snapshot_display_selection_changed));
665         snapshot_display.signal_button_press_event().connect (mem_fun (*this, &Editor::snapshot_display_button_press), false);
666
667         Gtk::Label* nlabel;
668
669         nlabel = manage (new Label (_("Regions")));
670         nlabel->set_angle (-90);
671         the_notebook.append_page (region_list_scroller, *nlabel);
672         nlabel = manage (new Label (_("Tracks/Busses")));
673         nlabel->set_angle (-90);
674         the_notebook.append_page (route_list_scroller, *nlabel);
675         nlabel = manage (new Label (_("Snapshots")));
676         nlabel->set_angle (-90);
677         the_notebook.append_page (snapshot_display_scroller, *nlabel);
678         nlabel = manage (new Label (_("Edit Groups")));
679         nlabel->set_angle (-90);
680         the_notebook.append_page (*edit_group_display_packer, *nlabel);
681         
682         if (!Profile->get_sae()) {
683                 nlabel = manage (new Label (_("Chunks")));
684                 nlabel->set_angle (-90);
685                 the_notebook.append_page (named_selection_scroller, *nlabel);
686         }
687
688         the_notebook.set_show_tabs (true);
689         the_notebook.set_scrollable (true);
690         the_notebook.popup_enable ();
691         the_notebook.set_tab_pos (Gtk::POS_RIGHT);
692
693         post_maximal_editor_width = 0;
694         post_maximal_pane_position = 0;
695         edit_pane.pack1 (edit_packer, true, true);
696         edit_pane.pack2 (the_notebook, false, true);
697         
698         edit_pane.signal_size_allocate().connect (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
699
700         top_hbox.pack_start (toolbar_frame, true, true);
701
702         HBox *hbox = manage (new HBox);
703         hbox->pack_start (edit_pane, true, true);
704
705         global_vpacker.pack_start (top_hbox, false, false);
706         global_vpacker.pack_start (*hbox, true, true);
707
708         global_hpacker.pack_start (global_vpacker, true, true);
709
710         set_name ("EditorWindow");
711         add_accel_group (ActionManager::ui_manager->get_accel_group());
712
713         status_bar_hpacker.show ();
714
715         vpacker.pack_end (status_bar_hpacker, false, false);
716         vpacker.pack_end (global_hpacker, true, true);
717
718         /* register actions now so that set_state() can find them and set toggles/checks etc */
719         
720         register_actions ();
721
722         snap_type = SnapToBeat;
723         set_snap_to (snap_type);
724         snap_mode = SnapOff;
725         set_snap_mode (snap_mode);
726         _edit_point = EditAtMouse;
727         set_edit_point_preference (_edit_point);
728
729         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
730         set_state (*node);
731
732         _playlist_selector = new PlaylistSelector();
733         _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
734
735         RegionView::RegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_regionview));
736
737         /* nudge stuff */
738
739         nudge_forward_button.add (*(manage (new Image (::get_icon("nudge_right")))));
740         nudge_backward_button.add (*(manage (new Image (::get_icon("nudge_left")))));
741
742         ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge Region/Selection Forwards"));
743         ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge Region/Selection Backwards"));
744
745         nudge_forward_button.set_name ("TransportButton");
746         nudge_backward_button.set_name ("TransportButton");
747
748         fade_context_menu.set_name ("ArdourContextMenu");
749
750         /* icons, titles, WM stuff */
751
752         list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
753         Glib::RefPtr<Gdk::Pixbuf> icon;
754
755         if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
756                 window_icons.push_back (icon);
757         }
758         if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
759                 window_icons.push_back (icon);
760         }
761         if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
762                 window_icons.push_back (icon);
763         }
764         if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
765                 window_icons.push_back (icon);
766         }
767         if (!window_icons.empty()) {
768                 set_icon_list (window_icons);
769                 set_default_icon_list (window_icons);
770         }
771
772         WindowTitle title(Glib::get_application_name());
773         title += _("Editor");
774         set_title (title.get_string());
775         set_wmclass (X_("ardour_editor"), "Ardour");
776
777         add (vpacker);
778         add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
779
780         signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
781         signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
782
783         /* allow external control surfaces/protocols to do various things */
784
785         ControlProtocol::ZoomToSession.connect (mem_fun (*this, &Editor::temporal_zoom_session));
786         ControlProtocol::ZoomIn.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), false));
787         ControlProtocol::ZoomOut.connect (bind (mem_fun (*this, &Editor::temporal_zoom_step), true));
788         ControlProtocol::ScrollTimeline.connect (mem_fun (*this, &Editor::control_scroll));
789
790         Config->ParameterChanged.connect (mem_fun (*this, &Editor::parameter_changed));
791         Route::SyncOrderKeys.connect (mem_fun (*this, &Editor::sync_order_keys));
792
793         constructed = true;
794         instant_save ();
795 }
796
797 Editor::~Editor()
798 {
799         /* <CMT Additions> */
800         if(image_socket_listener)
801         {
802                 if(image_socket_listener->is_connected())
803                 {
804                         image_socket_listener->close_connection() ;
805                 }
806                 
807                 delete image_socket_listener ;
808                 image_socket_listener = 0 ;
809         }
810         /* </CMT Additions> */
811 }
812
813 void
814 Editor::add_toplevel_controls (Container& cont)
815 {
816         vpacker.pack_start (cont, false, false);
817         cont.show_all ();
818 }
819
820 void
821 Editor::catch_vanishing_regionview (RegionView *rv)
822 {
823         /* note: the selection will take care of the vanishing
824            audioregionview by itself.
825         */
826
827         if (clicked_regionview == rv) {
828                 clicked_regionview = 0;
829         }
830
831         if (entered_regionview == rv) {
832                 set_entered_regionview (0);
833         }
834 }
835
836 void
837 Editor::set_entered_regionview (RegionView* rv)
838 {
839         if (rv == entered_regionview) {
840                 return;
841         }
842
843         if (entered_regionview) {
844                 entered_regionview->exited ();
845         }
846
847         if ((entered_regionview = rv) != 0) {
848                 entered_regionview->entered ();
849         }
850 }
851
852 void
853 Editor::set_entered_track (TimeAxisView* tav)
854 {
855         if (entered_track) {
856                 entered_track->exited ();
857         }
858
859         if ((entered_track = tav) != 0) {
860                 entered_track->entered ();
861         }
862 }
863
864 void
865 Editor::show_window ()
866 {
867         show_all ();
868         present ();
869
870         /* now reset all audio_time_axis heights, because widgets might need
871            to be re-hidden
872         */
873         
874         TimeAxisView *tv;
875         
876         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
877                 tv = (static_cast<TimeAxisView*>(*i));
878                 tv->reset_height ();
879         }
880 }
881
882 void
883 Editor::instant_save ()
884 {
885         if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
886                 return;
887         }
888
889         if (session) {
890                 session->add_instant_xml(get_state(), session->path());
891         } else {
892                 Config->add_instant_xml(get_state(), get_user_ardour_path());
893         }
894 }
895
896 void
897 Editor::edit_point_clock_changed()
898 {
899         if (_dragging_edit_point) {
900                 return;
901         }
902
903         if (selection->markers.empty()) {
904                 return;
905         }
906
907         bool ignored;
908         Location* loc = find_location_from_marker (selection->markers.front(), ignored);
909
910         if (!loc) {
911                 return;
912         }
913
914         loc->move_to (edit_point_clock.current_time());
915 }
916
917 void
918 Editor::zoom_adjustment_changed ()
919 {
920         if (session == 0) {
921                 return;
922         }
923
924         double fpu = zoom_range_clock.current_duration() / canvas_width;
925
926         if (fpu < 1.0) {
927                 fpu = 1.0;
928                 zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width));
929         } else if (fpu > session->current_end_frame() / canvas_width) {
930                 fpu = session->current_end_frame() / canvas_width;
931                 zoom_range_clock.set ((nframes_t) floor (fpu * canvas_width));
932         }
933         
934         temporal_zoom (fpu);
935 }
936
937 void
938 Editor::control_scroll (float fraction)
939 {
940         ENSURE_GUI_THREAD(bind (mem_fun (*this, &Editor::control_scroll), fraction));
941
942         if (!session) {
943                 return;
944         }
945
946         double step = fraction * current_page_frames();
947
948         /*
949                 _control_scroll_target is an optional<T>
950         
951                 it acts like a pointer to an nframes_t, with
952                 a operator conversion to boolean to check
953                 that it has a value could possibly use
954                 playhead_cursor->current_frame to store the
955                 value and a boolean in the class to know
956                 when it's out of date
957         */
958
959         if (!_control_scroll_target) {
960                 _control_scroll_target = session->transport_frame();
961                 _dragging_playhead = true;
962         }
963
964         if ((fraction < 0.0f) && (*_control_scroll_target < (nframes_t) fabs(step))) {
965                 *_control_scroll_target = 0;
966         } else if ((fraction > 0.0f) && (max_frames - *_control_scroll_target < step)) {
967                 *_control_scroll_target = max_frames - (current_page_frames()*2); // allow room for slop in where the PH is on the screen
968         } else {
969                 *_control_scroll_target += (nframes_t) floor (step);
970         }
971
972         /* move visuals, we'll catch up with it later */
973
974         playhead_cursor->set_position (*_control_scroll_target);
975         UpdateAllTransportClocks (*_control_scroll_target);
976         
977         if (*_control_scroll_target > (current_page_frames() / 2)) {
978                 /* try to center PH in window */
979                 reset_x_origin (*_control_scroll_target - (current_page_frames()/2));
980         } else {
981                 reset_x_origin (0);
982         }
983
984         /*
985                 Now we do a timeout to actually bring the session to the right place
986                 according to the playhead. This is to avoid reading disk buffers on every
987                 call to control_scroll, which is driven by ScrollTimeline and therefore
988                 probably by a control surface wheel which can generate lots of events.
989         */
990         /* cancel the existing timeout */
991
992         control_scroll_connection.disconnect ();
993
994         /* add the next timeout */
995
996         control_scroll_connection = Glib::signal_timeout().connect (bind (mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
997 }
998
999 bool
1000 Editor::deferred_control_scroll (nframes_t target)
1001 {
1002         session->request_locate (*_control_scroll_target, session->transport_rolling());
1003         // reset for next stream
1004         _control_scroll_target = boost::none;
1005         _dragging_playhead = false;
1006         return false;
1007 }
1008
1009 void
1010 Editor::on_realize ()
1011 {
1012         Window::on_realize ();
1013         Realized ();
1014 }
1015
1016 void
1017 Editor::start_scrolling ()
1018 {
1019         scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect 
1020                 (mem_fun(*this, &Editor::update_current_screen));
1021 }
1022
1023 void
1024 Editor::stop_scrolling ()
1025 {
1026         scroll_connection.disconnect ();
1027 }
1028
1029 void
1030 Editor::map_position_change (nframes_t frame)
1031 {
1032         ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1033
1034         if (session == 0 || !_follow_playhead) {
1035                 return;
1036         }
1037
1038         center_screen (frame);
1039         playhead_cursor->set_position (frame);
1040 }       
1041
1042 void
1043 Editor::center_screen (nframes_t frame)
1044 {
1045         double page = canvas_width * frames_per_unit;
1046
1047         /* if we're off the page, then scroll.
1048          */
1049         
1050         if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1051                 center_screen_internal (frame, page);
1052         }
1053 }
1054
1055 void
1056 Editor::center_screen_internal (nframes_t frame, float page)
1057 {
1058         page /= 2;
1059                 
1060         if (frame > page) {
1061                 frame -= (nframes_t) page;
1062         } else {
1063                 frame = 0;
1064         }
1065
1066         reset_x_origin (frame);
1067 }
1068
1069 void
1070 Editor::handle_new_duration ()
1071 {
1072         ENSURE_GUI_THREAD (mem_fun (*this, &Editor::handle_new_duration));
1073
1074         nframes_t new_end = session->get_maximum_extent() + (nframes_t) floorf (current_page_frames() * 0.10f);
1075                                   
1076         if (new_end > last_canvas_frame) {
1077                 last_canvas_frame = new_end;
1078                 horizontal_adjustment.set_upper (last_canvas_frame / frames_per_unit);
1079                 reset_scrolling_region ();
1080         }
1081
1082         horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
1083 }
1084
1085 void
1086 Editor::update_title_s (const string & snap_name)
1087 {
1088         ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1089         
1090         update_title ();
1091 }
1092
1093 void
1094 Editor::update_title ()
1095 {
1096         ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1097
1098         if (session) {
1099                 bool dirty = session->dirty();
1100
1101                 string session_name;
1102
1103                 if (session->snap_name() != session->name()) {
1104                         session_name = session->snap_name();
1105                 } else {
1106                         session_name = session->name();
1107                 }
1108
1109                 if (dirty) {
1110                         session_name = "*" + session_name;
1111                 }
1112
1113                 WindowTitle title(session_name);
1114                 title += Glib::get_application_name();
1115                 set_title (title.get_string());
1116         }
1117 }
1118
1119 void
1120 Editor::connect_to_session (Session *t)
1121 {
1122         session = t;
1123
1124         /* there are never any selected regions at startup */
1125
1126         sensitize_the_right_region_actions (false);
1127
1128         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1129         set_state (*node);
1130
1131         /* catch up with the playhead */
1132
1133         session->request_locate (playhead_cursor->current_frame);
1134
1135         if (first_action_message) {
1136                 first_action_message->hide();
1137         }
1138
1139         update_title ();
1140
1141         session->GoingAway.connect (mem_fun(*this, &Editor::session_going_away));
1142         session->history().Changed.connect (mem_fun (*this, &Editor::history_changed));
1143
1144         /* These signals can all be emitted by a non-GUI thread. Therefore the
1145            handlers for them must not attempt to directly interact with the GUI,
1146            but use Gtkmm2ext::UI::instance()->call_slot();
1147         */
1148
1149         session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1150         session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1151         session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route)));
1152         session_connections.push_back (session->AudioRegionsAdded.connect (mem_fun(*this, &Editor::handle_new_audio_regions)));
1153         session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::handle_audio_region_removed)));
1154         session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::handle_new_duration)));
1155         session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::add_edit_group)));
1156         session_connections.push_back (session->edit_group_removed.connect (mem_fun(*this, &Editor::edit_groups_changed)));
1157         session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1158         session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1159         session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1160         session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1161         session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1162         session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1163
1164         session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1165
1166         session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1167
1168         edit_groups_changed ();
1169
1170         edit_point_clock.set_session (session);
1171         zoom_range_clock.set_session (session);
1172         _playlist_selector->set_session (session);
1173         nudge_clock.set_session (session);
1174
1175         if (rhythm_ferret) {
1176                 rhythm_ferret->set_session (session);
1177         }
1178
1179 #ifdef FFT_ANALYSIS
1180         if (analysis_window != 0)
1181                 analysis_window->set_session (session);
1182 #endif
1183
1184         Location* loc = session->locations()->auto_loop_location();
1185         if (loc == 0) {
1186                 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1187                 if (loc->start() == loc->end()) {
1188                         loc->set_end (loc->start() + 1);
1189                 }
1190                 session->locations()->add (loc, false);
1191                 session->set_auto_loop_location (loc);
1192         } else {
1193                 // force name
1194                 loc->set_name (_("Loop"));
1195         }
1196         
1197         loc = session->locations()->auto_punch_location();
1198         if (loc == 0) {
1199                 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1200                 if (loc->start() == loc->end()) {
1201                         loc->set_end (loc->start() + 1);
1202                 }
1203                 session->locations()->add (loc, false);
1204                 session->set_auto_punch_location (loc);
1205         } else {
1206                 // force name
1207                 loc->set_name (_("Punch"));
1208         }
1209
1210         Config->map_parameters (mem_fun (*this, &Editor::parameter_changed));
1211         
1212         session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved));
1213         
1214         refresh_location_display ();
1215         session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1216         session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1217         session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1218         session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1219         session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1220
1221         if (sfbrowser) {
1222                 sfbrowser->set_session (session);
1223         }
1224
1225         handle_new_duration ();
1226
1227         redisplay_regions ();
1228         redisplay_named_selections ();
1229         redisplay_snapshots ();
1230
1231         initial_route_list_display ();
1232
1233         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1234                 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1235         }
1236
1237         restore_ruler_visibility ();
1238         //tempo_map_changed (Change (0));
1239         session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1240
1241         start_scrolling ();
1242
1243         /* don't show master bus in a new session */
1244
1245         if (ARDOUR_UI::instance()->session_is_new ()) {
1246
1247                 TreeModel::Children rows = route_display_model->children();
1248                 TreeModel::Children::iterator i;
1249         
1250                 no_route_list_redisplay = true;
1251                 
1252                 for (i = rows.begin(); i != rows.end(); ++i) {
1253                         TimeAxisView *tv =  (*i)[route_display_columns.tv];
1254                         AudioTimeAxisView *atv;
1255                         
1256                         if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1257                                 if (atv->route()->master()) {
1258                                         route_list_display.get_selection()->unselect (i);
1259                                 }
1260                         }
1261                 }
1262                 
1263                 no_route_list_redisplay = false;
1264                 redisplay_route_list ();
1265         }
1266
1267         switch (snap_type) {
1268         case SnapToRegionStart:
1269         case SnapToRegionEnd:
1270         case SnapToRegionSync:
1271         case SnapToRegionBoundary:
1272                 build_region_boundary_cache ();
1273                 break;
1274
1275         default:
1276                 break;
1277         }
1278
1279         /* register for undo history */
1280
1281         session->register_with_memento_command_factory(_id, this);
1282
1283         start_updating ();
1284 }
1285
1286 void
1287 Editor::build_cursors ()
1288 {
1289         using namespace Gdk;
1290         
1291         Gdk::Color mbg ("#000000" ); /* Black */
1292         Gdk::Color mfg ("#0000ff" ); /* Blue. */
1293
1294         {
1295                 RefPtr<Bitmap> source, mask;
1296                 source = Bitmap::create (mag_bits, mag_width, mag_height);
1297                 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1298                 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1299         }
1300
1301         Gdk::Color fbg ("#ffffff" );
1302         Gdk::Color ffg  ("#000000" );
1303         
1304         {
1305                 RefPtr<Bitmap> source, mask;
1306                 
1307                 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1308                 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1309                 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1310         }
1311         
1312         { 
1313                 RefPtr<Bitmap> source, mask;
1314                 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1315                 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1316                 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1317         }
1318
1319         { 
1320                 RefPtr<Bitmap> bits;
1321                 char pix[4] = { 0, 0, 0, 0 };
1322                 bits = Bitmap::create (pix, 2, 2);
1323                 Gdk::Color c;
1324                 transparent_cursor = new Gdk::Cursor (bits, bits, c, c, 0, 0);
1325         }
1326         
1327
1328         grabber_cursor = new Gdk::Cursor (HAND2);
1329         
1330         {
1331                 Glib::RefPtr<Gdk::Pixbuf> grabber_edit_point_pixbuf (::get_icon ("grabber_edit_point"));
1332                 grabber_edit_point_cursor = new Gdk::Cursor (Gdk::Display::get_default(), grabber_edit_point_pixbuf, 5, 17);
1333         }
1334
1335         cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
1336         trimmer_cursor =  new Gdk::Cursor (SB_H_DOUBLE_ARROW);
1337         selector_cursor = new Gdk::Cursor (XTERM);
1338         time_fx_cursor = new Gdk::Cursor (SIZING);
1339         wait_cursor = new Gdk::Cursor  (WATCH);
1340         timebar_cursor = new Gdk::Cursor(LEFT_PTR);
1341 }
1342
1343 void
1344 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1345 {
1346         using namespace Menu_Helpers;
1347         AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1348
1349         if (arv == 0) {
1350                 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1351                 /*NOTREACHED*/
1352         }
1353
1354         MenuList& items (fade_context_menu.items());
1355
1356         items.clear ();
1357
1358         switch (item_type) {
1359         case FadeInItem:
1360         case FadeInHandleItem:
1361                 if (arv->audio_region()->fade_in_active()) {
1362                         items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*this, &Editor::set_fade_in_active), false)));
1363                 } else {
1364                         items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_in_active), true)));
1365                 }
1366                 
1367                 items.push_back (SeparatorElem());
1368
1369                 if (Profile->get_sae()) {
1370                         items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Linear)));
1371                         items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast)));
1372                 } else {
1373                         items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Linear)));
1374                         items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Fast)));
1375                         items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogB)));
1376                         items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::LogA)));
1377                         items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_in_shape), AudioRegion::Slow)));
1378                 }
1379                 break;
1380
1381         case FadeOutItem:
1382         case FadeOutHandleItem:
1383                 if (arv->audio_region()->fade_out_active()) {
1384                         items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*this, &Editor::set_fade_out_active), false)));
1385                 } else {
1386                         items.push_back (MenuElem (_("Activate"), bind (mem_fun (*this, &Editor::set_fade_out_active), true)));
1387                 }
1388                 
1389                 items.push_back (SeparatorElem());
1390
1391                 if (Profile->get_sae()) {
1392                         items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
1393                         items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
1394                 } else {
1395                         items.push_back (MenuElem (_("Linear"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Linear)));
1396                         items.push_back (MenuElem (_("Slowest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Slow)));
1397                         items.push_back (MenuElem (_("Slow"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogA)));
1398                         items.push_back (MenuElem (_("Fast"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::LogB)));
1399                         items.push_back (MenuElem (_("Fastest"), bind (mem_fun (*this, &Editor::set_fade_out_shape), AudioRegion::Fast)));
1400                 }
1401                 break;
1402
1403         default:
1404                 fatal << _("programming error: ")
1405                       << X_("non-fade canvas item passed to popup_fade_context_menu()")
1406                       << endmsg;
1407                 /*NOTREACHED*/
1408         }
1409
1410         fade_context_menu.popup (button, time);
1411 }
1412
1413 void
1414 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, nframes_t frame)
1415 {
1416         using namespace Menu_Helpers;
1417         Menu* (Editor::*build_menu_function)(nframes_t);
1418         Menu *menu;
1419
1420         switch (item_type) {
1421         case RegionItem:
1422         case RegionViewName:
1423         case RegionViewNameHighlight:
1424                 if (with_selection) {
1425                         build_menu_function = &Editor::build_track_selection_context_menu;
1426                 } else {
1427                         build_menu_function = &Editor::build_track_region_context_menu;
1428                 }
1429                 break;
1430
1431         case SelectionItem:
1432                 if (with_selection) {
1433                         build_menu_function = &Editor::build_track_selection_context_menu;
1434                 } else {
1435                         build_menu_function = &Editor::build_track_context_menu;
1436                 }
1437                 break;
1438
1439         case CrossfadeViewItem:
1440                 build_menu_function = &Editor::build_track_crossfade_context_menu;
1441                 break;
1442
1443         case StreamItem:
1444                 if (clicked_audio_trackview->get_diskstream()) {
1445                         build_menu_function = &Editor::build_track_context_menu;
1446                 } else {
1447                         build_menu_function = &Editor::build_track_bus_context_menu;
1448                 }
1449                 break;
1450
1451         default:
1452                 /* probably shouldn't happen but if it does, we don't care */
1453                 return;
1454         }
1455
1456         menu = (this->*build_menu_function)(frame);
1457         menu->set_name ("ArdourContextMenu");
1458         
1459         /* now handle specific situations */
1460
1461         switch (item_type) {
1462         case RegionItem:
1463         case RegionViewName:
1464         case RegionViewNameHighlight:
1465                 if (!with_selection) {
1466                         if (region_edit_menu_split_item) {
1467                                 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1468                                         ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1469                                 } else {
1470                                         ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1471                                 }
1472                         }
1473                         /*
1474                         if (region_edit_menu_split_multichannel_item) {
1475                                 if (clicked_regionview && clicked_regionview->region().n_channels() > 1) {
1476                                         // GTK2FIX find the action, change its sensitivity
1477                                         // region_edit_menu_split_multichannel_item->set_sensitive (true);
1478                                 } else {
1479                                         // GTK2FIX see above
1480                                         // region_edit_menu_split_multichannel_item->set_sensitive (false);
1481                                 }
1482                         }*/
1483                 }
1484                 break;
1485
1486         case SelectionItem:
1487                 break;
1488
1489         case CrossfadeViewItem:
1490                 break;
1491
1492         case StreamItem:
1493                 break;
1494
1495         default:
1496                 /* probably shouldn't happen but if it does, we don't care */
1497                 return;
1498         }
1499
1500         if (item_type != SelectionItem && clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1501
1502                 /* Bounce to disk */
1503                 
1504                 using namespace Menu_Helpers;
1505                 MenuList& edit_items  = menu->items();
1506                 
1507                 edit_items.push_back (SeparatorElem());
1508
1509                 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1510                 case AudioTrack::NoFreeze:
1511                         edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1512                         break;
1513
1514                 case AudioTrack::Frozen:
1515                         edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1516                         break;
1517                         
1518                 case AudioTrack::UnFrozen:
1519                         edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1520                         break;
1521                 }
1522
1523         }
1524
1525         menu->popup (button, time);
1526 }
1527
1528 Menu*
1529 Editor::build_track_context_menu (nframes_t ignored)
1530 {
1531         using namespace Menu_Helpers;
1532
1533         MenuList& edit_items = track_context_menu.items();
1534         edit_items.clear();
1535
1536         add_dstream_context_items (edit_items);
1537         return &track_context_menu;
1538 }
1539
1540 Menu*
1541 Editor::build_track_bus_context_menu (nframes_t ignored)
1542 {
1543         using namespace Menu_Helpers;
1544
1545         MenuList& edit_items = track_context_menu.items();
1546         edit_items.clear();
1547
1548         add_bus_context_items (edit_items);
1549         return &track_context_menu;
1550 }
1551
1552 Menu*
1553 Editor::build_track_region_context_menu (nframes_t frame)
1554 {
1555         using namespace Menu_Helpers;
1556         MenuList& edit_items  = track_region_context_menu.items();
1557         edit_items.clear();
1558
1559         AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1560
1561         if (atv) {
1562                 boost::shared_ptr<Diskstream> ds;
1563                 boost::shared_ptr<Playlist> pl;
1564                 
1565                 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1566                         Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)frame * ds->speed()));
1567                         for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1568                                 add_region_context_items (atv->audio_view(), (*i), edit_items);
1569                         }
1570                         delete regions;
1571                 }
1572         }
1573
1574         add_dstream_context_items (edit_items);
1575
1576         return &track_region_context_menu;
1577 }
1578
1579 Menu*
1580 Editor::build_track_crossfade_context_menu (nframes_t frame)
1581 {
1582         using namespace Menu_Helpers;
1583         MenuList& edit_items  = track_crossfade_context_menu.items();
1584         edit_items.clear ();
1585
1586         AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1587
1588         if (atv) {
1589                 boost::shared_ptr<Diskstream> ds;
1590                 boost::shared_ptr<Playlist> pl;
1591                 boost::shared_ptr<AudioPlaylist> apl;
1592
1593                 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = boost::dynamic_pointer_cast<AudioPlaylist> (pl)) != 0)) {
1594
1595                         Playlist::RegionList* regions = pl->regions_at (frame);
1596                         AudioPlaylist::Crossfades xfades;
1597
1598                         apl->crossfades_at (frame, xfades);
1599
1600                         bool many = xfades.size() > 1;
1601
1602                         for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1603                                 add_crossfade_context_items (atv->audio_view(), (*i), edit_items, many);
1604                         }
1605
1606                         for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1607                                 add_region_context_items (atv->audio_view(), (*i), edit_items);
1608                         }
1609
1610                         delete regions;
1611                 }
1612         }
1613
1614         add_dstream_context_items (edit_items);
1615
1616         return &track_crossfade_context_menu;
1617 }
1618
1619 #ifdef FFT_ANALYSIS
1620 void
1621 Editor::analyze_region_selection()
1622 {
1623         if (analysis_window == 0) {
1624                 analysis_window = new AnalysisWindow();
1625
1626                 if (session != 0)
1627                         analysis_window->set_session(session);
1628
1629                 analysis_window->show_all();
1630         }
1631
1632         analysis_window->set_regionmode();
1633         analysis_window->analyze();
1634         
1635         analysis_window->present();
1636 }
1637
1638 void
1639 Editor::analyze_range_selection()
1640 {
1641         if (analysis_window == 0) {
1642                 analysis_window = new AnalysisWindow();
1643
1644                 if (session != 0)
1645                         analysis_window->set_session(session);
1646
1647                 analysis_window->show_all();
1648         }
1649
1650         analysis_window->set_rangemode();
1651         analysis_window->analyze();
1652         
1653         analysis_window->present();
1654 }
1655 #endif /* FFT_ANALYSIS */
1656
1657
1658
1659 Menu*
1660 Editor::build_track_selection_context_menu (nframes_t ignored)
1661 {
1662         using namespace Menu_Helpers;
1663         MenuList& edit_items  = track_selection_context_menu.items();
1664         edit_items.clear ();
1665
1666         add_selection_context_items (edit_items);
1667         // edit_items.push_back (SeparatorElem());
1668         // add_dstream_context_items (edit_items);
1669
1670         return &track_selection_context_menu;
1671 }
1672
1673 void
1674 Editor::add_crossfade_context_items (AudioStreamView* view, boost::shared_ptr<Crossfade> xfade, Menu_Helpers::MenuList& edit_items, bool many)
1675 {
1676         using namespace Menu_Helpers;
1677         Menu     *xfade_menu = manage (new Menu);
1678         MenuList& items       = xfade_menu->items();
1679         xfade_menu->set_name ("ArdourContextMenu");
1680         string str;
1681
1682         if (xfade->active()) {
1683                 str = _("Mute");
1684         } else { 
1685                 str = _("Unmute");
1686         }
1687
1688         items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), boost::weak_ptr<Crossfade> (xfade))));
1689         items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), boost::weak_ptr<Crossfade> (xfade))));
1690
1691         if (xfade->can_follow_overlap()) {
1692
1693                 if (xfade->following_overlap()) {
1694                         str = _("Convert to short");
1695                 } else {
1696                         str = _("Convert to full");
1697                 }
1698
1699                 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1700         }
1701
1702         if (many) {
1703                 str = xfade->out()->name();
1704                 str += "->";
1705                 str += xfade->in()->name();
1706         } else {
1707                 str = _("Crossfade");
1708         }
1709
1710         edit_items.push_back (MenuElem (str, *xfade_menu));
1711         edit_items.push_back (SeparatorElem());
1712 }
1713
1714 void
1715 Editor::xfade_edit_left_region ()
1716 {
1717         if (clicked_crossfadeview) {
1718                 clicked_crossfadeview->left_view.show_region_editor ();
1719         }
1720 }
1721
1722 void
1723 Editor::xfade_edit_right_region ()
1724 {
1725         if (clicked_crossfadeview) {
1726                 clicked_crossfadeview->right_view.show_region_editor ();
1727         }
1728 }
1729
1730 void
1731 Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region> region, Menu_Helpers::MenuList& edit_items)
1732 {
1733         using namespace Menu_Helpers;
1734         Menu     *region_menu = manage (new Menu);
1735         MenuList& items       = region_menu->items();
1736         region_menu->set_name ("ArdourContextMenu");
1737         
1738         boost::shared_ptr<AudioRegion> ar;
1739
1740         if (region) {
1741                 ar = boost::dynamic_pointer_cast<AudioRegion> (region);
1742         }
1743
1744         /* when this particular menu pops up, make the relevant region 
1745            become selected.
1746         */
1747
1748         region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, boost::weak_ptr<Region>(region)));
1749
1750         items.push_back (MenuElem (_("Rename"), mem_fun(*this, &Editor::rename_region)));
1751         items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1752         items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1753         items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun  (*this, &Editor::lower_region_to_bottom)));
1754         items.push_back (SeparatorElem());
1755         items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_point)));
1756         items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1757         items.push_back (SeparatorElem());
1758
1759         items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::play_selected_region)));
1760         items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1761         items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1762
1763 #ifdef FFT_ANALYSIS
1764         items.push_back (MenuElem (_("Analyze region"), mem_fun(*this, &Editor::analyze_region_selection)));
1765 #endif
1766
1767         items.push_back (SeparatorElem());
1768
1769         sigc::connection fooc;
1770
1771         items.push_back (CheckMenuElem (_("Lock")));
1772         CheckMenuItem* region_lock_item = static_cast<CheckMenuItem*>(&items.back());
1773         if (region->locked()) {
1774                 region_lock_item->set_active();
1775         }
1776         region_lock_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_lock));
1777
1778         items.push_back (CheckMenuElem (_("Glue to Bars&Beats")));
1779         CheckMenuItem* bbt_glue_item = static_cast<CheckMenuItem*>(&items.back());
1780
1781         switch (region->positional_lock_style()) {
1782         case Region::MusicTime:
1783                 bbt_glue_item->set_active (true);
1784                 break;
1785         default:
1786                 bbt_glue_item->set_active (false);
1787                 break;
1788         }
1789
1790         bbt_glue_item->signal_activate().connect (bind (mem_fun (*this, &Editor::set_region_lock_style), Region::MusicTime));
1791
1792         items.push_back (CheckMenuElem (_("Mute")));
1793         CheckMenuItem* region_mute_item = static_cast<CheckMenuItem*>(&items.back());
1794         fooc = region_mute_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_mute));
1795         if (region->muted()) {
1796                 fooc.block (true);
1797                 region_mute_item->set_active();
1798                 fooc.block (false);
1799         }
1800         
1801         if (!Profile->get_sae()) {
1802                 items.push_back (CheckMenuElem (_("Opaque")));
1803                 CheckMenuItem* region_opaque_item = static_cast<CheckMenuItem*>(&items.back());
1804                 fooc = region_opaque_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_region_opaque));
1805                 if (region->opaque()) {
1806                         fooc.block (true);
1807                         region_opaque_item->set_active();
1808                         fooc.block (false);
1809                 }
1810         }
1811
1812         items.push_back (CheckMenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1813         if (region->at_natural_position()) {
1814                 items.back().set_sensitive (false);
1815         }
1816         
1817         items.push_back (SeparatorElem());
1818         
1819         if (ar) {
1820                 
1821                 RegionView* rv = sv->find_view (ar);
1822                 AudioRegionView* arv = dynamic_cast<AudioRegionView*>(rv);
1823                 
1824                 if (!Profile->get_sae()) {
1825                         items.push_back (MenuElem (_("Reset Envelope"), mem_fun(*this, &Editor::reset_region_gain_envelopes)));
1826
1827                         items.push_back (CheckMenuElem (_("Envelope Visible")));
1828                         CheckMenuItem* region_envelope_visible_item = static_cast<CheckMenuItem*> (&items.back());
1829                         fooc = region_envelope_visible_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_visibility));
1830                         if (arv->envelope_visible()) {
1831                                 fooc.block (true);
1832                                 region_envelope_visible_item->set_active (true);
1833                                 fooc.block (false);
1834                         }
1835                 
1836                         items.push_back (CheckMenuElem (_("Envelope Active")));
1837                         CheckMenuItem* region_envelope_active_item = static_cast<CheckMenuItem*> (&items.back());
1838                         fooc = region_envelope_active_item->signal_activate().connect (mem_fun(*this, &Editor::toggle_gain_envelope_active));
1839                         
1840                         if (ar->envelope_active()) {
1841                                 fooc.block (true);
1842                                 region_envelope_active_item->set_active (true);
1843                                 fooc.block (false);
1844                         }
1845
1846                         items.push_back (SeparatorElem());
1847                 }
1848
1849                 if (ar->scale_amplitude() != 1.0f) {
1850                         items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1851                 } else {
1852                         items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1853                 }
1854         }
1855
1856         items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1857         items.push_back (SeparatorElem());
1858
1859         /* range related stuff */
1860
1861         items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_audio_region)));
1862         items.push_back (MenuElem (_("Set Range Selection"), mem_fun (*this, &Editor::set_selection_from_audio_region)));
1863         items.push_back (SeparatorElem());
1864                          
1865         /* Nudge region */
1866
1867         Menu *nudge_menu = manage (new Menu());
1868         MenuList& nudge_items = nudge_menu->items();
1869         nudge_menu->set_name ("ArdourContextMenu");
1870         
1871         nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false, false))));
1872         nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false, false))));
1873         nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1874         nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1875
1876         items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1877         items.push_back (SeparatorElem());
1878
1879         Menu *trim_menu = manage (new Menu);
1880         MenuList& trim_items = trim_menu->items();
1881         trim_menu->set_name ("ArdourContextMenu");
1882         
1883         trim_items.push_back (MenuElem (_("Start to edit point"), mem_fun(*this, &Editor::trim_region_from_edit_point)));
1884         trim_items.push_back (MenuElem (_("Edit point to end"), mem_fun(*this, &Editor::trim_region_to_edit_point)));
1885         trim_items.push_back (MenuElem (_("Trim To Loop"), mem_fun(*this, &Editor::trim_region_to_loop)));
1886         trim_items.push_back (MenuElem (_("Trim To Punch"), mem_fun(*this, &Editor::trim_region_to_punch)));
1887                              
1888         items.push_back (MenuElem (_("Trim"), *trim_menu));
1889         items.push_back (SeparatorElem());
1890
1891         items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1892         region_edit_menu_split_item = &items.back();
1893
1894         items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1895         region_edit_menu_split_multichannel_item = &items.back();
1896
1897         items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), false))));
1898         items.push_back (MenuElem (_("Multi-Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1899         items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1900         items.push_back (SeparatorElem());
1901         items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1902
1903         /* OK, stick the region submenu at the top of the list, and then add
1904            the standard items.
1905         */
1906
1907         /* we have to hack up the region name because "_" has a special
1908            meaning for menu titles.
1909         */
1910
1911         string::size_type pos = 0;
1912         string menu_item_name = region->name();
1913
1914         while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1915                 menu_item_name.replace (pos, 1, "__");
1916                 pos += 2;
1917         }
1918         
1919         edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1920         edit_items.push_back (SeparatorElem());
1921 }
1922
1923 void
1924 Editor::add_selection_context_items (Menu_Helpers::MenuList& items)
1925 {
1926         using namespace Menu_Helpers;
1927
1928         items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1929         items.push_back (MenuElem (_("Loop range"), bind (mem_fun(*this, &Editor::set_loop_from_selection), true)));
1930
1931 #ifdef FFT_ANALYSIS
1932         items.push_back (SeparatorElem());
1933         items.push_back (MenuElem (_("Analyze range"), mem_fun(*this, &Editor::analyze_range_selection)));
1934 #endif
1935         
1936         items.push_back (SeparatorElem());
1937         items.push_back (MenuElem (_("Extend Range to End of Region"), bind (mem_fun(*this, &Editor::extend_selection_to_end_of_region), false)));
1938         items.push_back (MenuElem (_("Extend Range to Start of Region"), bind (mem_fun(*this, &Editor::extend_selection_to_start_of_region), false)));
1939
1940         items.push_back (SeparatorElem());
1941         items.push_back (MenuElem (_("Convert to region in-place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1942         items.push_back (MenuElem (_("Convert to region in region list"), mem_fun(*this, &Editor::new_region_from_selection)));
1943         
1944         items.push_back (SeparatorElem());
1945         items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1946
1947         items.push_back (SeparatorElem());
1948         items.push_back (MenuElem (_("Set loop from selection"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
1949         items.push_back (MenuElem (_("Set punch from selection"), mem_fun(*this, &Editor::set_punch_from_selection)));
1950         
1951         items.push_back (SeparatorElem());
1952         items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection)));
1953         items.push_back (SeparatorElem());
1954         items.push_back (MenuElem (_("Crop region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1955         items.push_back (MenuElem (_("Fill range with region"), mem_fun(*this, &Editor::region_fill_selection)));
1956         items.push_back (MenuElem (_("Duplicate range"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1957         items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::create_named_selection)));
1958         items.push_back (SeparatorElem());
1959         items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1960         items.push_back (MenuElem (_("Export range"), mem_fun(*this, &Editor::export_selection)));
1961 }
1962
1963 void
1964 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1965 {
1966         using namespace Menu_Helpers;
1967
1968         /* Playback */
1969
1970         Menu *play_menu = manage (new Menu);
1971         MenuList& play_items = play_menu->items();
1972         play_menu->set_name ("ArdourContextMenu");
1973         
1974         play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
1975         play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1976         play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1977         play_items.push_back (SeparatorElem());
1978         play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1979         
1980         edit_items.push_back (MenuElem (_("Play"), *play_menu));
1981
1982         /* Selection */
1983
1984         Menu *select_menu = manage (new Menu);
1985         MenuList& select_items = select_menu->items();
1986         select_menu->set_name ("ArdourContextMenu");
1987         
1988         select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1989         select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
1990         select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1991         select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
1992         select_items.push_back (SeparatorElem());
1993         select_items.push_back (MenuElem (_("Set range to loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1994         select_items.push_back (MenuElem (_("Set range to punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1995         select_items.push_back (SeparatorElem());
1996         select_items.push_back (MenuElem (_("Select All After Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1997         select_items.push_back (MenuElem (_("Select All Before Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1998         select_items.push_back (MenuElem (_("Select All After Playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1999         select_items.push_back (MenuElem (_("Select All Before Playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2000         select_items.push_back (MenuElem (_("Select All Between Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), false)));
2001         select_items.push_back (MenuElem (_("Select All Within Playhead & Edit Point"), bind (mem_fun(*this, &Editor::select_all_selectables_between), true)));
2002         select_items.push_back (MenuElem (_("Select Range Between Playhead & Edit Point"), mem_fun(*this, &Editor::select_range_between)));
2003
2004         select_items.push_back (SeparatorElem());
2005
2006         edit_items.push_back (MenuElem (_("Select"), *select_menu));
2007
2008         /* Cut-n-Paste */
2009
2010         Menu *cutnpaste_menu = manage (new Menu);
2011         MenuList& cutnpaste_items = cutnpaste_menu->items();
2012         cutnpaste_menu->set_name ("ArdourContextMenu");
2013         
2014         cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2015         cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2016         cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2017
2018         cutnpaste_items.push_back (SeparatorElem());
2019
2020         cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2021         cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2022
2023         cutnpaste_items.push_back (SeparatorElem());
2024
2025         cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2026
2027         edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2028
2029         /* Adding new material */
2030         
2031         edit_items.push_back (SeparatorElem());
2032         edit_items.push_back (MenuElem (_("Insert Selected Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2033         edit_items.push_back (MenuElem (_("Insert Existing Audio"), bind (mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2034
2035         /* Nudge track */
2036
2037         Menu *nudge_menu = manage (new Menu());
2038         MenuList& nudge_items = nudge_menu->items();
2039         nudge_menu->set_name ("ArdourContextMenu");
2040         
2041         edit_items.push_back (SeparatorElem());
2042         nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2043         nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2044         nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2045         nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2046
2047         edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2048 }
2049
2050 void
2051 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2052 {
2053         using namespace Menu_Helpers;
2054
2055         /* Playback */
2056
2057         Menu *play_menu = manage (new Menu);
2058         MenuList& play_items = play_menu->items();
2059         play_menu->set_name ("ArdourContextMenu");
2060         
2061         play_items.push_back (MenuElem (_("Play from edit point"), mem_fun(*this, &Editor::play_from_edit_point)));
2062         play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2063         edit_items.push_back (MenuElem (_("Play"), *play_menu));
2064
2065         /* Selection */
2066
2067         Menu *select_menu = manage (new Menu);
2068         MenuList& select_items = select_menu->items();
2069         select_menu->set_name ("ArdourContextMenu");
2070         
2071         select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2072         select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), Selection::Set)));
2073         select_items.push_back (MenuElem (_("Invert selection in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2074         select_items.push_back (MenuElem (_("Invert selection"), mem_fun(*this, &Editor::invert_selection)));
2075         select_items.push_back (SeparatorElem());
2076         select_items.push_back (MenuElem (_("Select all after edit point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
2077         select_items.push_back (MenuElem (_("Select all before edit point"), bind (mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
2078         select_items.push_back (MenuElem (_("Select all after playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2079         select_items.push_back (MenuElem (_("Select all before playhead"), bind (mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2080
2081         edit_items.push_back (MenuElem (_("Select"), *select_menu));
2082
2083         /* Cut-n-Paste */
2084
2085         Menu *cutnpaste_menu = manage (new Menu);
2086         MenuList& cutnpaste_items = cutnpaste_menu->items();
2087         cutnpaste_menu->set_name ("ArdourContextMenu");
2088         
2089         cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2090         cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2091         cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2092
2093         Menu *nudge_menu = manage (new Menu());
2094         MenuList& nudge_items = nudge_menu->items();
2095         nudge_menu->set_name ("ArdourContextMenu");
2096         
2097         edit_items.push_back (SeparatorElem());
2098         nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2099         nudge_items.push_back (MenuElem (_("Nudge track after edit point fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2100         nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2101         nudge_items.push_back (MenuElem (_("Nudge track after edit point bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2102
2103         edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2104 }
2105
2106 void
2107 Editor::set_snap_to (SnapType st)
2108 {
2109         unsigned int snap_ind = (unsigned int)st;
2110         snap_type = st;
2111         
2112         if (snap_ind > snap_type_strings.size() - 1) {
2113                 snap_ind = 0;
2114                 snap_type = (SnapType)snap_ind;
2115         }
2116         
2117         string str = snap_type_strings[snap_ind];
2118
2119         if (str != snap_type_selector.get_active_text()) {
2120                 snap_type_selector.set_active_text (str);
2121         }
2122
2123         instant_save ();
2124
2125         switch (snap_type) {
2126         case SnapToAThirtysecondBeat:
2127         case SnapToASixteenthBeat:
2128         case SnapToAEighthBeat:
2129         case SnapToAQuarterBeat:
2130         case SnapToAThirdBeat:
2131                 update_tempo_based_rulers ();
2132                 break;
2133
2134         case SnapToRegionStart:
2135         case SnapToRegionEnd:
2136         case SnapToRegionSync:
2137         case SnapToRegionBoundary:
2138                 build_region_boundary_cache ();
2139                 break;
2140
2141         default:
2142                 /* relax */
2143                 break;
2144     }
2145 }
2146
2147 void
2148 Editor::set_snap_mode (SnapMode mode)
2149 {
2150         snap_mode = mode;
2151         string str = snap_mode_strings[(int)mode];
2152
2153         if (str != snap_mode_selector.get_active_text ()) {
2154                 snap_mode_selector.set_active_text (str);
2155         }
2156
2157         instant_save ();
2158 }
2159 void
2160 Editor::set_edit_point_preference (EditPoint ep)
2161 {
2162         bool changed = _edit_point != ep;
2163
2164         _edit_point = ep;
2165         string str = edit_point_strings[(int)ep];
2166
2167         if (str != edit_point_selector.get_active_text ()) {
2168                 edit_point_selector.set_active_text (str);
2169         }
2170
2171         set_canvas_cursor ();
2172
2173         if (!changed) {
2174                 return;
2175         }
2176
2177         switch (zoom_focus) {
2178         case ZoomFocusMouse:
2179         case ZoomFocusPlayhead:
2180         case ZoomFocusEdit:
2181                 switch (_edit_point) {
2182                 case EditAtMouse:
2183                         set_zoom_focus (ZoomFocusMouse);
2184                         break;
2185                 case EditAtPlayhead:
2186                         set_zoom_focus (ZoomFocusPlayhead);
2187                         break;
2188                 case EditAtSelectedMarker:
2189                         set_zoom_focus (ZoomFocusEdit);
2190                         break;
2191                 }
2192                 break;
2193         default:
2194                 break;
2195         }
2196
2197         instant_save ();
2198 }
2199
2200 int
2201 Editor::set_state (const XMLNode& node)
2202 {
2203         const XMLProperty* prop;
2204         XMLNode* geometry;
2205         int x, y, xoff, yoff;
2206         Gdk::Geometry g;
2207
2208         if ((prop = node.property ("id")) != 0) {
2209                 _id = prop->value ();
2210         }
2211
2212         if ((geometry = find_named_node (node, "geometry")) == 0) {
2213
2214                 g.base_width = default_width;
2215                 g.base_height = default_height;
2216                 x = 1;
2217                 y = 1;
2218                 xoff = 0;
2219                 yoff = 21;
2220
2221         } else {
2222
2223                 g.base_width = atoi(geometry->property("x_size")->value());
2224                 g.base_height = atoi(geometry->property("y_size")->value());
2225                 x = atoi(geometry->property("x_pos")->value());
2226                 y = atoi(geometry->property("y_pos")->value());
2227                 xoff = atoi(geometry->property("x_off")->value());
2228                 yoff = atoi(geometry->property("y_off")->value());
2229         }
2230
2231         set_default_size (g.base_width, g.base_height);
2232         move (x, y);
2233
2234         if (session && (prop = node.property ("playhead"))) {
2235                 nframes_t pos = atol (prop->value().c_str());
2236                 playhead_cursor->set_position (pos);
2237         } else {
2238                 playhead_cursor->set_position (0);
2239
2240                 /* reset_x_origin() doesn't work right here, since the old
2241                    position may be zero already, and it does nothing in such
2242                    circumstances.
2243                 */
2244                 
2245                 leftmost_frame = 0;
2246                 horizontal_adjustment.set_value (0);
2247         }
2248
2249         if ((prop = node.property ("mixer-width"))) {
2250                 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2251         }
2252
2253         if ((prop = node.property ("zoom-focus"))) {
2254                 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2255         }
2256
2257         if ((prop = node.property ("zoom"))) {
2258                 reset_zoom (PBD::atof (prop->value()));
2259         }
2260
2261         if ((prop = node.property ("snap-to"))) {
2262                 set_snap_to ((SnapType) atoi (prop->value()));
2263         }
2264
2265         if ((prop = node.property ("snap-mode"))) {
2266                 set_snap_mode ((SnapMode) atoi (prop->value()));
2267         }
2268
2269         if ((prop = node.property ("edit-point"))) {
2270                 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point));
2271         }
2272
2273         if ((prop = node.property ("mouse-mode"))) {
2274                 MouseMode m = str2mousemode(prop->value());
2275                 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2276                 set_mouse_mode (m, true);
2277         } else {
2278                 mouse_mode = MouseGain; /* lie, to force the mode switch */
2279                 set_mouse_mode (MouseObject, true);
2280         }
2281
2282         if ((prop = node.property ("show-waveforms"))) {
2283                 bool yn = (prop->value() == "yes");
2284                 _show_waveforms = !yn;
2285                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-waveform-visible"));
2286                 if (act) {
2287                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2288                         /* do it twice to force the change */
2289                         tact->set_active (!yn);
2290                         tact->set_active (yn);
2291                 }
2292         }
2293
2294         if ((prop = node.property ("show-waveforms-recording"))) {
2295                 bool yn = (prop->value() == "yes");
2296                 _show_waveforms_recording = !yn;
2297                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformsWhileRecording"));
2298                 if (act) {
2299                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2300                         /* do it twice to force the change */
2301                         tact->set_active (!yn);
2302                         tact->set_active (yn);
2303                 }
2304         }
2305         
2306         if ((prop = node.property ("show-measures"))) {
2307                 bool yn = (prop->value() == "yes");
2308                 _show_measures = !yn;
2309                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2310                 if (act) {
2311                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2312                         /* do it twice to force the change */
2313                         tact->set_active (!yn);
2314                         tact->set_active (yn);
2315                 }
2316         }
2317
2318         if ((prop = node.property ("follow-playhead"))) {
2319                 bool yn = (prop->value() == "yes");
2320                 set_follow_playhead (yn);
2321                 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2322                 if (act) {
2323                         RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2324                         if (tact->get_active() != yn) {
2325                                 tact->set_active (yn);
2326                         }
2327                 }
2328         }
2329
2330         if ((prop = node.property ("region-list-sort-type"))) {
2331                 region_list_sort_type = (Editing::RegionListSortType) -1; // force change 
2332                 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2333         }
2334
2335         if ((prop = node.property ("xfades-visible"))) {
2336                 bool yn = (prop->value() == "yes");
2337                 _xfade_visibility = !yn;
2338                 // set_xfade_visibility (yn);
2339         }
2340
2341         if ((prop = node.property ("show-editor-mixer"))) {
2342
2343                 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2344                 if (act) {
2345
2346                         Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2347                         bool yn = (prop->value() == X_("yes"));
2348
2349                         /* do it twice to force the change */
2350                         
2351                         tact->set_active (!yn);
2352                         tact->set_active (yn);
2353                 }
2354         }
2355
2356
2357         return 0;
2358 }
2359
2360 XMLNode&
2361 Editor::get_state ()
2362 {
2363         XMLNode* node = new XMLNode ("Editor");
2364         char buf[32];
2365
2366         _id.print (buf, sizeof (buf));
2367         node->add_property ("id", buf);
2368         
2369         if (is_realized()) {
2370                 Glib::RefPtr<Gdk::Window> win = get_window();
2371                 
2372                 int x, y, xoff, yoff, width, height;
2373                 win->get_root_origin(x, y);
2374                 win->get_position(xoff, yoff);
2375                 win->get_size(width, height);
2376                 
2377                 XMLNode* geometry = new XMLNode ("geometry");
2378
2379                 snprintf(buf, sizeof(buf), "%d", width);
2380                 geometry->add_property("x_size", string(buf));
2381                 snprintf(buf, sizeof(buf), "%d", height);
2382                 geometry->add_property("y_size", string(buf));
2383                 snprintf(buf, sizeof(buf), "%d", x);
2384                 geometry->add_property("x_pos", string(buf));
2385                 snprintf(buf, sizeof(buf), "%d", y);
2386                 geometry->add_property("y_pos", string(buf));
2387                 snprintf(buf, sizeof(buf), "%d", xoff);
2388                 geometry->add_property("x_off", string(buf));
2389                 snprintf(buf, sizeof(buf), "%d", yoff);
2390                 geometry->add_property("y_off", string(buf));
2391                 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2392                 geometry->add_property("edit_pane_pos", string(buf));
2393
2394                 node->add_child_nocopy (*geometry);
2395         }
2396
2397         maybe_add_mixer_strip_width (*node);
2398         
2399         snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2400         node->add_property ("zoom-focus", buf);
2401         snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2402         node->add_property ("zoom", buf);
2403         snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2404         node->add_property ("snap-to", buf);
2405         snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2406         node->add_property ("snap-mode", buf);
2407
2408         node->add_property ("edit-point", enum_2_string (_edit_point));
2409
2410         snprintf (buf, sizeof (buf), "%" PRIu32, playhead_cursor->current_frame);
2411         node->add_property ("playhead", buf);
2412
2413         node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2414         node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2415         node->add_property ("show-measures", _show_measures ? "yes" : "no");
2416         node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2417         node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2418         node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2419         node->add_property ("mouse-mode", enum2str(mouse_mode));
2420         
2421         Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2422         if (act) {
2423                 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2424                 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2425         }
2426
2427         return *node;
2428 }
2429
2430
2431
2432 TimeAxisView *
2433 Editor::trackview_by_y_position (double y)
2434 {
2435         for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2436
2437                 TimeAxisView *tv;
2438
2439                 if ((tv = (*iter)->covers_y_position (y)) != 0) {
2440                         return tv;
2441                 }
2442         }
2443
2444         return 0;
2445 }
2446
2447 void
2448 Editor::snap_to (nframes64_t& start, int32_t direction, bool for_mark)
2449 {
2450         if (!session || snap_mode == SnapOff) {
2451                 return;
2452         }
2453
2454         snap_to_internal (start, direction, for_mark);
2455 }
2456
2457 void
2458 Editor::snap_to_internal (nframes64_t& start, int32_t direction, bool for_mark)
2459 {
2460         Location* before = 0;
2461         Location* after = 0;
2462
2463         const nframes64_t one_second = session->frame_rate();
2464         const nframes64_t one_minute = session->frame_rate() * 60;
2465         const nframes64_t one_smpte_second = (nframes64_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame());
2466         nframes64_t one_smpte_minute = (nframes64_t)(rint(session->smpte_frames_per_second()) * session->frames_per_smpte_frame() * 60);
2467         nframes64_t presnap = start;
2468
2469         switch (snap_type) {
2470         case SnapToCDFrame:
2471                 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2472                         start = (nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2473                 } else {
2474                         start = (nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2475                 }
2476                 break;
2477
2478         case SnapToSMPTEFrame:
2479                 if (((direction == 0) && (fmod((double)start, (double)session->frames_per_smpte_frame()) > (session->frames_per_smpte_frame() / 2))) || (direction > 0)) {
2480                         start = (nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2481                 } else {
2482                         start = (nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) *  session->frames_per_smpte_frame());
2483                 }
2484                 break;
2485
2486         case SnapToSMPTESeconds:
2487                 if (session->smpte_offset_negative())
2488                 {
2489                         start += session->smpte_offset ();
2490                 } else {
2491                         start -= session->smpte_offset ();
2492                 }    
2493                 if (((direction == 0) && (start % one_smpte_second > one_smpte_second / 2)) || direction > 0) {
2494                         start = (nframes_t) ceil ((double) start / one_smpte_second) * one_smpte_second;
2495                 } else {
2496                         start = (nframes_t) floor ((double) start / one_smpte_second) * one_smpte_second;
2497                 }
2498                 
2499                 if (session->smpte_offset_negative())
2500                 {
2501                         start -= session->smpte_offset ();
2502                 } else {
2503                         start += session->smpte_offset ();
2504                 }
2505                 break;
2506                 
2507         case SnapToSMPTEMinutes:
2508                 if (session->smpte_offset_negative())
2509                 {
2510                         start += session->smpte_offset ();
2511                 } else {
2512                         start -= session->smpte_offset ();
2513                 }
2514                 if (((direction == 0) && (start % one_smpte_minute > one_smpte_minute / 2)) || direction > 0) {
2515                         start = (nframes_t) ceil ((double) start / one_smpte_minute) * one_smpte_minute;
2516                 } else {
2517                         start = (nframes_t) floor ((double) start / one_smpte_minute) * one_smpte_minute;
2518                 }
2519                 if (session->smpte_offset_negative())
2520                 {
2521                         start -= session->smpte_offset ();
2522                 } else {
2523                         start += session->smpte_offset ();
2524                 }
2525                 break;
2526                 
2527         case SnapToSeconds:
2528                 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2529                         start = (nframes_t) ceil ((double) start / one_second) * one_second;
2530                 } else {
2531                         start = (nframes_t) floor ((double) start / one_second) * one_second;
2532                 }
2533                 break;
2534                 
2535         case SnapToMinutes:
2536                 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2537                         start = (nframes_t) ceil ((double) start / one_minute) * one_minute;
2538                 } else {
2539                         start = (nframes_t) floor ((double) start / one_minute) * one_minute;
2540                 }
2541                 break;
2542
2543         case SnapToBar:
2544                 start = session->tempo_map().round_to_bar (start, direction);
2545                 break;
2546
2547         case SnapToBeat:
2548                 start = session->tempo_map().round_to_beat (start, direction);
2549                 break;
2550
2551         case SnapToAThirtysecondBeat:
2552                 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2553                 break;
2554
2555         case SnapToASixteenthBeat:
2556                 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2557                 break;
2558
2559         case SnapToAEighthBeat:
2560                 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2561                 break;
2562
2563         case SnapToAQuarterBeat:
2564                 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2565                 break;
2566
2567         case SnapToAThirdBeat:
2568                 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2569                 break;
2570
2571         case SnapToMark:
2572                 if (for_mark) {
2573                         return;
2574                 }
2575
2576                 before = session->locations()->first_location_before (start);
2577                 after = session->locations()->first_location_after (start);
2578
2579                 if (direction < 0) {
2580                         if (before) {
2581                                 start = before->start();
2582                         } else {
2583                                 start = 0;
2584                         }
2585                 } else if (direction > 0) {
2586                         if (after) {
2587                                 start = after->start();
2588                         } else {
2589                                 start = session->current_end_frame();
2590                         }
2591                 } else {
2592                         if (before) {
2593                                 if (after) {
2594                                         /* find nearest of the two */
2595                                         if ((start - before->start()) < (after->start() - start)) {
2596                                                 start = before->start();
2597                                         } else {
2598                                                 start = after->start();
2599                                         }
2600                                 } else {
2601                                         start = before->start();
2602                                 }
2603                         } else if (after) {
2604                                 start = after->start();
2605                         } else {
2606                                 /* relax */
2607                         }
2608                 }
2609                 break;
2610
2611         case SnapToRegionStart:
2612         case SnapToRegionEnd:
2613         case SnapToRegionSync:
2614         case SnapToRegionBoundary:
2615                 if (!region_boundary_cache.empty()) {
2616                         vector<nframes_t>::iterator i;
2617
2618                         if (direction > 0) {
2619                                 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2620                         } else {
2621                                 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2622                         }
2623                         
2624                         if (i != region_boundary_cache.end()) {
2625
2626                                 /* lower bound doesn't quite to the right thing for our purposes */
2627
2628                                 if (direction < 0 && i != region_boundary_cache.begin()) {
2629                                         --i;
2630                                 }
2631
2632                                 start = *i;
2633
2634                         } else {
2635                                 start = region_boundary_cache.back();
2636                         }
2637                 } 
2638                 break;
2639         }
2640
2641         switch (snap_mode) {
2642         case SnapNormal:
2643                 return;                 
2644                 
2645         case SnapMagnetic:
2646                 
2647                 if (presnap > start) {
2648                         if (presnap > (start + unit_to_frame(snap_threshold))) {
2649                                 start = presnap;
2650                         }
2651                         
2652                 } else if (presnap < start) {
2653                         if (presnap < (start - unit_to_frame(snap_threshold))) {
2654                                 start = presnap;
2655                         }
2656                 }
2657                 
2658         default:
2659                 /* handled at entry */
2660                 return;
2661                 
2662         }
2663 }
2664
2665 void
2666 Editor::setup_toolbar ()
2667 {
2668         string pixmap_path;
2669
2670 #ifdef GTKOSX
2671         const guint32 FUDGE = 38; // Combo's are stupid - they steal space from the entry for the button
2672 #else
2673         const guint32 FUDGE = 18; // Combo's are stupid - they steal space from the entry for the button
2674 #endif
2675
2676         /* Mode Buttons (tool selection) */
2677
2678         vector<ToggleButton *> mouse_mode_buttons;
2679
2680         mouse_move_button.add (*(manage (new Image (::get_icon("tool_object")))));
2681         mouse_move_button.set_relief(Gtk::RELIEF_NONE);
2682         mouse_mode_buttons.push_back (&mouse_move_button);
2683
2684         if (!Profile->get_sae()) {
2685                 mouse_select_button.add (*(manage (new Image (get_xpm("tool_range.xpm")))));
2686                 mouse_select_button.set_relief(Gtk::RELIEF_NONE);
2687                 mouse_mode_buttons.push_back (&mouse_select_button);
2688
2689                 mouse_gain_button.add (*(manage (new Image (::get_icon("tool_gain")))));
2690                 mouse_gain_button.set_relief(Gtk::RELIEF_NONE);
2691                 mouse_mode_buttons.push_back (&mouse_gain_button);
2692         }
2693
2694         mouse_zoom_button.add (*(manage (new Image (::get_icon("tool_zoom")))));
2695         mouse_zoom_button.set_relief(Gtk::RELIEF_NONE);
2696         mouse_mode_buttons.push_back (&mouse_zoom_button);
2697         mouse_timefx_button.add (*(manage (new Image (::get_icon("tool_stretch")))));
2698         mouse_timefx_button.set_relief(Gtk::RELIEF_NONE);
2699         mouse_mode_buttons.push_back (&mouse_timefx_button);
2700         mouse_audition_button.add (*(manage (new Image (::get_icon("tool_audition")))));
2701         mouse_audition_button.set_relief(Gtk::RELIEF_NONE);
2702         mouse_mode_buttons.push_back (&mouse_audition_button);
2703         
2704         mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2705
2706         HBox* mode_box = manage(new HBox);
2707         mode_box->set_border_width (2);
2708         mode_box->set_spacing(4);
2709         mouse_mode_button_box.set_spacing(1);
2710         mouse_mode_button_box.pack_start(mouse_move_button, true, true);
2711         if (!Profile->get_sae()) {
2712                 mouse_mode_button_box.pack_start(mouse_select_button, true, true);
2713         }
2714         mouse_mode_button_box.pack_start(mouse_zoom_button, true, true);
2715         if (!Profile->get_sae()) {
2716                 mouse_mode_button_box.pack_start(mouse_gain_button, true, true);
2717         }
2718         mouse_mode_button_box.pack_start(mouse_timefx_button, true, true);
2719         mouse_mode_button_box.pack_start(mouse_audition_button, true, true);
2720         mouse_mode_button_box.set_homogeneous(true);
2721
2722         vector<string> edit_mode_strings;
2723         edit_mode_strings.push_back (edit_mode_to_string (Slide));
2724         edit_mode_strings.push_back (edit_mode_to_string (Splice));
2725         edit_mode_strings.push_back (edit_mode_to_string (Lock));
2726
2727         edit_mode_selector.set_name ("EditModeSelector");
2728         Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, longest (edit_mode_strings).c_str(), 2+FUDGE, 10);
2729         set_popdown_strings (edit_mode_selector, edit_mode_strings);
2730         edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2731
2732         mode_box->pack_start(edit_mode_selector);
2733         mode_box->pack_start(mouse_mode_button_box);
2734         
2735         mouse_mode_tearoff = manage (new TearOff (*mode_box));
2736         mouse_mode_tearoff->set_name ("MouseModeBase");
2737
2738         mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
2739                                                   &mouse_mode_tearoff->tearoff_window()));
2740         mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
2741                                                   &mouse_mode_tearoff->tearoff_window(), 1));
2742         mouse_mode_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
2743                                                   &mouse_mode_tearoff->tearoff_window()));
2744         mouse_mode_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
2745                                                    &mouse_mode_tearoff->tearoff_window(), 1));
2746
2747         mouse_move_button.set_name ("MouseModeButton");
2748         mouse_select_button.set_name ("MouseModeButton");
2749         mouse_gain_button.set_name ("MouseModeButton");
2750         mouse_zoom_button.set_name ("MouseModeButton");
2751         mouse_timefx_button.set_name ("MouseModeButton");
2752         mouse_audition_button.set_name ("MouseModeButton");
2753
2754         ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("Select/Move Objects"));
2755         ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("Select/Move Ranges"));
2756         ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("Draw Gain Automation"));
2757         ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("Select Zoom Range"));
2758         ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("Stretch/Shrink Regions"));
2759         ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("Listen to Specific Regions"));
2760
2761         mouse_move_button.unset_flags (CAN_FOCUS);
2762         mouse_select_button.unset_flags (CAN_FOCUS);
2763         mouse_gain_button.unset_flags (CAN_FOCUS);
2764         mouse_zoom_button.unset_flags (CAN_FOCUS);
2765         mouse_timefx_button.unset_flags (CAN_FOCUS);
2766         mouse_audition_button.unset_flags (CAN_FOCUS);
2767
2768         mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2769         mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2770
2771         mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2772         mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2773         mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2774         mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2775         mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2776
2777         // mouse_move_button.set_active (true);
2778         
2779
2780         /* Zoom */
2781         
2782         zoom_box.set_spacing (1);
2783         zoom_box.set_border_width (2);
2784
2785         zoom_in_button.set_name ("EditorTimeButton");
2786         zoom_in_button.set_size_request(-1,16);
2787         zoom_in_button.add (*(manage (new Image (::get_icon("zoom_in")))));
2788         zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
2789         ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom In"));
2790         
2791         zoom_out_button.set_name ("EditorTimeButton");
2792         zoom_out_button.set_size_request(-1,16);
2793         zoom_out_button.add (*(manage (new Image (::get_icon("zoom_out")))));
2794         zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
2795         ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom Out"));
2796
2797         zoom_out_full_button.set_name ("EditorTimeButton");
2798         zoom_out_full_button.set_size_request(-1,16);
2799         zoom_out_full_button.add (*(manage (new Image (::get_icon("zoom_full")))));
2800         zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
2801         ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to Session"));
2802
2803         zoom_focus_selector.set_name ("ZoomFocusSelector");
2804         Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, _("Playhead"), FUDGE, 0);
2805         set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
2806         zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2807         ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus"));
2808
2809         zoom_box.pack_start (zoom_focus_selector, true, true);
2810         zoom_box.pack_start (zoom_out_button, false, false);
2811         zoom_box.pack_start (zoom_in_button, false, false);
2812         zoom_box.pack_start (zoom_out_full_button, false, false);
2813
2814         snap_box.set_spacing (1);
2815         snap_box.set_border_width (2);
2816
2817         snap_type_selector.set_name ("SnapTypeSelector");
2818         Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, _("SMPTE Seconds"), 2+FUDGE, 10);
2819         set_popdown_strings (snap_type_selector, snap_type_strings);
2820         snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2821         ARDOUR_UI::instance()->tooltips().set_tip (snap_type_selector, _("Snap/Grid Units"));
2822
2823         snap_mode_selector.set_name ("SnapModeSelector");
2824         Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, _("Magnetic Snap"), 2+FUDGE, 10);
2825         set_popdown_strings (snap_mode_selector, snap_mode_strings);
2826         snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2827         ARDOUR_UI::instance()->tooltips().set_tip (snap_mode_selector, _("Snap/Grid Mode"));
2828
2829         edit_point_selector.set_name ("SnapModeSelector");
2830         Gtkmm2ext::set_size_request_to_display_given_text (edit_point_selector, _("Playhead"), 2+FUDGE, 10);
2831         set_popdown_strings (edit_point_selector, edit_point_strings);
2832         edit_point_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_point_selection_done));
2833         ARDOUR_UI::instance()->tooltips().set_tip (edit_point_selector, _("Edit point"));
2834
2835         snap_box.pack_start (edit_point_clock, false, false);
2836         snap_box.pack_start (snap_mode_selector, false, false);
2837         snap_box.pack_start (snap_type_selector, false, false);
2838         snap_box.pack_start (edit_point_selector, false, false);
2839
2840         /* Nudge */
2841
2842         HBox *nudge_box = manage (new HBox);
2843         nudge_box->set_spacing(1);
2844         nudge_box->set_border_width (2);
2845
2846         nudge_forward_button.signal_button_release_event().connect (mem_fun(*this, &Editor::nudge_forward_release), false);
2847         nudge_backward_button.signal_button_release_event().connect (mem_fun(*this, &Editor::nudge_backward_release), false);
2848
2849         nudge_box->pack_start (nudge_backward_button, false, false);
2850         nudge_box->pack_start (nudge_forward_button, false, false);
2851         nudge_box->pack_start (nudge_clock, false, false);
2852
2853
2854         /* Pack everything in... */
2855
2856         HBox* hbox = new HBox;
2857         hbox->set_spacing(10);
2858
2859         tools_tearoff = new TearOff (*hbox);
2860         tools_tearoff->set_name ("MouseModeBase");
2861
2862         tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
2863                                              &tools_tearoff->tearoff_window()));
2864         tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
2865                                              &tools_tearoff->tearoff_window(), 0));
2866         tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox), 
2867                                              &tools_tearoff->tearoff_window()));
2868         tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox), 
2869                                               &tools_tearoff->tearoff_window(), 0));
2870
2871         toolbar_hbox.set_spacing (10);
2872         toolbar_hbox.set_border_width (1);
2873
2874         toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2875         toolbar_hbox.pack_start (*tools_tearoff, false, false);
2876
2877         
2878         hbox->pack_start (snap_box, false, false);
2879         // hbox->pack_start (zoom_box, false, false); 
2880         hbox->pack_start (*nudge_box, false, false);
2881
2882         hbox->show_all ();
2883         
2884         toolbar_base.set_name ("ToolBarBase");
2885         toolbar_base.add (toolbar_hbox);
2886
2887         toolbar_frame.set_shadow_type (SHADOW_OUT);
2888         toolbar_frame.set_name ("BaseFrame");
2889         toolbar_frame.add (toolbar_base);
2890 }
2891
2892 int
2893 Editor::convert_drop_to_paths (vector<ustring>& paths, 
2894                                const RefPtr<Gdk::DragContext>& context,
2895                                gint                x,
2896                                gint                y,
2897                                const SelectionData& data,
2898                                guint               info,
2899                                guint               time)                               
2900
2901 {       
2902         if (session == 0) {
2903                 return -1;
2904         }
2905
2906         vector<ustring> uris = data.get_uris();
2907
2908         if (uris.empty()) {
2909
2910                 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
2911                    are actually URI lists. So do it by hand.
2912                 */
2913
2914                 if (data.get_target() != "text/plain") {
2915                         return -1;
2916                 }
2917   
2918                 /* Parse the "uri-list" format that Nautilus provides, 
2919                    where each pathname is delimited by \r\n
2920                 */
2921         
2922                 const char* p = data.get_text().c_str();
2923                 const char* q;
2924
2925                 while (p)
2926                 {
2927                         if (*p != '#')
2928                         {
2929                                 while (g_ascii_isspace (*p))
2930                                         p++;
2931                                 
2932                                 q = p;
2933                                 while (*q && (*q != '\n') && (*q != '\r'))
2934                                         q++;
2935                                 
2936                                 if (q > p)
2937                                 {
2938                                         q--;
2939                                         while (q > p && g_ascii_isspace (*q))
2940                                                 q--;
2941                                         
2942                                         if (q > p)
2943                                         {
2944                                                 uris.push_back (ustring (p, q - p + 1));
2945                                         }
2946                                 }
2947                         }
2948                         p = strchr (p, '\n');
2949                         if (p)
2950                                 p++;
2951                 }
2952
2953                 if (uris.empty()) {
2954                         return -1;
2955                 }
2956         }
2957         
2958         for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
2959
2960                 if ((*i).substr (0,7) == "file://") {
2961
2962                         
2963                         ustring p = *i;
2964                         PBD::url_decode (p);
2965
2966                         // scan forward past three slashes
2967                         
2968                         ustring::size_type slashcnt = 0;
2969                         ustring::size_type n = 0;
2970                         ustring::iterator x = p.begin();
2971
2972                         while (slashcnt < 3 && x != p.end()) {
2973                                 if ((*x) == '/') {
2974                                         slashcnt++;
2975                                 } else if (slashcnt == 3) {
2976                                         break;
2977                                 }
2978                                 ++n;
2979                                 ++x;
2980                         }
2981
2982                         if (slashcnt != 3 || x == p.end()) {
2983                                 error << _("malformed URL passed to drag-n-drop code") << endmsg;
2984                                 continue;
2985                         }
2986
2987                         paths.push_back (p.substr (n - 1));
2988                 }
2989         }
2990
2991         return 0;
2992 }
2993
2994 void
2995 Editor::new_tempo_section ()
2996
2997 {
2998 }
2999
3000 void
3001 Editor::map_transport_state ()
3002 {
3003         ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3004
3005         if (session->transport_stopped()) {
3006                 have_pending_keyboard_selection = false;
3007         }
3008
3009         update_loop_range_view (true);
3010 }
3011
3012 /* UNDO/REDO */
3013
3014 Editor::State::State ()
3015 {
3016         selection = new Selection;
3017 }
3018
3019 Editor::State::~State ()
3020 {
3021         delete selection;
3022 }
3023
3024 UndoAction
3025 Editor::get_memento () const
3026 {
3027         State *state = new State;
3028
3029         store_state (*state);
3030         return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3031 }
3032
3033 void
3034 Editor::store_state (State& state) const
3035 {
3036         *state.selection = *selection;
3037 }
3038
3039 void
3040 Editor::restore_state (State *state)
3041 {
3042         if (*selection == *state->selection) {
3043                 return;
3044         }
3045
3046         *selection = *state->selection;
3047         time_selection_changed ();
3048         region_selection_changed ();   
3049
3050         /* XXX other selection change handlers? */
3051 }
3052
3053 void
3054 Editor::begin_reversible_command (string name)
3055 {
3056         if (session) {
3057                 // before = &get_state();
3058                 session->begin_reversible_command (name);
3059         }
3060 }
3061
3062 void
3063 Editor::commit_reversible_command ()
3064 {
3065         if (session) {
3066                 // session->commit_reversible_command (new MementoCommand<Editor>(*this, before, &get_state()));
3067                 session->commit_reversible_command ();
3068         }
3069 }
3070
3071 void
3072 Editor::set_edit_group_solo (Route& route, bool yn)
3073 {
3074         RouteGroup *edit_group;
3075
3076         if ((edit_group = route.edit_group()) != 0) {
3077                 edit_group->apply (&Route::set_solo, yn, this);
3078         } else {
3079                 route.set_solo (yn, this);
3080         }
3081 }
3082
3083 void
3084 Editor::set_edit_group_mute (Route& route, bool yn)
3085 {
3086         RouteGroup *edit_group = 0;
3087
3088         if ((edit_group == route.edit_group()) != 0) {
3089                 edit_group->apply (&Route::set_mute, yn, this);
3090         } else {
3091                 route.set_mute (yn, this);
3092         }
3093 }
3094                 
3095 void
3096 Editor::history_changed ()
3097 {
3098         string label;
3099
3100         if (undo_action && session) {
3101                 if (session->undo_depth() == 0) {
3102                         label = _("Undo");
3103                 } else {
3104                         label = string_compose(_("Undo (%1)"), session->next_undo());
3105                 }
3106                 undo_action->property_label() = label;
3107         }
3108
3109         if (redo_action && session) {
3110                 if (session->redo_depth() == 0) {
3111                         label = _("Redo");
3112                 } else {
3113                         label = string_compose(_("Redo (%1)"), session->next_redo());
3114                 }
3115                 redo_action->property_label() = label;
3116         }
3117 }
3118
3119 void
3120 Editor::duplicate_dialog (bool with_dialog)
3121 {
3122         float times = 1.0f;
3123
3124         if (mouse_mode == MouseRange) {
3125                 if (selection->time.length() == 0) {
3126                         return;
3127                 }
3128         }
3129
3130         RegionSelection rs;
3131         get_regions_for_action (rs);
3132         
3133         if (mouse_mode != MouseRange) {
3134
3135                 if (rs.empty()) {
3136                         return;
3137                 }
3138         }
3139
3140         if (with_dialog) {
3141
3142                 ArdourDialog win ("Duplication Dialog");
3143                 Label  label (_("Number of Duplications:"));
3144                 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3145                 SpinButton spinner (adjustment, 0.0, 1);
3146                 HBox hbox;
3147                 
3148                 win.get_vbox()->set_spacing (12);
3149                 win.get_vbox()->pack_start (hbox);
3150                 hbox.set_border_width (6);
3151                 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3152                 
3153                 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3154                    place, visually. so do this by hand.
3155                 */
3156                 
3157                 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3158                 spinner.signal_activate().connect (sigc::bind (mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3159                 spinner.grab_focus();
3160
3161                 hbox.show ();
3162                 label.show ();
3163                 spinner.show ();
3164                 
3165                 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3166                 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3167                 win.set_default_response (RESPONSE_ACCEPT);
3168                 
3169                 win.set_position (WIN_POS_MOUSE);
3170                 
3171                 spinner.grab_focus ();
3172                 
3173                 switch (win.run ()) {
3174                 case RESPONSE_ACCEPT:
3175                         break;
3176                 default:
3177                         return;
3178                 }
3179                 
3180                 times = adjustment.get_value();
3181         }
3182
3183         if (mouse_mode == MouseRange) {
3184                 duplicate_selection (times);
3185         } else {
3186                 duplicate_some_regions (rs, times);
3187         }
3188 }
3189
3190 void
3191 Editor::show_verbose_canvas_cursor ()
3192 {
3193         verbose_canvas_cursor->raise_to_top();
3194         verbose_canvas_cursor->show();
3195         verbose_cursor_visible = true;
3196 }
3197
3198 void
3199 Editor::hide_verbose_canvas_cursor ()
3200 {
3201         verbose_canvas_cursor->hide();
3202         verbose_cursor_visible = false;
3203 }
3204
3205 double
3206 Editor::clamp_verbose_cursor_x (double x)
3207 {
3208         return min (horizontal_adjustment.get_value() + canvas_width - 75.0, x);
3209 }
3210
3211 double
3212 Editor::clamp_verbose_cursor_y (double y)
3213 {
3214         return min (vertical_adjustment.get_value() + canvas_height - 50.0, y);
3215 }
3216
3217 void
3218 Editor::set_verbose_canvas_cursor (const string & txt, double x, double y)
3219 {
3220         verbose_canvas_cursor->property_text() = txt.c_str();
3221         /* don't get too close to the edge */
3222         verbose_canvas_cursor->property_x() = clamp_verbose_cursor_x (x);
3223         verbose_canvas_cursor->property_y() = clamp_verbose_cursor_x (y);
3224 }
3225
3226 void
3227 Editor::set_verbose_canvas_cursor_text (const string & txt)
3228 {
3229         verbose_canvas_cursor->property_text() = txt.c_str();
3230 }
3231
3232 void
3233 Editor::set_edit_mode (EditMode m)
3234 {
3235         Config->set_edit_mode (m);
3236 }
3237
3238 void
3239 Editor::cycle_edit_mode ()
3240 {
3241         switch (Config->get_edit_mode()) {
3242         case Slide:
3243                 Config->set_edit_mode (Splice);
3244                 break;
3245         case Splice:
3246                 Config->set_edit_mode (Lock);
3247                 break;
3248         case Lock:
3249                 Config->set_edit_mode (Slide);
3250                 break;
3251         }
3252 }
3253
3254 void
3255 Editor::edit_mode_selection_done ()
3256 {
3257         if (session == 0) {
3258                 return;
3259         }
3260
3261         string choice = edit_mode_selector.get_active_text();
3262         EditMode mode = Slide;
3263
3264         if (choice == _("Splice Edit")) {
3265                 mode = Splice;
3266         } else if (choice == _("Slide Edit")) {
3267                 mode = Slide;
3268         } else if (choice == _("Lock Edit")) {
3269                 mode = Lock;
3270         }
3271
3272         Config->set_edit_mode (mode);
3273 }       
3274
3275 void
3276 Editor::snap_type_selection_done ()
3277 {
3278         string choice = snap_type_selector.get_active_text();
3279         SnapType snaptype = SnapToBeat;
3280
3281         if (choice == _("Beats/3")) {
3282                 snaptype = SnapToAThirdBeat;
3283         } else if (choice == _("Beats/4")) {
3284                 snaptype = SnapToAQuarterBeat;
3285         } else if (choice == _("Beats/8")) {
3286                 snaptype = SnapToAEighthBeat;
3287         } else if (choice == _("Beats/16")) {
3288                 snaptype = SnapToASixteenthBeat;
3289         } else if (choice == _("Beats/32")) {
3290                 snaptype = SnapToAThirtysecondBeat;
3291         } else if (choice == _("Beats")) {
3292                 snaptype = SnapToBeat;
3293         } else if (choice == _("Bars")) {
3294                 snaptype = SnapToBar;
3295         } else if (choice == _("Marks")) {
3296                 snaptype = SnapToMark;
3297         } else if (choice == _("Region starts")) {
3298                 snaptype = SnapToRegionStart;
3299         } else if (choice == _("Region ends")) {
3300                 snaptype = SnapToRegionEnd;
3301         } else if (choice == _("Region bounds")) {
3302                 snaptype = SnapToRegionBoundary;
3303         } else if (choice == _("Region syncs")) {
3304                 snaptype = SnapToRegionSync;
3305         } else if (choice == _("CD Frames")) {
3306                 snaptype = SnapToCDFrame;
3307         } else if (choice == _("SMPTE Frames")) {
3308                 snaptype = SnapToSMPTEFrame;
3309         } else if (choice == _("SMPTE Seconds")) {
3310                 snaptype = SnapToSMPTESeconds;
3311         } else if (choice == _("SMPTE Minutes")) {
3312                 snaptype = SnapToSMPTEMinutes;
3313         } else if (choice == _("Seconds")) {
3314                 snaptype = SnapToSeconds;
3315         } else if (choice == _("Minutes")) {
3316                 snaptype = SnapToMinutes;
3317         }
3318
3319         RefPtr<RadioAction> ract = snap_type_action (snaptype);
3320         if (ract) {
3321                 ract->set_active ();
3322         }
3323 }       
3324
3325 void
3326 Editor::snap_mode_selection_done ()
3327 {
3328         string choice = snap_mode_selector.get_active_text();
3329         SnapMode mode = SnapNormal;
3330
3331         if (choice == _("No Grid")) {
3332                 mode = SnapOff;
3333         } else if (choice == _("Grid")) {
3334                 mode = SnapNormal;
3335         } else if (choice == _("Magnetic")) {
3336                 mode = SnapMagnetic;
3337         }
3338
3339         RefPtr<RadioAction> ract = snap_mode_action (mode);
3340
3341         if (ract) {
3342                 ract->set_active (true);
3343         }
3344 }
3345
3346 void
3347 Editor::cycle_edit_point (bool with_marker)
3348 {
3349         switch (_edit_point) {
3350         case EditAtMouse:
3351                 set_edit_point_preference (EditAtPlayhead);
3352                 break;
3353         case EditAtPlayhead:
3354                 if (with_marker) {
3355                         set_edit_point_preference (EditAtSelectedMarker);
3356                 } else {
3357                         set_edit_point_preference (EditAtMouse);
3358                 }
3359                 break;
3360         case EditAtSelectedMarker:
3361                 set_edit_point_preference (EditAtMouse);
3362                 break;
3363         }
3364 }
3365
3366 void
3367 Editor::edit_point_selection_done ()
3368 {
3369         string choice = edit_point_selector.get_active_text();
3370         EditPoint ep = EditAtSelectedMarker;
3371
3372         if (choice == _("Marker")) {
3373                 set_edit_point_preference (EditAtSelectedMarker);
3374         } else if (choice == _("Playhead")) {
3375                 set_edit_point_preference (EditAtPlayhead);
3376         } else {
3377                 set_edit_point_preference (EditAtMouse);
3378         }
3379
3380         RefPtr<RadioAction> ract = edit_point_action (ep);
3381
3382         if (ract) {
3383                 ract->set_active (true);
3384         }
3385 }
3386
3387 void
3388 Editor::zoom_focus_selection_done ()
3389 {
3390         string choice = zoom_focus_selector.get_active_text();
3391         ZoomFocus focus_type = ZoomFocusLeft;
3392
3393         if (choice == _("Left")) {
3394                 focus_type = ZoomFocusLeft;
3395         } else if (choice == _("Right")) {
3396                 focus_type = ZoomFocusRight;
3397         } else if (choice == _("Center")) {
3398                 focus_type = ZoomFocusCenter;
3399         } else if (choice == _("Playhead")) {
3400                 focus_type = ZoomFocusPlayhead;
3401         } else if (choice == _("Mouse")) {
3402                 focus_type = ZoomFocusMouse;
3403         } else if (choice == _("Active Mark")) {
3404                 focus_type = ZoomFocusEdit;
3405         } 
3406         
3407         RefPtr<RadioAction> ract = zoom_focus_action (focus_type);
3408
3409         if (ract) {
3410                 ract->set_active ();
3411         }
3412 }       
3413
3414 gint
3415 Editor::edit_controls_button_release (GdkEventButton* ev)
3416 {
3417         if (Keyboard::is_context_menu_event (ev)) {
3418                 ARDOUR_UI::instance()->add_route (this);
3419         }
3420         return TRUE;
3421 }
3422
3423 gint
3424 Editor::mouse_select_button_release (GdkEventButton* ev)
3425 {
3426         /* this handles just right-clicks */
3427
3428         if (ev->button != 3) {
3429                 return false;
3430         }
3431
3432         return true;
3433 }
3434
3435 Editor::TrackViewList *
3436 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3437 {
3438         TrackViewList *v;
3439         TrackViewList::iterator i;
3440
3441         v = new TrackViewList;
3442
3443         if (track == 0 && group == 0) {
3444
3445                 /* all views */
3446
3447                 for (i = track_views.begin(); i != track_views.end (); ++i) {
3448                         v->push_back (*i);
3449                 }
3450
3451         } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3452                 
3453                 /* just the view for this track
3454                  */
3455
3456                 v->push_back (track);
3457
3458         } else {
3459                 
3460                 /* views for all tracks in the edit group */
3461                 
3462                 for (i  = track_views.begin(); i != track_views.end (); ++i) {
3463
3464                         if (group == 0 || (*i)->edit_group() == group) {
3465                                 v->push_back (*i);
3466                         }
3467                 }
3468         }
3469         
3470         return v;
3471 }
3472
3473 void
3474 Editor::set_zoom_focus (ZoomFocus f)
3475 {
3476         string str = zoom_focus_strings[(int)f];
3477
3478         if (str != zoom_focus_selector.get_active_text()) {
3479                 zoom_focus_selector.set_active_text (str);
3480         }
3481         
3482         if (zoom_focus != f) {
3483                 zoom_focus = f;
3484
3485                 ZoomFocusChanged (); /* EMIT_SIGNAL */
3486
3487                 instant_save ();
3488         }
3489 }
3490
3491 void
3492 Editor::ensure_float (Window& win)
3493 {
3494         win.set_transient_for (*this);
3495 }
3496
3497 void 
3498 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3499 {
3500         /* recover or initialize pane positions. do this here rather than earlier because
3501            we don't want the positions to change the child allocations, which they seem to do.
3502          */
3503
3504         int pos;
3505         XMLProperty* prop;
3506         char buf[32];
3507         XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3508         int width, height;
3509         static int32_t done;
3510         XMLNode* geometry;
3511
3512         if ((geometry = find_named_node (*node, "geometry")) == 0) {
3513                 width = default_width;
3514                 height = default_height;
3515         } else {
3516                 width = atoi(geometry->property("x_size")->value());
3517                 height = atoi(geometry->property("y_size")->value());
3518         }
3519
3520         if (which == static_cast<Paned*> (&edit_pane)) {
3521
3522                 if (done) {
3523                         return;
3524                 }
3525
3526                 if (!geometry || (prop = geometry->property ("edit_pane_pos")) == 0) {
3527                         /* initial allocation is 90% to canvas, 10% to notebook */
3528                         pos = (int) floor (alloc.get_width() * 0.90f);
3529                         snprintf (buf, sizeof(buf), "%d", pos);
3530                 } else {
3531                         pos = atoi (prop->value());
3532                 }
3533                 
3534                 if ((done = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
3535                         edit_pane.set_position (pos);
3536                         pre_maximal_pane_position = pos;
3537                 }
3538         }
3539 }
3540
3541 void
3542 Editor::detach_tearoff (Box* b, Window* w)
3543 {
3544         if (tools_tearoff->torn_off() && 
3545             mouse_mode_tearoff->torn_off()) {
3546                 top_hbox.remove (toolbar_frame);
3547         }
3548 }
3549
3550 void
3551 Editor::reattach_tearoff (Box* b, Window* w, int32_t n)
3552 {
3553         if (toolbar_frame.get_parent() == 0) {
3554                 top_hbox.pack_end (toolbar_frame);
3555         }
3556 }
3557
3558 void
3559 Editor::set_show_measures (bool yn)
3560 {
3561         if (_show_measures != yn) {
3562                 hide_measures ();
3563
3564                 if ((_show_measures = yn) == true) {
3565                         draw_measures ();
3566                 }
3567                 instant_save ();
3568         }
3569 }
3570
3571 void
3572 Editor::toggle_follow_playhead ()
3573 {
3574         RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3575         if (act) {
3576                 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3577                 set_follow_playhead (tact->get_active());
3578         }
3579 }
3580
3581 void
3582 Editor::set_follow_playhead (bool yn)
3583 {
3584         if (_follow_playhead != yn) {
3585                 if ((_follow_playhead = yn) == true) {
3586                         /* catch up */
3587                         update_current_screen ();
3588                 }
3589                 instant_save ();
3590         }
3591 }
3592
3593 void
3594 Editor::toggle_xfade_active (boost::weak_ptr<Crossfade> wxfade)
3595 {
3596         boost::shared_ptr<Crossfade> xfade (wxfade.lock());
3597         if (xfade) {
3598                 xfade->set_active (!xfade->active());
3599         }
3600 }
3601
3602 void
3603 Editor::toggle_xfade_length (boost::weak_ptr<Crossfade> wxfade)
3604 {
3605         boost::shared_ptr<Crossfade> xfade (wxfade.lock());
3606         if (xfade) {
3607                 xfade->set_follow_overlap (!xfade->following_overlap());
3608         }
3609 }
3610
3611 void
3612 Editor::edit_xfade (boost::weak_ptr<Crossfade> wxfade)
3613 {
3614         boost::shared_ptr<Crossfade> xfade (wxfade.lock());
3615
3616         if (!xfade) {
3617                 return;
3618         }
3619
3620         CrossfadeEditor cew (*session, xfade, xfade->fade_in().get_min_y(), 1.0);
3621                 
3622         ensure_float (cew);
3623         
3624         switch (cew.run ()) {
3625         case RESPONSE_ACCEPT:
3626                 break;
3627         default:
3628                 return;
3629         }
3630         
3631         cew.apply ();
3632         xfade->StateChanged (Change (~0));
3633 }
3634
3635 PlaylistSelector&
3636 Editor::playlist_selector () const
3637 {
3638         return *_playlist_selector;
3639 }
3640
3641 nframes_t
3642 Editor::get_nudge_distance (nframes_t pos, nframes_t& next)
3643 {
3644         nframes_t ret;
3645
3646         ret = nudge_clock.current_duration (pos);
3647         next = ret + 1; /* XXXX fix me */
3648
3649         return ret;
3650 }
3651
3652 void
3653 Editor::end_location_changed (Location* location)
3654 {
3655         ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
3656         reset_scrolling_region ();
3657 }
3658
3659 int
3660 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3661 {
3662         ArdourDialog dialog ("playlist deletion dialog");
3663         Label  label (string_compose (_("Playlist %1 is currently unused.\n"
3664                                         "If left alone, no audio files used by it will be cleaned.\n"
3665                                         "If deleted, audio files used by it alone by will cleaned."),
3666                                       pl->name()));
3667         
3668         dialog.set_position (WIN_POS_CENTER);
3669         dialog.get_vbox()->pack_start (label);
3670
3671         label.show ();
3672
3673         dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
3674         dialog.add_button (_("Keep playlist"), RESPONSE_REJECT);
3675         dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3676
3677         switch (dialog.run ()) {
3678         case RESPONSE_ACCEPT:
3679                 /* delete the playlist */
3680                 return 0;
3681                 break;
3682
3683         case RESPONSE_REJECT:
3684                 /* keep the playlist */
3685                 return 1;
3686                 break;
3687
3688         default:
3689                 break;
3690         }
3691
3692         return -1;
3693 }
3694
3695 bool
3696 Editor::audio_region_selection_covers (nframes_t where)
3697 {
3698         for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3699                 if ((*a)->region()->covers (where)) {
3700                         return true;
3701                 }
3702         }
3703
3704         return false;
3705 }
3706
3707 void
3708 Editor::prepare_for_cleanup ()
3709 {
3710         cut_buffer->clear_regions ();
3711         cut_buffer->clear_playlists ();
3712
3713         selection->clear_regions ();
3714         selection->clear_playlists ();
3715 }
3716
3717 Location*
3718 Editor::transport_loop_location()
3719 {
3720         if (session) {
3721                 return session->locations()->auto_loop_location();
3722         } else {
3723                 return 0;
3724         }
3725 }
3726
3727 Location*
3728 Editor::transport_punch_location()
3729 {
3730         if (session) {
3731                 return session->locations()->auto_punch_location();
3732         } else {
3733                 return 0;
3734         }
3735 }
3736
3737 bool
3738 Editor::control_layout_scroll (GdkEventScroll* ev)
3739 {
3740         switch (ev->direction) {
3741         case GDK_SCROLL_UP:
3742                 scroll_tracks_up_line ();
3743                 return true;
3744                 break;
3745
3746         case GDK_SCROLL_DOWN:
3747                 scroll_tracks_down_line ();
3748                 return true;
3749                 
3750         default:
3751                 /* no left/right handling yet */
3752                 break;
3753         }
3754
3755         return false;
3756 }
3757
3758
3759 /** A new snapshot has been selected.
3760  */
3761 void
3762 Editor::snapshot_display_selection_changed ()
3763 {
3764         if (snapshot_display.get_selection()->count_selected_rows() > 0) {
3765
3766                 TreeModel::iterator i = snapshot_display.get_selection()->get_selected();
3767                 
3768                 Glib::ustring snap_name = (*i)[snapshot_display_columns.real_name];
3769
3770                 if (snap_name.length() == 0) {
3771                         return;
3772                 }
3773                 
3774                 if (session->snap_name() == snap_name) {
3775                         return;
3776                 }
3777                 
3778                 ARDOUR_UI::instance()->load_session(session->path(), string (snap_name));
3779         }
3780 }
3781
3782 bool
3783 Editor::snapshot_display_button_press (GdkEventButton* ev)
3784 {
3785         if (ev->button == 3) {
3786                 /* Right-click on the snapshot list. Work out which snapshot it
3787                    was over. */
3788                 Gtk::TreeModel::Path path;
3789                 Gtk::TreeViewColumn* col;
3790                 int cx;
3791                 int cy;
3792                 snapshot_display.get_path_at_pos ((int) ev->x, (int) ev->y, path, col, cx, cy);
3793                 Gtk::TreeModel::iterator iter = snapshot_display_model->get_iter (path);
3794                 if (iter) {
3795                         Gtk::TreeModel::Row row = *iter;
3796                         popup_snapshot_context_menu (ev->button, ev->time, row[snapshot_display_columns.real_name]);
3797                 }
3798                 return true;
3799         }
3800
3801         return false;
3802 }
3803
3804
3805 /** Pop up the snapshot display context menu.
3806  * @param button Button used to open the menu.
3807  * @param time Menu open time.
3808  * @snapshot_name Name of the snapshot that the menu click was over.
3809  */
3810
3811 void
3812 Editor::popup_snapshot_context_menu (int button, int32_t time, Glib::ustring snapshot_name)
3813 {
3814         using namespace Menu_Helpers;
3815
3816         MenuList& items (snapshot_context_menu.items());
3817         items.clear ();
3818
3819         const bool modification_allowed = (session->snap_name() != snapshot_name && session->name() != snapshot_name);
3820
3821         items.push_back (MenuElem (_("Remove"), bind (mem_fun (*this, &Editor::remove_snapshot), snapshot_name)));
3822         if (!modification_allowed) {
3823                 items.back().set_sensitive (false);
3824         }
3825
3826         items.push_back (MenuElem (_("Rename"), bind (mem_fun (*this, &Editor::rename_snapshot), snapshot_name)));
3827         if (!modification_allowed) {
3828                 items.back().set_sensitive (false);
3829         }
3830
3831         snapshot_context_menu.popup (button, time);
3832 }
3833
3834 void
3835 Editor::rename_snapshot (Glib::ustring old_name)
3836 {
3837         ArdourPrompter prompter(true);
3838
3839         string new_name;
3840
3841         prompter.set_name ("Prompter");
3842         prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
3843         prompter.set_prompt (_("New name of snapshot"));
3844         prompter.set_initial_text (old_name);
3845         
3846         if (prompter.run() == RESPONSE_ACCEPT) {
3847                 prompter.get_result (new_name);
3848                 if (new_name.length()) {
3849                         session->rename_state (old_name, new_name);
3850                         redisplay_snapshots ();
3851                 }
3852         }
3853 }
3854
3855
3856 void
3857 Editor::remove_snapshot (Glib::ustring name)
3858 {
3859         vector<string> choices;
3860
3861         std::string prompt  = string_compose (_("Do you really want to remove snapshot \"%1\" ?\n(cannot be undone)"), name);
3862
3863         choices.push_back (_("No, do nothing."));
3864         choices.push_back (_("Yes, remove it."));
3865
3866         Gtkmm2ext::Choice prompter (prompt, choices);
3867
3868         if (prompter.run () == 1) {
3869                 session->remove_state (name);
3870                 redisplay_snapshots ();
3871         }
3872 }
3873
3874 void
3875 Editor::redisplay_snapshots ()
3876 {
3877         if (session == 0) {
3878                 return;
3879         }
3880
3881         vector<string*>* states;
3882
3883         if ((states = session->possible_states()) == 0) {
3884                 return;
3885         }
3886
3887         snapshot_display_model->clear ();
3888
3889         for (vector<string*>::iterator i = states->begin(); i != states->end(); ++i) {
3890                 string statename = *(*i);
3891                 TreeModel::Row row = *(snapshot_display_model->append());
3892                 
3893                 /* this lingers on in case we ever want to change the visible
3894                    name of the snapshot.
3895                 */
3896                 
3897                 string display_name;
3898                 display_name = statename;
3899
3900                 if (statename == session->snap_name()) {
3901                         snapshot_display.get_selection()->select(row);
3902                 } 
3903                 
3904                 row[snapshot_display_columns.visible_name] = display_name;
3905                 row[snapshot_display_columns.real_name] = statename;
3906         }
3907
3908         delete states;
3909 }
3910
3911 void
3912 Editor::session_state_saved (string snap_name)
3913 {
3914         ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::session_state_saved), snap_name));
3915         redisplay_snapshots ();
3916 }
3917
3918 void
3919 Editor::maximise_editing_space ()
3920 {
3921         initial_ruler_update_required = true;
3922
3923         mouse_mode_tearoff->set_visible (false);
3924         tools_tearoff->set_visible (false);
3925
3926         pre_maximal_pane_position = edit_pane.get_position();
3927         pre_maximal_editor_width = this->get_width();
3928
3929         if(post_maximal_pane_position == 0) {
3930                 post_maximal_pane_position = edit_pane.get_width();
3931         }
3932
3933
3934         fullscreen();
3935         if(post_maximal_editor_width) {
3936                 edit_pane.set_position (post_maximal_pane_position - 
3937                         abs(post_maximal_editor_width - pre_maximal_editor_width));
3938         } else {
3939                 edit_pane.set_position (post_maximal_pane_position);
3940         }
3941 }
3942
3943 void
3944 Editor::restore_editing_space ()
3945 {
3946         initial_ruler_update_required = true;
3947
3948         // user changed width of pane during fullscreen
3949         if(post_maximal_pane_position != edit_pane.get_position()) {
3950                 post_maximal_pane_position = edit_pane.get_position();
3951         }
3952
3953         unfullscreen();
3954
3955         mouse_mode_tearoff->set_visible (true);
3956         tools_tearoff->set_visible (true);
3957         post_maximal_editor_width = this->get_width();
3958
3959
3960         edit_pane.set_position (
3961                 pre_maximal_pane_position + abs(this->get_width() - pre_maximal_editor_width)
3962         );
3963 }
3964
3965 /**
3966  *  Make new playlists for a given track and also any others that belong
3967  *  to the same active edit group.
3968  *  @param v Track.
3969  */
3970
3971 void 
3972 Editor::new_playlists (TimeAxisView* v)
3973 {
3974         begin_reversible_command (_("new playlists"));
3975         mapover_audio_tracks (mem_fun (*this, &Editor::mapped_use_new_playlist), v);
3976         commit_reversible_command ();
3977 }
3978
3979
3980 /**
3981  *  Use a copy of the current playlist for a given track and also any others that belong
3982  *  to the same active edit group.
3983  *  @param v Track.
3984  */
3985
3986 void
3987 Editor::copy_playlists (TimeAxisView* v)
3988 {
3989         begin_reversible_command (_("copy playlists"));
3990         mapover_audio_tracks (mem_fun (*this, &Editor::mapped_use_copy_playlist), v);
3991         commit_reversible_command ();
3992 }
3993
3994
3995 /**
3996  *  Clear the current playlist for a given track and also any others that belong
3997  *  to the same active edit group.
3998  *  @param v Track.
3999  */
4000
4001 void 
4002 Editor::clear_playlists (TimeAxisView* v)
4003 {
4004         begin_reversible_command (_("clear playlists"));
4005         mapover_audio_tracks (mem_fun (*this, &Editor::mapped_clear_playlist), v);
4006         commit_reversible_command ();
4007 }
4008
4009 void 
4010 Editor::mapped_use_new_playlist (AudioTimeAxisView& atv, uint32_t sz)
4011 {
4012         atv.use_new_playlist (sz > 1 ? false : true);
4013 }
4014
4015 void
4016 Editor::mapped_use_copy_playlist (AudioTimeAxisView& atv, uint32_t sz)
4017 {
4018         atv.use_copy_playlist (sz > 1 ? false : true);
4019 }
4020
4021 void 
4022 Editor::mapped_clear_playlist (AudioTimeAxisView& atv, uint32_t sz)
4023 {
4024         atv.clear_playlist ();
4025 }
4026
4027 bool
4028 Editor::on_key_press_event (GdkEventKey* ev)
4029 {
4030         return key_press_focus_accelerator_handler (*this, ev);
4031 }
4032
4033 bool
4034 Editor::on_key_release_event (GdkEventKey* ev)
4035 {
4036         return Gtk::Window::on_key_release_event (ev);
4037         // return key_press_focus_accelerator_handler (*this, ev);
4038 }
4039
4040 void
4041 Editor::reset_x_origin (nframes_t frame)
4042 {
4043         queue_visual_change (frame);
4044 }
4045
4046 void
4047 Editor::reset_zoom (double fpu)
4048 {
4049         queue_visual_change (fpu);
4050 }
4051
4052 void
4053 Editor::reposition_and_zoom (nframes_t frame, double fpu)
4054 {
4055         reset_x_origin (frame);
4056         reset_zoom (fpu);
4057 }
4058
4059 void
4060 Editor::swap_visual_state ()
4061 {
4062         if (last_visual_state.frames_per_unit == 0) {
4063                 // never set
4064                 return;
4065         }
4066
4067         /* note: the correct functionality here is very dependent on the ordering of 
4068            setting zoom focus, horizontal position and finally zoom. this is because
4069            it is set_frames_per_unit() that overwrites last_visual_state.
4070         */
4071
4072         set_zoom_focus (last_visual_state.zoom_focus);
4073         reposition_and_zoom (last_visual_state.leftmost_frame, last_visual_state.frames_per_unit);
4074         zoomed_to_region = false;
4075 }
4076
4077 void
4078 Editor::set_frames_per_unit (double fpu)
4079 {
4080         /* this is the core function that controls the zoom level of the canvas. it is called
4081            whenever one or more calls are made to reset_zoom(). it executes in an idle handler.
4082         */
4083
4084         if (fpu == frames_per_unit) {
4085                 return;
4086         }
4087
4088         if (fpu < 2.0) {
4089                 fpu = 2.0;
4090         }
4091
4092         
4093         /* don't allow zooms that fit more than the maximum number
4094            of frames into an 800 pixel wide space.
4095         */
4096
4097         if (max_frames / fpu < 800.0) {
4098                 return;
4099         }
4100
4101         if (fpu == frames_per_unit) {
4102                 return;
4103         }
4104         
4105         last_visual_state.frames_per_unit = frames_per_unit;
4106         last_visual_state.leftmost_frame = leftmost_frame;
4107         last_visual_state.zoom_focus = zoom_focus;
4108
4109         frames_per_unit = fpu;
4110         post_zoom ();
4111 }
4112
4113 void
4114 Editor::post_zoom ()
4115 {
4116         // convert fpu to frame count
4117
4118         nframes_t frames = (nframes_t) floor (frames_per_unit * canvas_width);
4119
4120         if (frames_per_unit != zoom_range_clock.current_duration()) {
4121                 zoom_range_clock.set (frames);
4122         }
4123
4124         if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
4125                 if (!selection->tracks.empty()) {
4126                         for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4127                                 (*i)->reshow_selection (selection->time);
4128                         }
4129                 } else {
4130                         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4131                                 (*i)->reshow_selection (selection->time);
4132                         }
4133                 }
4134         }
4135
4136         ZoomChanged (); /* EMIT_SIGNAL */
4137
4138         reset_hscrollbar_stepping ();
4139         reset_scrolling_region ();
4140
4141         if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
4142
4143         instant_save ();
4144 }
4145
4146 void
4147 Editor::queue_visual_change (nframes_t where)
4148 {
4149         pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::TimeOrigin);
4150         pending_visual_change.time_origin = where;
4151         
4152         if (pending_visual_change.idle_handler_id < 0) {
4153                 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4154         }
4155 }
4156
4157 void
4158 Editor::queue_visual_change (double fpu)
4159 {
4160         pending_visual_change.pending = VisualChange::Type (pending_visual_change.pending | VisualChange::ZoomLevel);
4161         pending_visual_change.frames_per_unit = fpu;
4162
4163         if (pending_visual_change.idle_handler_id < 0) {
4164                 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE, _idle_visual_changer, this, 0);
4165         }
4166 }
4167
4168 int
4169 Editor::_idle_visual_changer (void* arg)
4170 {
4171         return static_cast<Editor*>(arg)->idle_visual_changer ();
4172 }
4173
4174 int
4175 Editor::idle_visual_changer ()
4176 {
4177         VisualChange::Type p = pending_visual_change.pending;
4178
4179         pending_visual_change.pending = (VisualChange::Type) 0;
4180         pending_visual_change.idle_handler_id = -1;
4181
4182         if (p & VisualChange::ZoomLevel) {
4183                 set_frames_per_unit (pending_visual_change.frames_per_unit);
4184         }
4185
4186         if (p & VisualChange::TimeOrigin) {
4187                 
4188                 nframes_t time_origin = (nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
4189
4190                 if (time_origin != pending_visual_change.time_origin) {
4191                         horizontal_adjustment.set_value (pending_visual_change.time_origin/frames_per_unit);
4192                 } else {
4193                         update_fixed_rulers();
4194                         redisplay_tempo (true);
4195                 }
4196         }
4197
4198         return 0; /* this is always a one-shot call */
4199 }
4200
4201 struct EditorOrderTimeAxisSorter {
4202     bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4203             return a->order < b->order;
4204     }
4205 };
4206         
4207 void
4208 Editor::sort_track_selection (TrackSelection* sel)
4209 {
4210         EditorOrderTimeAxisSorter cmp;
4211
4212         if (sel) {
4213                 sel->sort (cmp);
4214         } else {
4215                 selection->tracks.sort (cmp);
4216         }
4217 }
4218
4219 nframes64_t
4220 Editor::get_preferred_edit_position (bool ignore_playhead)
4221 {
4222         bool ignored;
4223         nframes64_t where = 0;
4224         EditPoint ep = _edit_point;
4225
4226         if (entered_marker) {
4227                 return entered_marker->position();
4228         }
4229
4230         if (ignore_playhead && ep == EditAtPlayhead) {
4231                 ep = EditAtSelectedMarker;
4232         }
4233
4234         switch (ep) {
4235         case EditAtPlayhead:
4236                 where = session->audible_frame();
4237                 break;
4238                 
4239         case EditAtSelectedMarker:
4240                 if (!selection->markers.empty()) {
4241                         bool is_start;
4242                         Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4243                         if (loc) {
4244                                 if (is_start) {
4245                                         where =  loc->start();
4246                                 } else {
4247                                         where = loc->end();
4248                                 }
4249                                 break;
4250                         }
4251                 } 
4252                 /* fallthru */
4253                 
4254         default:
4255         case EditAtMouse:
4256                 if (!mouse_frame (where, ignored)) {
4257                         /* XXX not right but what can we do ? */
4258                         return 0;
4259                 }
4260                 snap_to (where);
4261                 break;
4262         }
4263
4264         return where;
4265 }
4266
4267 void
4268 Editor::set_loop_range (nframes_t start, nframes_t end, string cmd)
4269 {
4270         if (!session) return;
4271
4272         begin_reversible_command (cmd);
4273         
4274         Location* tll;
4275
4276         if ((tll = transport_loop_location()) == 0) {
4277                 Location* loc = new Location (start, end, _("Loop"),  Location::IsAutoLoop);
4278                 XMLNode &before = session->locations()->get_state();
4279                 session->locations()->add (loc, true);
4280                 session->set_auto_loop_location (loc);
4281                 XMLNode &after = session->locations()->get_state();
4282                 session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
4283         }
4284         else {
4285                 XMLNode &before = tll->get_state();
4286                 tll->set_hidden (false, this);
4287                 tll->set (start, end);
4288                 XMLNode &after = tll->get_state();
4289                 session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4290         }
4291         
4292         commit_reversible_command ();
4293 }
4294
4295 void
4296 Editor::set_punch_range (nframes_t start, nframes_t end, string cmd)
4297 {
4298         if (!session) return;
4299
4300         begin_reversible_command (cmd);
4301         
4302         Location* tpl;
4303
4304         if ((tpl = transport_punch_location()) == 0) {
4305                 Location* loc = new Location (start, end, _("Loop"),  Location::IsAutoPunch);
4306                 XMLNode &before = session->locations()->get_state();
4307                 session->locations()->add (loc, true);
4308                 session->set_auto_loop_location (loc);
4309                 XMLNode &after = session->locations()->get_state();
4310                 session->add_command (new MementoCommand<Locations>(*(session->locations()), &before, &after));
4311         }
4312         else {
4313                 XMLNode &before = tpl->get_state();
4314                 tpl->set_hidden (false, this);
4315                 tpl->set (start, end);
4316                 XMLNode &after = tpl->get_state();
4317                 session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4318         }
4319         
4320         commit_reversible_command ();
4321 }
4322
4323 void
4324 Editor::get_regions_at (RegionSelection& rs, nframes64_t where, const TrackSelection& ts) const
4325 {
4326         const TrackSelection* tracks;
4327
4328         if (ts.empty()) {
4329                 tracks = &track_views;
4330         } else {
4331                 tracks = &ts;
4332         }
4333
4334         for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4335         
4336                 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
4337
4338                 if (atv) {
4339                         boost::shared_ptr<Diskstream> ds;
4340                         boost::shared_ptr<Playlist> pl;
4341                         
4342                         if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
4343
4344                                 Playlist::RegionList* regions = pl->regions_at ((nframes_t) floor ( (double)where * ds->speed()));
4345
4346                                 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4347
4348                                         RegionView* rv = atv->audio_view()->find_view (*i);
4349
4350                                         if (rv) {
4351                                                 rs.push_back (rv);
4352                                         }
4353                                 }
4354
4355                                 delete regions;
4356                         }
4357                 }
4358         }
4359 }
4360
4361 void
4362 Editor::get_regions_after (RegionSelection& rs, nframes64_t where, const TrackSelection& ts) const
4363 {
4364         const TrackSelection* tracks;
4365
4366         if (ts.empty()) {
4367                 tracks = &track_views;
4368         } else {
4369                 tracks = &ts;
4370         }
4371
4372         for (TrackSelection::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4373         
4374                 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(*t);
4375
4376                 if (atv) {
4377                         boost::shared_ptr<Diskstream> ds;
4378                         boost::shared_ptr<Playlist> pl;
4379                         
4380                         if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
4381
4382                                 Playlist::RegionList* regions = pl->regions_touched ((nframes_t) floor ( (double)where * ds->speed()), max_frames);
4383
4384                                 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4385
4386                                         RegionView* rv = atv->audio_view()->find_view (*i);
4387
4388                                         if (rv) {
4389                                                 rs.push_back (rv);
4390                                         }
4391                                 }
4392
4393                                 delete regions;
4394                         }
4395                 }
4396         }
4397 }
4398
4399 void
4400 Editor::get_regions_for_action (RegionSelection& rs, bool allow_entered)
4401 {
4402         if (selection->regions.empty()) {
4403
4404                 if (selection->tracks.empty()) {
4405
4406                         /* no regions or tracks selected
4407                         */
4408                         
4409                         if (entered_regionview && mouse_mode == Editing::MouseObject) {
4410
4411                                 /*  entered regionview is valid and we're in object mode - 
4412                                     just use entered regionview
4413                                 */
4414
4415                                 rs.add (entered_regionview);
4416                         }
4417
4418                         return;
4419
4420                 } else {
4421
4422                         /* no regions selected, so get all regions at the edit point across
4423                            all selected tracks. 
4424                         */
4425
4426                         nframes64_t where = get_preferred_edit_position();
4427                         get_regions_at (rs, where, selection->tracks);
4428
4429                         /* if the entered regionview wasn't selected and neither was its track
4430                            then add it.
4431                         */
4432
4433                         if (entered_regionview != 0 &&
4434                             !selection->selected (entered_regionview) && 
4435                             !selection->selected (&entered_regionview->get_time_axis_view())) {
4436                                 rs.add (entered_regionview);
4437                         }
4438                 }
4439
4440         } else {
4441                 
4442                 /* just use the selected regions */
4443
4444                 rs = selection->regions;
4445
4446                 /* if the entered regionview wasn't selected and we allow this sort of thing,
4447                    then add it.
4448                 */
4449
4450                 if (allow_entered && entered_regionview && !selection->selected (entered_regionview)) {
4451                         rs.add (entered_regionview);
4452                 }
4453
4454         }
4455 }
4456
4457 void
4458 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions)
4459 {
4460
4461         for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4462                 
4463                 RouteTimeAxisView* tatv;
4464                 
4465                 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4466                         
4467                         boost::shared_ptr<Playlist> pl;
4468                         vector<boost::shared_ptr<Region> > results;
4469                         RegionView* marv;
4470                         boost::shared_ptr<Diskstream> ds;
4471                         
4472                         if ((ds = tatv->get_diskstream()) == 0) {
4473                                 /* bus */
4474                                 continue;
4475                         }
4476                         
4477                         if ((pl = (ds->playlist())) != 0) {
4478                                 pl->get_region_list_equivalent_regions (region, results);
4479                         }
4480                         
4481                         for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4482                                 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4483                                         regions.push_back (marv);
4484                                 }
4485                         }
4486                         
4487                 }
4488         }
4489 }       
4490
4491 void
4492 Editor::show_rhythm_ferret ()
4493 {
4494         if (rhythm_ferret == 0) {
4495                 rhythm_ferret = new RhythmFerret(*this);
4496         }
4497
4498         rhythm_ferret->set_session (session);
4499         rhythm_ferret->show ();
4500         rhythm_ferret->present ();
4501 }
4502
4503 void
4504 Editor::first_idle ()
4505 {
4506         MessageDialog* dialog = 0;
4507
4508         if (track_views.size() > 1) { 
4509                 dialog = new MessageDialog (*this, 
4510                                             _("Please wait while Ardour loads visual data"),
4511                                             true,
4512                                             Gtk::MESSAGE_INFO,
4513                                             Gtk::BUTTONS_NONE);
4514                 dialog->present ();
4515                 ARDOUR_UI::instance()->flush_pending ();
4516         }
4517
4518         for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4519                 (*t)->first_idle();
4520         }
4521         
4522         if (dialog) {
4523                 delete dialog;
4524         }
4525
4526         _have_idled = true;
4527 }