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