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