2 Copyright (C) 2000 Paul Davis
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.
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.
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.
27 #include <sigc++/bind.h>
29 #include <libgnomecanvas/libgnomecanvas.h>
30 #include <pbd/error.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/tearoff.h>
34 #include <gtkmm2ext/utils.h>
36 #include <ardour/audio_track.h>
37 #include <ardour/diskstream.h>
38 #include <ardour/plugin_manager.h>
39 #include <ardour/location.h>
40 #include <ardour/audioplaylist.h>
41 #include <ardour/audioregion.h>
42 #include <ardour/session.h>
43 #include <ardour/session_route.h>
44 #include <ardour/tempo.h>
45 #include <ardour/utils.h>
47 #include "ardour_ui.h"
48 #include "canvas-ruler.h"
49 #include "canvas-simpleline.h"
50 #include "canvas-simplerect.h"
51 #include "canvas-waveview.h"
52 #include "check_mark.h"
54 #include "grouped_buttons.h"
57 #include "playlist_selector.h"
58 #include "regionview.h"
59 #include "rgb_macros.h"
60 #include "selection.h"
61 #include "streamview.h"
62 #include "time_axis_view.h"
64 #include "crossfade_view.h"
66 #include "public_editor.h"
67 #include "crossfade_edit.h"
68 #include "audio_time_axis.h"
69 #include "gui_thread.h"
74 #include "imageframe_socket_handler.h"
75 /* </CMT Additions> */
79 using namespace ARDOUR;
81 using namespace Gtkmm2ext;
82 using namespace Editing;
84 /* XXX this is a hack. it ought to be the maximum value of an jack_nframes_t */
86 const double max_canvas_coordinate = 100000000.0;
87 const double Editor::timebar_height = 15.0;
89 #include "editor_xpms"
91 static const gchar *route_list_titles[] = {
96 static const gchar *edit_group_list_titles[] = {
100 static const gchar *named_selection_display_titles[] = {
105 static const int32_t slide_index = 0;
106 static const int32_t splice_index = 1;
108 static const gchar *edit_mode_strings[] = {
114 static const gchar *snap_type_strings[] = {
138 static const gchar *snap_mode_strings[] = {
144 static const gchar *zoom_focus_strings[] = {
153 /* Soundfile drag-n-drop */
161 static GtkTargetEntry target_table[] = {
162 { "STRING", 0, TARGET_STRING },
163 { "text/plain", 0, TARGET_STRING },
164 { "text/uri-list", 0, TARGET_URL },
165 { "application/x-rootwin-drop", 0, TARGET_ROOTWIN }
168 static guint n_targets = sizeof(target_table) / sizeof(target_table[0]);
170 Gdk::Cursor* Editor::cross_hair_cursor = 0;
171 Gdk::Cursor* Editor::selector_cursor = 0;
172 Gdk::Cursor* Editor::trimmer_cursor = 0;
173 Gdk::Cursor* Editor::grabber_cursor = 0;
174 Gdk::Cursor* Editor::zoom_cursor = 0;
175 Gdk::Cursor* Editor::time_fx_cursor = 0;
176 Gdk::Cursor* Editor::fader_cursor = 0;
177 Gdk::Cursor* Editor::speaker_cursor = 0;
178 Gdk::Cursor* Editor::null_cursor = 0;
179 Gdk::Cursor* Editor::wait_cursor = 0;
180 Gdk::Cursor* Editor::timebar_cursor = 0;
182 GdkPixmap *Editor::check_pixmap = 0;
183 GdkBitmap *Editor::check_mask = 0;
184 GdkPixmap *Editor::empty_pixmap = 0;
185 GdkBitmap *Editor::empty_mask = 0;
187 Editor::Editor (AudioEngine& eng)
190 /* time display buttons */
192 minsec_label (_("Mins:Secs")),
193 bbt_label (_("Bars:Beats")),
194 smpte_label (_("SMPTE")),
195 frame_label (_("Frames")),
196 tempo_label (_("Tempo")),
197 meter_label (_("Meter")),
198 mark_label (_("Location Markers")),
199 range_mark_label (_("Range Markers")),
200 transport_mark_label (_("Loop/Punch Ranges")),
202 edit_packer (3, 3, false),
203 edit_hscroll_left_arrow (Gtk::ARROW_LEFT, Gtk::SHADOW_OUT),
204 edit_hscroll_right_arrow (Gtk::ARROW_RIGHT, Gtk::SHADOW_OUT),
206 named_selection_display (internationalize (named_selection_display_titles)),
208 /* tool bar related */
210 editor_mixer_button (_("editor\nmixer")),
212 selection_start_clock (X_("SelectionStartClock"), true),
213 selection_end_clock (X_("SelectionEndClock"), true),
214 edit_cursor_clock (X_("EditCursorClock"), true),
215 zoom_range_clock (X_("ZoomRangeClock"), true, true),
217 toolbar_selection_clock_table (2,3),
219 mouse_mode_button_table (2, 3),
221 mouse_select_button (_("range")),
222 mouse_move_button (_("object")),
223 mouse_gain_button (_("gain")),
224 mouse_zoom_button (_("zoom")),
225 mouse_timefx_button (_("timefx")),
226 mouse_audition_button (_("listen")),
228 automation_mode_button (_("mode")),
229 global_automation_button (_("automation")),
231 edit_mode_label (_("Edit Mode")),
232 snap_type_label (_("Snap To")),
233 snap_mode_label(_("Snap Mode")),
234 zoom_focus_label (_("Zoom Focus")),
236 /* <CMT Additions> */
237 image_socket_listener(0),
238 /* </CMT Additions> */
242 nudge_label (_("Nudge")),
243 nudge_clock (X_("NudgeClock"), true, true)
248 /* we are a singleton */
250 PublicEditor::_instance = this;
254 check_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
255 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
256 &check_mask, NULL, (gchar **) check_xpm);
257 empty_pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
258 gtk_widget_get_colormap (GTK_WIDGET(edit_group_list.gobj())),
259 &empty_mask, NULL, (gchar **) empty_xpm);
263 selection = new Selection;
264 cut_buffer = new Selection;
266 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
267 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
268 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
269 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
271 clicked_regionview = 0;
272 clicked_trackview = 0;
273 clicked_audio_trackview = 0;
274 clicked_crossfadeview = 0;
275 clicked_control_point = 0;
276 latest_regionview = 0;
277 last_update_frame = 0;
279 last_audition_region = 0;
280 current_mixer_strip = 0;
281 current_bbt_points = 0;
283 snap_type = SnapToFrame;
284 set_snap_to (snap_type);
285 snap_mode = SnapNormal;
286 set_snap_mode (snap_mode);
287 snap_threshold = 5.0;
288 bbt_beat_subdivision = 4;
291 autoscroll_timeout_tag = -1;
292 interthread_progress_window = 0;
293 current_interthread_info = 0;
294 _show_measures = true;
295 _show_waveforms = true;
296 _show_waveforms_recording = true;
297 first_action_message = 0;
299 show_gain_after_trim = false;
300 no_zoom_repos_update = false;
301 ignore_route_list_reorder = false;
302 verbose_cursor_on = true;
303 route_removal = false;
305 show_automatic_regions_in_region_list = true;
306 have_pending_keyboard_selection = false;
307 _follow_playhead = true;
308 _xfade_visibility = true;
309 editor_ruler_menu = 0;
310 no_ruler_shown_update = false;
311 edit_group_list_menu = 0;
313 region_list_menu = 0;
315 marker_menu_item = 0;
317 transport_marker_menu = 0;
318 new_transport_marker_menu = 0;
319 editor_mixer_strip_width = Wide;
320 repos_zoom_queued = false;
321 import_audio_item = 0;
322 embed_audio_item = 0;
323 region_edit_menu_split_item = 0;
325 region_edit_menu_split_multichannel_item = 0;
326 edit_hscroll_dragging = false;
328 ignore_mouse_mode_toggle = false;
329 current_stepping_trackview = 0;
331 entered_regionview = 0;
332 clear_entered_track = false;
333 _new_regionviews_show_envelope = false;
334 current_timestretch = 0;
339 location_marker_color = color_map[cLocationMarker];
340 location_range_color = color_map[cLocationRange];
341 location_cd_marker_color = color_map[cLocationCDMarker];
342 location_loop_color = color_map[cLocationLoop];
343 location_punch_color = color_map[cLocationPunch];
345 range_marker_drag_rect = 0;
346 marker_drag_line = 0;
348 mouse_mode = MouseZoom; /* force change in next call */
349 set_mouse_mode (MouseObject, true);
351 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
352 zoom_focus = ZoomFocusLeft;
353 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
355 initialize_rulers ();
356 initialize_canvas ();
358 track_canvas_scroller.add (track_canvas);
359 track_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
360 track_canvas_scroller.set_name ("TrackCanvasScroller");
362 track_canvas_scroller.get_vadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
363 track_canvas_scroller.get_vadjustment()->set_step_increment (10.0);
365 track_canvas_scroller.get_hadjustment()->set_lower (0.0);
366 track_canvas_scroller.get_hadjustment()->set_upper (1200.0);
367 track_canvas_scroller.get_hadjustment()->set_step_increment (20.0);
368 track_canvas_scroller.get_hadjustment()->signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
370 edit_vscrollbar.set_adjustment(*track_canvas_scroller.get_vadjustment());
371 edit_hscrollbar.set_adjustment(*track_canvas_scroller.get_hadjustment());
373 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_press));
374 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscroll_slider_button_release));
375 edit_hscrollbar.size_allocate.connect (mem_fun(*this, &Editor::hscroll_slider_allocate));
377 time_canvas_scroller.add (time_canvas);
378 time_canvas_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
379 time_canvas_scroller.set_hadjustment (*track_canvas_scroller.get_hadjustment());
380 time_canvas_scroller.set_name ("TimeCanvasScroller");
382 edit_controls_vbox.set_spacing (track_spacing);
383 edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
384 edit_controls_scroller.add (edit_controls_hbox);
385 edit_controls_scroller.set_name ("EditControlsBase");
386 edit_controls_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_NEVER);
388 Viewport* viewport = static_cast<Viewport*> (edit_controls_scroller.get_child());
390 viewport->set_shadow_type (Gtk::SHADOW_NONE);
391 viewport->set_name ("EditControlsBase");
392 viewport->add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
393 viewport->signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
398 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
401 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
403 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
404 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
405 time_canvas_vbox.pack_start (*frames_ruler, false, false);
406 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
407 time_canvas_vbox.pack_start (time_canvas_scroller, true, true);
408 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
410 bbt_label.set_name ("EditorTimeButton");
411 bbt_label.set_size_request (-1, (int)timebar_height);
412 bbt_label.set_alignment (1.0, 0.5);
413 bbt_label.set_padding (5,0);
414 minsec_label.set_name ("EditorTimeButton");
415 minsec_label.set_size_request (-1, (int)timebar_height);
416 minsec_label.set_alignment (1.0, 0.5);
417 minsec_label.set_padding (5,0);
418 smpte_label.set_name ("EditorTimeButton");
419 smpte_label.set_size_request (-1, (int)timebar_height);
420 smpte_label.set_alignment (1.0, 0.5);
421 smpte_label.set_padding (5,0);
422 frame_label.set_name ("EditorTimeButton");
423 frame_label.set_size_request (-1, (int)timebar_height);
424 frame_label.set_alignment (1.0, 0.5);
425 frame_label.set_padding (5,0);
426 tempo_label.set_name ("EditorTimeButton");
427 tempo_label.set_size_request (-1, (int)timebar_height);
428 tempo_label.set_alignment (1.0, 0.5);
429 tempo_label.set_padding (5,0);
430 meter_label.set_name ("EditorTimeButton");
431 meter_label.set_size_request (-1, (int)timebar_height);
432 meter_label.set_alignment (1.0, 0.5);
433 meter_label.set_padding (5,0);
434 mark_label.set_name ("EditorTimeButton");
435 mark_label.set_size_request (-1, (int)timebar_height);
436 mark_label.set_alignment (1.0, 0.5);
437 mark_label.set_padding (5,0);
438 range_mark_label.set_name ("EditorTimeButton");
439 range_mark_label.set_size_request (-1, (int)timebar_height);
440 range_mark_label.set_alignment (1.0, 0.5);
441 range_mark_label.set_padding (5,0);
442 transport_mark_label.set_name ("EditorTimeButton");
443 transport_mark_label.set_size_request (-1, (int)timebar_height);
444 transport_mark_label.set_alignment (1.0, 0.5);
445 transport_mark_label.set_padding (5,0);
447 time_button_vbox.pack_start (minsec_label, false, false);
448 time_button_vbox.pack_start (smpte_label, false, false);
449 time_button_vbox.pack_start (frame_label, false, false);
450 time_button_vbox.pack_start (bbt_label, false, false);
451 time_button_vbox.pack_start (meter_label, false, false);
452 time_button_vbox.pack_start (tempo_label, false, false);
453 time_button_vbox.pack_start (mark_label, false, false);
455 time_button_event_box.add (time_button_vbox);
457 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
458 time_button_event_box.set_name ("TimebarLabelBase");
459 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
461 /* these enable us to have a dedicated window (for cursor setting, etc.)
462 for the canvas areas.
465 track_canvas_event_box.add (track_canvas_scroller);
467 time_canvas_event_box.add (time_canvas_vbox);
468 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
471 edit_packer.set_col_spacings (0);
472 edit_packer.set_row_spacings (0);
473 edit_packer.set_homogeneous (false);
474 edit_packer.set_name ("EditorWindow");
476 // edit_packer.attach (edit_hscroll_left_arrow_event, 0, 1, 0, 1, Gtk::FILL, 0, 0, 0);
477 // edit_packer.attach (edit_hscroll_slider, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, 0, 0, 0);
478 // edit_packer.attach (edit_hscroll_right_arrow_event, 2, 3, 0, 1, Gtk::FILL, 0, 0, 0);
479 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
481 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
482 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
484 edit_packer.attach (edit_controls_scroller, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
485 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
486 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
488 edit_frame.set_name ("BaseFrame");
489 edit_frame.set_shadow_type (SHADOW_IN);
490 edit_frame.add (edit_packer);
492 zoom_in_button.set_name ("EditorTimeButton");
493 zoom_out_button.set_name ("EditorTimeButton");
494 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
495 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
497 // zoom_onetoone_button.set_name ("EditorTimeButton");
498 zoom_out_full_button.set_name ("EditorTimeButton");
499 // ARDOUR_UI::instance()->tooltips().set_tip (zoom_onetoone_button, _("Zoom in 1:1"));
500 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
502 zoom_in_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_in_button_xpm)))));
503 zoom_out_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_button_xpm)))));
504 zoom_out_full_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(zoom_out_full_button_xpm)))));
505 // zoom_onetoone_button.add (*(manage (new Gtk::Image (zoom_onetoone_button_xpm))));
508 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
509 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
510 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
511 // zoom_onetoone_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom), 1.0));
513 zoom_indicator_box.pack_start (zoom_out_button, false, false);
514 zoom_indicator_box.pack_start (zoom_in_button, false, false);
515 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
516 // zoom_indicator_box.pack_start (zoom_onetoone_button, false, false);
517 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
519 zoom_indicator_label.set_text (_("Zoom Span"));
520 zoom_indicator_label.set_name ("ToolBarLabel");
523 zoom_indicator_vbox.set_spacing (3);
524 zoom_indicator_vbox.set_border_width (3);
525 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
526 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
529 bottom_hbox.set_border_width (3);
530 bottom_hbox.set_spacing (3);
532 route_display_model = ListStore::create(route_display_columns);
533 route_list.set_model (route_display_model);
534 route_list.append_column (_("Tracks"), route_display_columns.text);
535 route_list.set_name ("TrackListDisplay");
536 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
537 route_list.set_reorderable (true);
539 route_list.set_size_request (75,-1);
540 route_list.set_headers_visible (true);
541 route_list.set_headers_clickable (true);
543 route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
545 //route_list.set_shadow_type (Gtk::SHADOW_IN);
547 route_list_scroller.add (route_list);
548 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
550 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
551 route_list.rows_reordered.connect (mem_fun (*this, &Editor::queue_route_list_reordered));
552 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
554 edit_group_list_button_label.set_text (_("Edit Groups"));
555 edit_group_list_button_label.set_name ("EditGroupTitleButton");
556 edit_group_list_button.add (edit_group_list_button_label);
557 edit_group_list_button.set_name ("EditGroupTitleButton");
559 group_model = ListStore::create(group_columns);
560 edit_group_list.set_model (group_model);
561 edit_group_list.append_column (_("active"), group_columns.is_active);
562 edit_group_list.append_column (_("groupname"), group_columns.text);
563 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
564 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
566 /* use checkbox for the active column */
568 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
569 active_cell->set_property ("activatable", true);
570 active_cell->set_property ("radio", false);
572 edit_group_list.set_name ("MixerGroupList");
573 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
574 route_list.set_headers_visible (false);
575 edit_group_list.set_reorderable (false);
576 edit_group_list.set_size_request (75, -1);
577 edit_group_list.columns_autosize ();
578 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
580 edit_group_list_scroller.add (edit_group_list);
581 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
583 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
584 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
585 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
587 TreeModel::Row row = *(group_model->append());
588 row[group_columns.is_active] = false;
589 row[group_columns.text] = (_("-all-"));
590 edit_group_list.get_selection()->select (row);
591 /* GTK2FIX is set_data(0) setting the is_active to false here?
592 list<string> stupid_list;
594 stupid_list.push_back ("*");
595 stupid_list.push_back (_("-all-"));
597 edit_group_list.rows().push_back (stupid_list);
598 edit_group_list.rows().back().set_data (0);
599 edit_group_list.rows().back().select();
602 edit_group_vbox.pack_start (edit_group_list_button, false, false);
603 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
605 route_list_frame.set_name ("BaseFrame");
606 route_list_frame.set_shadow_type (Gtk::SHADOW_IN);
607 route_list_frame.add (route_list_scroller);
609 edit_group_list_frame.set_name ("BaseFrame");
610 edit_group_list_frame.set_shadow_type (Gtk::SHADOW_IN);
611 edit_group_list_frame.add (edit_group_vbox);
613 route_group_vpane.add1 (route_list_frame);
614 route_group_vpane.add2 (edit_group_list_frame);
616 list_vpacker.pack_start (route_group_vpane, true, true);
618 region_list_model = TreeStore::create (region_list_columns);
619 region_list_sort_model = TreeModelSort::create (region_list_model);
620 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
622 region_list_display.set_model (region_list_sort_model);
623 region_list_display.append_column (_("Regions"), region_list_columns.name);
624 region_list_display.set_reorderable (true);
625 region_list_display.set_size_request (100, -1);
626 region_list_display.set_data ("editor", this);
627 region_list_display.set_flags (Gtk::CAN_FOCUS);
628 region_list_display.set_name ("RegionListDisplay");
630 region_list_scroller.add (region_list_display);
631 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
633 region_list_display.drag_dest_set (GTK_DEST_DEFAULT_ALL,
634 target_table, n_targets - 1,
635 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
636 region_list_display.drag_data_received.connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
638 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
639 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
640 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
641 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
642 region_list_display.signal_motion_notify_event().connect (mem_fun(*this, &Editor::region_list_display_motion));
643 region_list_display.signal_enter_notify_event().connect (mem_fun(*this, &Editor::region_list_display_enter_notify));
644 region_list_display.signal_leave_notify_event().connect (mem_fun(*this, &Editor::region_list_display_leave_notify));
645 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
646 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
647 region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
649 named_selection_scroller.add (named_selection_display);
650 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
652 named_selection_model = TreeStore::create (named_selection_columns);
653 named_selection_display.set_model (named_selection_model);
654 named_selection_display.set_name ("RegionListDisplay");
655 named_selection_display.set_size_request (100, -1);
656 named_selection_display.set_headers_visible (true);
657 named_selection_display.set_headers_clickable (true);
658 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
659 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
660 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
662 region_selection_vpane.pack1 (region_list_scroller, true, true);
663 region_selection_vpane.pack2 (named_selection_scroller, true, true);
665 canvas_region_list_pane.pack1 (edit_frame, true, true);
666 canvas_region_list_pane.pack2 (region_selection_vpane, true, true);
668 track_list_canvas_pane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
669 static_cast<Gtk::Paned*> (&track_list_canvas_pane)));
670 canvas_region_list_pane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
671 static_cast<Gtk::Paned*> (&canvas_region_list_pane)));
672 route_group_vpane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
673 static_cast<Gtk::Paned*> (&route_group_vpane)));
674 region_selection_vpane.size_allocate.connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler),
675 static_cast<Gtk::Paned*> (®ion_selection_vpane)));
677 track_list_canvas_pane.pack1 (list_vpacker, true, true);
678 track_list_canvas_pane.pack2 (canvas_region_list_pane, true, true);
680 /* provide special pane-handle event handling for easy "hide" action */
682 /* 0: collapse to show left/upper child
683 1: collapse to show right/lower child
686 route_group_vpane.set_data ("collapse-direction", (gpointer) 0);
687 region_selection_vpane.set_data ("collapse-direction", (gpointer) 0);
688 canvas_region_list_pane.set_data ("collapse-direction", (gpointer) 0);
689 track_list_canvas_pane.set_data ("collapse-direction", (gpointer) 1);
691 route_group_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&route_group_vpane)));
692 region_selection_vpane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (®ion_selection_vpane)));
693 canvas_region_list_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&canvas_region_list_pane)));
694 track_list_canvas_pane.signal_button_release_event().connect (bind (sigc::ptr_fun (pane_handler), static_cast<Paned*> (&track_list_canvas_pane)));
696 top_hbox.pack_start (toolbar_frame, true, true);
698 HBox *hbox = manage (new HBox);
699 hbox->pack_start (track_list_canvas_pane, true, true);
701 global_vpacker.pack_start (top_hbox, false, false);
702 global_vpacker.pack_start (*hbox, true, true);
704 global_hpacker.pack_start (global_vpacker, true, true);
706 set_name ("EditorWindow");
708 vpacker.pack_end (global_hpacker, true, true);
710 _playlist_selector = new PlaylistSelector();
711 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
713 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
717 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
718 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
720 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
721 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
723 nudge_forward_button.set_name ("TransportButton");
724 nudge_backward_button.set_name ("TransportButton");
726 fade_context_menu.set_name ("ArdourContextMenu");
728 install_keybindings ();
730 set_title (_("ardour: editor"));
731 set_wmclass (_("ardour_editor"), "Ardour");
734 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
736 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
737 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
745 /* <CMT Additions> */
746 if(image_socket_listener)
748 if(image_socket_listener->is_connected())
750 image_socket_listener->close_connection() ;
753 delete image_socket_listener ;
754 image_socket_listener = 0 ;
756 /* </CMT Additions> */
760 Editor::add_toplevel_controls (Container& cont)
762 vpacker.pack_start (cont, false, false);
767 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
769 /* note: the selection will take care of the vanishing
770 audioregionview by itself.
773 if (clicked_regionview == rv) {
774 clicked_regionview = 0;
777 if (entered_regionview == rv) {
778 set_entered_regionview (0);
783 Editor::set_entered_regionview (AudioRegionView* rv)
785 if (rv == entered_regionview) {
789 if (entered_regionview) {
790 entered_regionview->exited ();
793 if ((entered_regionview = rv) != 0) {
794 entered_regionview->entered ();
799 Editor::set_entered_track (TimeAxisView* tav)
802 entered_track->exited ();
805 if ((entered_track = tav) != 0) {
806 entered_track->entered ();
811 Editor::left_track_canvas (GdkEventCrossing *ev)
813 set_entered_track (0);
814 set_entered_regionview (0);
820 Editor::initialize_canvas ()
822 gnome_canvas_init ();
824 /* adjust sensitivity for "picking" items */
826 // GNOME_CANVAS(track_canvas)->close_enough = 2;
828 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
829 track_canvas.set_name ("EditorMainCanvas");
830 track_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
831 track_canvas.signal_event().connect (mem_fun (*this, &Editor::track_canvas_event));
832 track_canvas.signal_leave_notify_event().connect (mem_fun(*this, &Editor::left_track_canvas));
834 /* set up drag-n-drop */
836 track_canvas.drag_dest_set (GTK_DEST_DEFAULT_ALL,
837 target_table, n_targets - 1,
838 GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
839 track_canvas.drag_data_received.connect (mem_fun(*this, &Editor::track_canvas_drag_data_received));
841 /* stuff for the verbose canvas cursor */
843 Pango::FontDescription font = get_font_for_style (N_("VerboseCanvasCursor"));
845 verbose_canvas_cursor = new Gnome::Canvas::Text (*track_canvas.root());
846 verbose_canvas_cursor->set_property ("font_desc", font);
847 verbose_canvas_cursor->set_property ("anchor", GTK_ANCHOR_NW);
848 verbose_canvas_cursor->set_property ("fill_color_rgba", color_map[cVerboseCanvasCursor]);
850 verbose_cursor_visible = false;
852 /* a group to hold time (measure) lines */
854 time_line_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
855 cursor_group = new Gnome::Canvas::Group (*track_canvas.root(), 0.0, 0.0);
857 time_canvas.set_name ("EditorTimeCanvas");
858 time_canvas.add_events (Gdk::POINTER_MOTION_HINT_MASK);
860 meter_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
861 tempo_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, 0.0);
862 marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 2.0);
863 range_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 3.0);
864 transport_marker_group = new Gnome::Canvas::Group (*time_canvas.root(), 0.0, timebar_height * 4.0);
866 tempo_bar = new Gnome::Canvas::SimpleRect (*tempo_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
867 tempo_bar->set_property ("fill_color_rgba", color_map[cTempoBar]);
868 tempo_bar->set_property ("outline_pixels", 0);
870 meter_bar = new Gnome::Canvas::SimpleRect (*meter_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
871 meter_bar->set_property ("fill_color_rgba", color_map[cMeterBar]);
872 meter_bar->set_property ("outline_pixels",0);
874 marker_bar = new Gnome::Canvas::SimpleRect (*marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
875 marker_bar->set_property ("fill_color_rgba", color_map[cMarkerBar]);
876 marker_bar->set_property ("outline_pixels", 0);
878 range_marker_bar = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
879 range_marker_bar->set_property ("fill_color_rgba", color_map[cRangeMarkerBar]);
880 range_marker_bar->set_property ("outline_pixels", 0);
882 transport_marker_bar = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
883 transport_marker_bar->set_property ("fill_color_rgba", color_map[cTransportMarkerBar]);
884 transport_marker_bar->set_property ("outline_pixels", 0);
886 range_bar_drag_rect = new Gnome::Canvas::SimpleRect (*range_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
887 range_bar_drag_rect->set_property ("fill_color_rgba", color_map[cRangeBarDragRectFill]);
888 range_bar_drag_rect->set_property ("outline_color_rgba", color_map[cRangeBarDragRect]);
889 range_bar_drag_rect->set_property ("outline_pixels", 0);
890 range_bar_drag_rect->hide ();
892 transport_bar_drag_rect = new Gnome::Canvas::SimpleRect (*transport_marker_group, 0.0, 0.0, max_canvas_coordinate, timebar_height);
893 transport_bar_drag_rect ->set_property ("fill_color_rgba", color_map[cTransportBarDragRectFill]);
894 transport_bar_drag_rect->set_property ("outline_color_rgba", color_map[cTransportBarDragRect]);
895 transport_bar_drag_rect->set_property ("outline_pixels", 0);
896 transport_bar_drag_rect->hide ();
898 marker_drag_line_points->push_back(Gnome::Art::Point(0.0, 0.0));
899 marker_drag_line_points->push_back(Gnome::Art::Point(0.0, 0.0));
901 marker_drag_line = new Gnome::Canvas::Line (*track_canvas.root());
902 marker_drag_line->set_property ("width_pixels", 1);
903 marker_drag_line->set_property("fill_color_rgba", color_map[cMarkerDragLine]);
904 marker_drag_line->set_property("points", marker_drag_line_points);
905 marker_drag_line->hide();
907 range_marker_drag_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
908 range_marker_drag_rect->set_property ("fill_color_rgba", color_map[cRangeDragRectFill]);
909 range_marker_drag_rect->set_property ("outline_color_rgba", color_map[cRangeDragRect]);
910 range_marker_drag_rect->hide ();
912 transport_loop_range_rect = new Gnome::Canvas::SimpleRect (group.root(), 0.0, 0.0, 0.0, 0.0);
913 transport_loop_range_rect->set_property ("fill_color_rgba", color_map[cTransportLoopRectFill]);
914 transport_loop_range_rect->set_property ("outline_color_rgba", color_map[cTransportLoopRect]);
915 transport_loop_range_rect->set_property ("outline_pixels", 1);
916 transport_loop_range_rect->hide();
918 transport_punch_range_rect = new Gnome::Canvas::SimpleRect (group.root(), 0.0, 0.0, 0.0, 0.0);
919 transport_punch_range_rect->set_property ("fill_color_rgba", color_map[cTransportPunchRectFill]);
920 transport_punch_range_rect->set_property ("outline_color_rgba", color_map[cTransportPunchRect]);
921 transport_punch_range_rect->set_property ("outline_pixels", 0);
922 transport_punch_range_rect->hide();
924 transport_loop_range_rect->lower_to_bottom (); // loop on the bottom
926 transport_punchin_line = new Gnome::Canvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, 0.0);
927 transport_punchin_line->set_property ("outline_color_rgba", color_map[cPunchInLine]);
928 transport_punchin_line->set_property ("outline_pixels", 1);
929 transport_punchin_line->hide ();
931 transport_punchout_line = new Gnome::Canvas::SimpleRect (group.root(), 0.0, 0.0, 0.0, 0.0);
932 transport_punchout_line->set_property ("outline_color_rgba", color_map[cPunchOutLine]);
933 transport_punchout_line->set_property ("outline_pixels", 1);
934 transport_punchout_line->hide();
936 // used to show zoom mode active zooming
937 zoom_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
938 zoom_rect->set_property ("fill_color_rgba", color_map[cZoomRectFill]);
939 zoom_rect->set_property ("outline_color_rgba", color_map[cZoomRect]);
940 zoom_rect->set_property ("outline_pixels", 1);
943 zoom_rect->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_zoom_rect_event));
945 // used as rubberband rect
946 rubberband_rect = new Gnome::Canvas::SimpleRect (*track_canvas.root(), 0.0, 0.0, 0.0, 0.0);
947 rubberband_rect->set_property ("outline_color_rgba", color_map[cRubberBandRect]);
948 rubberband_rect->set_property ("fill_color_rgba", (guint32) color_map[cRubberBandRectFill]);
949 rubberband_rect->set_property ("outline_pixels", 1);
950 rubberband_rect->hide();
952 tempo_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_tempo_bar_event));
953 meter_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_meter_bar_event));
954 marker_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_marker_bar_event));
955 range_marker_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_range_marker_bar_event));
956 transport_marker_bar->signal_event().connect (mem_fun (*this, &PublicEditor::canvas_transport_marker_bar_event));
958 /* separator lines */
960 tempo_line_points->push_back(Gnome::Art::Point(0, timebar_height));
961 tempo_line_points->push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
963 tempo_line = new Gnome::Canvas::Line (*tempo_group, *tempo_line_points);
964 tempo_line->set_property ("width_pixels", 0);
965 tempo_line->set_property ("fill_color", #000000);
967 meter_line_points->push_back(Gnome::Art::Point (0, timebar_height));
968 meter_line_points->push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
970 meter_line = new Gnome::Canvas::Line (*meter_group, *meter_line_points);
971 meter_line->set_property ("width_pixels", 0);
972 meter_line->set_property ("fill_color", #000000);
974 marker_line_points->push_back(Gnome::Art::Point (0, timebar_height));
975 marker_line_points->push_back(Gnome::Art::Point(max_canvas_coordinate, timebar_height));
977 marker_line = new Gnome::Canvas::Line (*marker_group, *marker_line_points);
978 marker_line->set_property ("width_pixels", 0);
979 marker_line->set_property ("fill_color", #000000);
981 range_marker_line = new Gnome::Canvas::Line (*range_marker_group, *marker_line_points);
982 range_marker_line->set_property ("width_pixels", 0);
983 range_marker_line->set_property ("fill_color", #000000);
985 transport_marker_line = new Gnome::Canvas::Line (*transport_marker_group, *marker_line_points);
986 transport_marker_line->set_property ("width_pixels", 0);
987 transport_marker_line->set_property ("fill_color", #000000);
989 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_loop_range_view), false));
990 ZoomChanged.connect (bind (mem_fun(*this, &Editor::update_punch_range_view), false));
992 double time_height = timebar_height * 5;
993 double time_width = FLT_MAX/frames_per_unit;
994 time_canvas.set_scroll_region(0.0, 0.0, time_width, time_height);
996 edit_cursor = new Cursor (*this, "blue", (GtkSignalFunc) _canvas_edit_cursor_event);
997 playhead_cursor = new Cursor (*this, "red", (GtkSignalFunc) _canvas_playhead_cursor_event);
999 track_canvas.size_allocate.connect (mem_fun(*this, &Editor::track_canvas_allocate));
1003 Editor::show_window ()
1007 /* now reset all audio_time_axis heights, because widgets might need
1013 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1014 tv = (static_cast<TimeAxisView*>(*i));
1015 tv->reset_height ();
1020 Editor::tie_vertical_scrolling ()
1022 edit_controls_scroller.get_vadjustment()->set_value (track_canvas_scroller.get_vadjustment()->get_value());
1024 float y1 = track_canvas_scroller.get_vadjustment()->get_value();
1025 playhead_cursor->set_y_axis(y1);
1026 edit_cursor->set_y_axis(y1);
1030 Editor::set_frames_per_unit (double fpu)
1032 jack_nframes_t frames;
1034 if (fpu == frames_per_unit) {
1042 // convert fpu to frame count
1044 frames = (jack_nframes_t) (fpu * canvas_width);
1046 /* don't allow zooms that fit more than the maximum number
1047 of frames into an 800 pixel wide space.
1050 if (max_frames / fpu < 800.0) {
1054 frames_per_unit = fpu;
1056 if (frames != zoom_range_clock.current_duration()) {
1057 zoom_range_clock.set (frames);
1060 /* only update these if we not about to call reposition_x_origin,
1061 which will do the same updates.
1065 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1068 if (!no_zoom_repos_update) {
1069 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1070 update_hscroller ();
1071 update_fixed_rulers ();
1072 tempo_map_changed (Change (0));
1075 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
1076 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
1077 (*i)->reshow_selection (selection->time);
1081 ZoomChanged (); /* EMIT_SIGNAL */
1083 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
1084 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
1091 Editor::instant_save ()
1093 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
1098 session->add_instant_xml(get_state(), session->path());
1100 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
1105 Editor::reposition_x_origin (jack_nframes_t frame)
1107 if (frame != leftmost_frame) {
1108 leftmost_frame = frame;
1109 double pixel = frame_to_pixel (frame);
1110 if (pixel >= track_canvas_scroller.get_hadjustment()->get_upper()) {
1111 track_canvas_scroller.get_hadjustment()->set_upper (frame_to_pixel (frame + (current_page_frames())));
1113 track_canvas_scroller.get_hadjustment()->set_value (frame/frames_per_unit);
1114 XOriginChanged (); /* EMIT_SIGNAL */
1119 Editor::edit_cursor_clock_changed()
1121 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
1122 edit_cursor->set_position (edit_cursor_clock.current_time());
1128 Editor::zoom_adjustment_changed ()
1130 if (session == 0 || no_zoom_repos_update) {
1134 double fpu = (double) zoom_range_clock.current_duration() / (double) canvas_width;
1138 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1140 else if (fpu > session->current_end_frame() / (double) canvas_width) {
1141 fpu = session->current_end_frame() / (double) canvas_width;
1142 zoom_range_clock.set ((jack_nframes_t) (fpu * canvas_width));
1145 temporal_zoom (fpu);
1149 Editor::canvas_horizontally_scrolled ()
1151 /* XXX note the potential loss of accuracy here caused by
1152 adjustments being 32bit floats with only a 24 bit mantissa,
1153 whereas jack_nframes_t is at least a 32 bit uint32_teger.
1156 leftmost_frame = (jack_nframes_t) floor (track_canvas_scroller.get_hadjustment()->get_value() * frames_per_unit);
1158 update_hscroller ();
1159 update_fixed_rulers ();
1161 if (!edit_hscroll_dragging) {
1162 tempo_map_changed (Change (0));
1164 update_tempo_based_rulers();
1169 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
1171 if (!repos_zoom_queued) {
1172 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
1173 repos_zoom_queued = true;
1178 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
1180 /* if we need to force an update to the hscroller stuff,
1181 don't set no_zoom_repos_update.
1184 no_zoom_repos_update = (frame != leftmost_frame);
1186 set_frames_per_unit (nfpu);
1187 if (no_zoom_repos_update) {
1188 reposition_x_origin (frame);
1190 no_zoom_repos_update = false;
1191 repos_zoom_queued = false;
1197 Editor::on_realize ()
1199 /* Even though we're not using acceleration, we want the
1202 Glib::RefPtr<Gdk::Pixmap> empty_pixmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1203 Glib::RefPtr<Gdk::Pixmap> empty_bitmap = Gdk::Pixmap::create(get_window(), 1, 1, 1);
1206 track_context_menu.accelerate (*this->get_toplevel());
1207 track_region_context_menu.accelerate (*this->get_toplevel());
1209 Window::on_realize ();
1211 Gdk::Color white ("#ffffff" );
1212 null_cursor = new Gdk::Cursor(empty_pixmap, empty_bitmap, white, white, 0, 0);
1220 track_canvas_scroller.get_window()->set_cursor (*current_canvas_cursor);
1221 time_canvas_scroller.get_window()->set_cursor (*timebar_cursor);
1225 Editor::track_canvas_allocate (GtkAllocation *alloc)
1227 canvas_width = alloc->width;
1228 canvas_height = alloc->height;
1230 if (session == 0 && !ARDOUR_UI::instance()->will_create_new_session_automatically()) {
1232 Pango::FontDescription font = get_font_for_style (N_("FirstActionMessage"));
1234 const char *txt1 = _("Start a new session\n");
1235 const char *txt2 = _("via Session menu");
1237 /* this mess of code is here to find out how wide this text is and
1238 position the message in the center of the editor window. there
1239 are two lines, so we use the longer of the the lines to
1240 compute width, and multiply the height by 2.
1246 /* this is a dummy widget that exists so that we can get the
1247 style from the RC file.
1250 Label foo (_(txt2));
1251 Glib::RefPtr<Pango::Layout> layout;
1252 foo.set_name ("NoSessionMessage");
1253 foo.ensure_style ();
1255 layout = foo.create_pango_layout (_(txt2));
1256 layout->set_font_description (font);
1257 layout->get_pixel_size (pixel_width, pixel_height);
1259 if (first_action_message == 0) {
1261 char txt[strlen(txt1)+strlen(txt2)+1];
1263 /* merge both lines */
1265 strcpy (txt, _(txt1));
1266 strcat (txt, _(txt2));
1268 first_action_message = gnome_canvas_item_new (gnome_canvas_root(GNOME_CANVAS(track_canvas)),
1269 gnome_canvas_text_get_type(),
1271 "fill_color_rgba", color_map[cFirstActionMessage],
1272 "x", (gdouble) (canvas_width - pixel_width) / 2.0,
1273 "y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)),
1274 "anchor", GTK_ANCHOR_NORTH_WEST,
1281 first_action_message->set_property ("x", (gdouble) (canvas_width - pixel_width) / 2.0),
1282 first_action_message->set_property ("y", (gdouble) (canvas_height/2.0) - (2.0 * (pixel_height)));
1286 zoom_range_clock.set ((jack_nframes_t) (canvas_width * frames_per_unit));
1287 edit_cursor->set_position (edit_cursor->current_frame);
1288 playhead_cursor->set_position (playhead_cursor->current_frame);
1289 reset_scrolling_region (alloc);
1291 Resized (); /* EMIT_SIGNAL */
1295 Editor::reset_scrolling_region (GtkAllocation *alloc)
1297 guint32 last_canvas_unit;
1299 guint32 canvas_alloc_height, canvas_alloc_width;
1300 TrackViewList::iterator i;
1301 static bool first_time = true;
1303 /* We need to make sure that the canvas always has its
1304 scrolling region set to larger of:
1306 - the size allocated for it (within the container its packed in)
1307 - the size required to see the entire session
1309 If we don't ensure at least the first of these, the canvas
1310 does some wierd and in my view unnecessary stuff to center
1311 itself within the allocated area, which causes bad, bad
1314 XXX GnomeCanvas has fixed this, and has an option to
1315 control the centering behaviour.
1318 last_canvas_unit = (guint32) ceil ((float) max_frames / frames_per_unit);
1323 for (i = track_views.begin(); i != track_views.end(); ++i) {
1324 if ((*i)->control_parent) {
1325 height += (*i)->effective_height;
1326 height += track_spacing;
1331 height -= track_spacing;
1335 canvas_height = (guint32) height;
1338 canvas_alloc_height = alloc->height;
1339 canvas_alloc_width = alloc->width;
1341 canvas_alloc_height = track_canvas.get_height();
1342 canvas_alloc_width = track_canvas.get_width();
1345 canvas_height = max (canvas_height, canvas_alloc_height);
1346 track_canvas.set_scroll_region ( 0.0, 0.0, max (last_canvas_unit, canvas_alloc_width), canvas_height);
1348 if (edit_cursor) edit_cursor->set_length (canvas_alloc_height);
1349 if (playhead_cursor) playhead_cursor->set_length (canvas_alloc_height);
1351 if (marker_drag_line) {
1352 marker_drag_line_points->coords[3] = canvas_height;
1353 // cerr << "set mlA points, nc = " << marker_drag_line_points->num_points << endl;
1354 marker_drag_line->set_property("points", marker_drag_line_points);
1356 if (range_marker_drag_rect) {
1357 range_marker_drag_rect->set_property("y1", 0.0);
1358 range_marker_drag_rect->set_property("y2", (double) canvas_height);
1360 if (transport_loop_range_rect) {
1361 transport_loop_range_rect->set_property("y1", 0.0);
1362 transport_loop_range_rect->set_property("y2", (double) canvas_height);
1364 if (transport_punch_range_rect) {
1365 transport_punch_range_rect->set_property("y1", 0.0);
1366 transport_punch_range_rect->set_property("y2", (double) canvas_height);
1368 if (transport_punchin_line) {
1369 transport_punchin_line->set_property("y1", 0.0);
1370 transport_punchin_line->set_property("y2", (double) canvas_height);
1372 if (transport_punchout_line) {
1373 transport_punchout_line->set_property("y1", 0.0);
1374 transport_punchout_line->set_property("y2", (double) canvas_height);
1377 update_fixed_rulers ();
1379 if (is_visible() && first_time) {
1380 tempo_map_changed (Change (0));
1388 Editor::queue_session_control_changed (Session::ControlType t)
1390 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1394 Editor::session_control_changed (Session::ControlType t)
1396 // right now we're only tracking the loop and punch state
1399 case Session::AutoLoop:
1400 update_loop_range_view (true);
1402 case Session::PunchIn:
1403 case Session::PunchOut:
1404 update_punch_range_view (true);
1413 Editor::fake_add_edit_group (RouteGroup *group)
1415 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1419 Editor::fake_handle_new_audio_region (AudioRegion *region)
1421 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1425 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1427 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1431 Editor::fake_handle_new_duration ()
1433 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1437 Editor::start_scrolling ()
1439 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1440 (mem_fun(*this, &Editor::update_current_screen));
1442 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1443 (mem_fun(*this, &Editor::update_slower));
1447 Editor::stop_scrolling ()
1449 scroll_connection.disconnect ();
1450 slower_update_connection.disconnect ();
1454 Editor::map_position_change (jack_nframes_t frame)
1456 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1458 if (session == 0 || !_follow_playhead) {
1462 center_screen (frame);
1463 playhead_cursor->set_position (frame);
1467 Editor::center_screen (jack_nframes_t frame)
1469 float page = canvas_width * frames_per_unit;
1471 /* if we're off the page, then scroll.
1474 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1475 center_screen_internal (frame,page);
1480 Editor::center_screen_internal (jack_nframes_t frame, float page)
1485 frame -= (jack_nframes_t) page;
1490 reposition_x_origin (frame);
1494 Editor::handle_new_duration ()
1496 reset_scrolling_region ();
1499 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1500 track_canvas_scroller.get_hadjustment()->set_value (leftmost_frame/frames_per_unit);
1503 update_hscroller ();
1507 Editor::update_title_s (string snap_name)
1509 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1515 Editor::update_title ()
1517 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1520 bool dirty = session->dirty();
1522 string wintitle = _("ardour: editor: ");
1528 wintitle += session->name();
1530 if (session->snap_name() != session->name()) {
1532 wintitle += session->snap_name();
1539 set_title (wintitle);
1544 Editor::connect_to_session (Session *t)
1548 if (first_action_message) {
1549 first_action_message->hide();
1552 flush_track_canvas();
1556 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1558 /* These signals can all be emitted by a non-GUI thread. Therefore the
1559 handlers for them must not attempt to directly interact with the GUI,
1560 but use Gtkmm2ext::UI::instance()->call_slot();
1563 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1564 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1565 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1566 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1567 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1568 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1569 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1570 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1571 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1572 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1573 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1574 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1575 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1577 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1578 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1580 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1582 session->foreach_edit_group(this, &Editor::add_edit_group);
1584 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1585 editor_mixer_button.set_name (X_("EditorMixerButton"));
1587 edit_cursor_clock.set_session (session);
1588 selection_start_clock.set_session (session);
1589 selection_end_clock.set_session (session);
1590 zoom_range_clock.set_session (session);
1591 _playlist_selector->set_session (session);
1592 nudge_clock.set_session (session);
1594 switch (session->get_edit_mode()) {
1596 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1600 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1604 Location* loc = session->locations()->auto_loop_location();
1606 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1607 if (loc->start() == loc->end()) {
1608 loc->set_end (loc->start() + 1);
1610 session->locations()->add (loc, false);
1611 session->set_auto_loop_location (loc);
1615 loc->set_name (_("Loop"));
1618 loc = session->locations()->auto_punch_location();
1620 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1621 if (loc->start() == loc->end()) {
1622 loc->set_end (loc->start() + 1);
1624 session->locations()->add (loc, false);
1625 session->set_auto_punch_location (loc);
1629 loc->set_name (_("Punch"));
1632 update_loop_range_view (true);
1633 update_punch_range_view (true);
1635 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1638 refresh_location_display ();
1639 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1640 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1641 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1642 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1643 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1645 reset_scrolling_region ();
1647 redisplay_regions ();
1648 redisplay_named_selections ();
1650 //route_list.freeze (); GTK2FIX
1651 route_display_model.clear ();
1652 session->foreach_route (this, &Editor::handle_new_route);
1653 // route_list.select_all ();
1655 route_list_reordered ();
1656 //route_list.thaw ();
1658 if (embed_audio_item) {
1659 embed_audio_item->set_sensitive (true);
1661 if (import_audio_item) {
1662 import_audio_item->set_sensitive (true);
1665 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1666 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1669 /* ::reposition_x_origin() doesn't work right here, since the old
1670 position may be zero already, and it does nothing in such
1676 track_canvas_scroller.get_hadjustment()->set_upper (session->current_end_frame() / frames_per_unit);
1677 track_canvas_scroller.get_hadjustment()->set_value (0);
1679 update_hscroller ();
1680 restore_ruler_visibility ();
1681 tempo_map_changed (Change (0));
1683 edit_cursor->set_position (0);
1684 playhead_cursor->set_position (0);
1688 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1691 /* don't show master bus in a new session */
1693 if (ARDOUR_UI::instance()->session_is_new ()) {
1695 TreeModel::Children rows = route_display_model->children();
1696 TreeModel::Children::iterator i;
1698 //route_list.freeze ();
1700 for (i = rows.begin(); i != rows.end(); ++i) {
1701 TimeAxisView *tv = (*i)[route_display_columns.tv];
1702 AudioTimeAxisView *atv;
1704 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1705 if (atv->route().master()) {
1706 route_list.get_selection()->unselect (i);
1707 //(*i)->unselect ();
1712 //route_list.thaw ();
1717 Editor::build_cursors ()
1719 Glib::RefPtr <Gdk::Pixmap> source, mask;
1720 Gdk::Color fg ("#ff0000"); /* Red. */
1721 Gdk::Color bg ("#0000ff"); /* Blue. */
1723 Gdk::Pixmap::create_from_data (source, hand_bits,
1724 hand_width, hand_height, 1, fg, bg);
1725 Gdk::Pixmap::create_from_data(mask, handmask_bits,
1726 handmask_width, handmask_height, 1, fg, bg);
1727 grabber_cursor = new Gdk::Cursor (source, mask, fg, bg, hand_x_hot, hand_y_hot);
1728 source->unreference();
1729 mask->unreference();
1731 Gdk::Color mbg ("#000000" ); /* Black */
1732 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1734 Gdk::Pixmap::create_from_data (source, mag_bits,
1735 mag_width, mag_height, 1, fg, bg);
1736 Gdk::Pixmap::create_from_data (mask, magmask_bits,
1737 mag_width, mag_height, 1, fg, bg);
1738 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1739 source->unreference();
1740 mask->unreference();
1742 Gdk::Color fbg ("#ffffff" );
1743 Gdk::Color ffg ("#000000" );
1745 Gdk::Pixmap::create_from_data (source, fader_cursor_bits,
1746 fader_cursor_width, fader_cursor_height, 1, fg, bg);
1747 Gdk::Pixmap::create_from_data (mask, fader_cursor_mask_bits,
1748 fader_cursor_width, fader_cursor_height, 1, fg, bg);
1749 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1750 source->unreference();
1751 mask->unreference();
1753 Gdk::Pixmap::create_from_data (source,speaker_cursor_bits,
1754 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1755 Gdk::Pixmap::create_from_data (mask, speaker_cursor_mask_bits,
1756 speaker_cursor_width, speaker_cursor_height, 1, fg, bg);
1757 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1758 source->unreference();
1759 mask->unreference();
1761 cross_hair_cursor = new Gdk::Cursor (Gdk::CROSSHAIR);
1762 trimmer_cursor = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
1763 selector_cursor = new Gdk::Cursor (Gdk::XTERM);
1764 time_fx_cursor = new Gdk::Cursor (Gdk::SIZING);
1765 wait_cursor = new Gdk::Cursor (Gdk::WATCH);
1766 timebar_cursor = new Gdk::Cursor(Gdk::LEFT_PTR);
1770 Editor::popup_fade_context_menu (int button, int32_t time, GnomeCanvasItem* item, ItemType item_type)
1772 using namespace Menu_Helpers;
1773 AudioRegionView* arv = static_cast<AudioRegionView*> (gtk_object_get_data (GTK_OBJECT(item), "regionview"));
1776 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1780 MenuList& items (fade_context_menu.items());
1784 switch (item_type) {
1786 case FadeInHandleItem:
1787 if (arv->region.fade_in_active()) {
1788 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1790 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1793 items.push_back (SeparatorElem());
1795 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1796 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1797 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1798 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1799 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1803 case FadeOutHandleItem:
1804 if (arv->region.fade_out_active()) {
1805 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1807 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1810 items.push_back (SeparatorElem());
1812 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1813 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1814 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1815 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1816 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1820 fatal << _("programming error: ")
1821 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1826 fade_context_menu.popup (button, time);
1830 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1832 using namespace Menu_Helpers;
1833 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1836 switch (item_type) {
1838 case AudioRegionViewName:
1839 case AudioRegionViewNameHighlight:
1840 if (with_selection) {
1841 build_menu_function = &Editor::build_track_selection_context_menu;
1843 build_menu_function = &Editor::build_track_region_context_menu;
1848 if (with_selection) {
1849 build_menu_function = &Editor::build_track_selection_context_menu;
1851 build_menu_function = &Editor::build_track_context_menu;
1855 case CrossfadeViewItem:
1856 build_menu_function = &Editor::build_track_crossfade_context_menu;
1860 if (clicked_audio_trackview->get_diskstream()) {
1861 build_menu_function = &Editor::build_track_context_menu;
1863 build_menu_function = &Editor::build_track_bus_context_menu;
1868 /* probably shouldn't happen but if it does, we don't care */
1872 menu = (this->*build_menu_function)(frame);
1873 menu->set_name ("ArdourContextMenu");
1875 /* now handle specific situations */
1877 switch (item_type) {
1879 case AudioRegionViewName:
1880 case AudioRegionViewNameHighlight:
1881 if (!with_selection) {
1882 if (region_edit_menu_split_item) {
1883 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1884 region_edit_menu_split_item->set_sensitive (true);
1886 region_edit_menu_split_item->set_sensitive (false);
1889 if (region_edit_menu_split_multichannel_item) {
1890 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1891 region_edit_menu_split_multichannel_item->set_sensitive (true);
1893 region_edit_menu_split_multichannel_item->set_sensitive (false);
1902 case CrossfadeViewItem:
1909 /* probably shouldn't happen but if it does, we don't care */
1913 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1915 /* Bounce to disk */
1917 using namespace Menu_Helpers;
1918 MenuList& edit_items = menu->items();
1920 edit_items.push_back (SeparatorElem());
1922 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1923 case AudioTrack::NoFreeze:
1924 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1927 case AudioTrack::Frozen:
1928 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1931 case AudioTrack::UnFrozen:
1932 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1938 menu->popup (button, time);
1942 Editor::build_track_context_menu (jack_nframes_t ignored)
1944 using namespace Menu_Helpers;
1946 MenuList& edit_items = track_context_menu.items();
1949 add_dstream_context_items (edit_items);
1950 return &track_context_menu;
1954 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1956 using namespace Menu_Helpers;
1958 MenuList& edit_items = track_context_menu.items();
1961 add_bus_context_items (edit_items);
1962 return &track_context_menu;
1966 Editor::build_track_region_context_menu (jack_nframes_t frame)
1968 using namespace Menu_Helpers;
1969 MenuList& edit_items = track_region_context_menu.items();
1972 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1978 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1979 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1980 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1981 add_region_context_items (atv->view, (*i), edit_items);
1987 add_dstream_context_items (edit_items);
1989 return &track_region_context_menu;
1993 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1995 using namespace Menu_Helpers;
1996 MenuList& edit_items = track_crossfade_context_menu.items();
1997 edit_items.clear ();
1999 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
2006 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
2008 Playlist::RegionList* regions = pl->regions_at (frame);
2009 AudioPlaylist::Crossfades xfades;
2011 apl->crossfades_at (frame, xfades);
2013 bool many = xfades.size() > 1;
2015 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
2016 add_crossfade_context_items (atv->view, (*i), edit_items, many);
2019 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
2020 add_region_context_items (atv->view, (*i), edit_items);
2027 add_dstream_context_items (edit_items);
2029 return &track_crossfade_context_menu;
2033 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
2035 using namespace Menu_Helpers;
2036 MenuList& edit_items = track_selection_context_menu.items();
2037 edit_items.clear ();
2039 add_selection_context_items (edit_items);
2040 add_dstream_context_items (edit_items);
2042 return &track_selection_context_menu;
2046 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
2048 using namespace Menu_Helpers;
2049 Menu *xfade_menu = manage (new Menu);
2050 MenuList& items = xfade_menu->items();
2051 xfade_menu->set_name ("ArdourContextMenu");
2054 if (xfade->active()) {
2060 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
2061 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
2063 if (xfade->can_follow_overlap()) {
2065 if (xfade->following_overlap()) {
2066 str = _("Convert to short");
2068 str = _("Convert to full");
2071 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
2075 str = xfade->out().name();
2077 str += xfade->in().name();
2079 str = _("Crossfade");
2082 edit_items.push_back (MenuElem (str, *xfade_menu));
2083 edit_items.push_back (SeparatorElem());
2087 Editor::xfade_edit_left_region ()
2089 if (clicked_crossfadeview) {
2090 clicked_crossfadeview->left_view.show_region_editor ();
2095 Editor::xfade_edit_right_region ()
2097 if (clicked_crossfadeview) {
2098 clicked_crossfadeview->right_view.show_region_editor ();
2103 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
2105 using namespace Menu_Helpers;
2106 Menu *region_menu = manage (new Menu);
2107 MenuList& items = region_menu->items();
2108 region_menu->set_name ("ArdourContextMenu");
2110 AudioRegion* ar = 0;
2113 ar = dynamic_cast<AudioRegion*> (region);
2116 /* when this particular menu pops up, make the relevant region
2120 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
2122 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
2123 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
2124 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
2125 items.push_back (SeparatorElem());
2126 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
2127 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
2128 items.push_back (SeparatorElem());
2130 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
2131 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
2132 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
2133 items.push_back (SeparatorElem());
2135 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
2136 might be able to figure out which overloaded member function to use in
2140 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
2142 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
2143 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
2144 items.push_back (SeparatorElem());
2146 if (region->muted()) {
2147 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
2149 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
2151 items.push_back (SeparatorElem());
2153 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
2154 items.push_back (SeparatorElem());
2159 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
2160 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
2161 items.push_back (SeparatorElem());
2163 if (ar->scale_amplitude() != 1.0f) {
2164 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
2166 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
2169 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
2170 items.push_back (SeparatorElem());
2174 Menu *nudge_menu = manage (new Menu());
2175 MenuList& nudge_items = nudge_menu->items();
2176 nudge_menu->set_name ("ArdourContextMenu");
2178 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
2179 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
2180 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
2181 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
2183 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2184 items.push_back (SeparatorElem());
2186 Menu *trim_menu = manage (new Menu);
2187 MenuList& trim_items = trim_menu->items();
2188 trim_menu->set_name ("ArdourContextMenu");
2190 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
2191 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
2193 items.push_back (MenuElem (_("Trim"), *trim_menu));
2194 items.push_back (SeparatorElem());
2196 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
2197 region_edit_menu_split_item = &items.back();
2199 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
2200 region_edit_menu_split_multichannel_item = &items.back();
2202 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
2203 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
2204 items.push_back (SeparatorElem());
2205 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
2206 items.push_back (SeparatorElem());
2207 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
2209 /* OK, stick the region submenu at the top of the list, and then add
2213 /* we have to hack up the region name because "_" has a special
2214 meaning for menu titles.
2217 string::size_type pos = 0;
2218 string menu_item_name = region->name();
2220 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
2221 menu_item_name.replace (pos, 1, "__");
2225 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
2226 edit_items.push_back (SeparatorElem());
2230 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
2232 using namespace Menu_Helpers;
2233 Menu *selection_menu = manage (new Menu);
2234 MenuList& items = selection_menu->items();
2235 selection_menu->set_name ("ArdourContextMenu");
2237 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
2238 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
2239 items.push_back (SeparatorElem());
2240 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
2241 items.push_back (SeparatorElem());
2242 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
2243 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
2244 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
2245 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
2246 items.push_back (SeparatorElem());
2247 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
2248 items.push_back (SeparatorElem());
2249 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
2250 items.push_back (SeparatorElem());
2251 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
2253 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
2254 edit_items.push_back (SeparatorElem());
2258 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2260 using namespace Menu_Helpers;
2264 Menu *play_menu = manage (new Menu);
2265 MenuList& play_items = play_menu->items();
2266 play_menu->set_name ("ArdourContextMenu");
2268 play_items.push_back (MenuElem (_("Play from edit cursor")));
2269 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2270 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
2271 play_items.push_back (SeparatorElem());
2272 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
2274 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2278 Menu *select_menu = manage (new Menu);
2279 MenuList& select_items = select_menu->items();
2280 select_menu->set_name ("ArdourContextMenu");
2282 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2283 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2284 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2285 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2286 select_items.push_back (SeparatorElem());
2287 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2288 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2289 select_items.push_back (SeparatorElem());
2291 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2295 Menu *cutnpaste_menu = manage (new Menu);
2296 MenuList& cutnpaste_items = cutnpaste_menu->items();
2297 cutnpaste_menu->set_name ("ArdourContextMenu");
2299 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2300 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2301 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2302 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
2304 cutnpaste_items.push_back (SeparatorElem());
2306 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
2307 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
2309 cutnpaste_items.push_back (SeparatorElem());
2311 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
2313 cutnpaste_items.push_back (SeparatorElem());
2315 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
2316 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
2318 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2320 /* Adding new material */
2322 Menu *import_menu = manage (new Menu());
2323 MenuList& import_items = import_menu->items();
2324 import_menu->set_name ("ArdourContextMenu");
2326 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2327 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
2329 edit_items.push_back (MenuElem (_("Import"), *import_menu));
2333 Menu *nudge_menu = manage (new Menu());
2334 MenuList& nudge_items = nudge_menu->items();
2335 nudge_menu->set_name ("ArdourContextMenu");
2337 edit_items.push_back (SeparatorElem());
2338 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2339 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2340 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2341 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2343 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2347 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2349 using namespace Menu_Helpers;
2353 Menu *play_menu = manage (new Menu);
2354 MenuList& play_items = play_menu->items();
2355 play_menu->set_name ("ArdourContextMenu");
2357 play_items.push_back (MenuElem (_("Play from edit cursor")));
2358 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
2359 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2363 Menu *select_menu = manage (new Menu);
2364 MenuList& select_items = select_menu->items();
2365 select_menu->set_name ("ArdourContextMenu");
2367 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
2368 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
2369 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
2370 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
2371 select_items.push_back (SeparatorElem());
2372 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
2373 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
2374 select_items.push_back (SeparatorElem());
2376 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2380 Menu *cutnpaste_menu = manage (new Menu);
2381 MenuList& cutnpaste_items = cutnpaste_menu->items();
2382 cutnpaste_menu->set_name ("ArdourContextMenu");
2384 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
2385 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
2386 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
2388 Menu *nudge_menu = manage (new Menu());
2389 MenuList& nudge_items = nudge_menu->items();
2390 nudge_menu->set_name ("ArdourContextMenu");
2392 edit_items.push_back (SeparatorElem());
2393 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
2394 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
2395 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
2396 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
2398 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2401 /* CURSOR SETTING AND MARKS AND STUFF */
2404 Editor::set_snap_to (SnapType st)
2407 vector<string> txt = internationalize (snap_type_strings);
2408 snap_type_selector.set_active_text (txt[(int)st]);
2412 switch (snap_type) {
2413 case SnapToAThirtysecondBeat:
2414 case SnapToASixteenthBeat:
2415 case SnapToAEighthBeat:
2416 case SnapToAQuarterBeat:
2417 case SnapToAThirdBeat:
2418 update_tempo_based_rulers ();
2426 Editor::set_snap_mode (SnapMode mode)
2429 vector<string> txt = internationalize (snap_mode_strings);
2430 snap_mode_selector.set_active_text (txt[(int)mode]);
2436 Editor::add_location_from_selection ()
2438 if (selection->time.empty()) {
2442 if (session == 0 || clicked_trackview == 0) {
2446 jack_nframes_t start = selection->time[clicked_selection].start;
2447 jack_nframes_t end = selection->time[clicked_selection].end;
2449 Location *location = new Location (start, end, "selection");
2451 session->begin_reversible_command (_("add marker"));
2452 session->add_undo (session->locations()->get_memento());
2453 session->locations()->add (location, true);
2454 session->add_redo_no_execute (session->locations()->get_memento());
2455 session->commit_reversible_command ();
2459 Editor::add_location_from_playhead_cursor ()
2461 jack_nframes_t where = session->audible_frame();
2463 Location *location = new Location (where, where, "mark", Location::IsMark);
2464 session->begin_reversible_command (_("add marker"));
2465 session->add_undo (session->locations()->get_memento());
2466 session->locations()->add (location, true);
2467 session->add_redo_no_execute (session->locations()->get_memento());
2468 session->commit_reversible_command ();
2473 Editor::set_state (const XMLNode& node)
2475 const XMLProperty* prop;
2477 int x, y, width, height, xoff, yoff;
2479 if ((geometry = find_named_node (node, "geometry")) == 0) {
2481 width = default_width;
2482 height = default_height;
2490 width = atoi(geometry->property("x_size")->value());
2491 height = atoi(geometry->property("y_size")->value());
2492 x = atoi(geometry->property("x_pos")->value());
2493 y = atoi(geometry->property("y_pos")->value());
2494 xoff = atoi(geometry->property("x_off")->value());
2495 yoff = atoi(geometry->property("y_off")->value());
2498 set_default_size(width, height);
2499 set_position(x, y-yoff);
2501 if ((prop = node.property ("zoom-focus"))) {
2502 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2505 if ((prop = node.property ("zoom"))) {
2506 set_frames_per_unit (atof (prop->value()));
2509 if ((prop = node.property ("snap-to"))) {
2510 set_snap_to ((SnapType) atoi (prop->value()));
2513 if ((prop = node.property ("snap-mode"))) {
2514 set_snap_mode ((SnapMode) atoi (prop->value()));
2517 if ((prop = node.property ("show-waveforms"))) {
2518 bool yn = (prop->value() == "yes");
2519 _show_waveforms = !yn;
2520 set_show_waveforms (yn);
2523 if ((prop = node.property ("show-waveforms-recording"))) {
2524 bool yn = (prop->value() == "yes");
2525 _show_waveforms_recording = !yn;
2526 set_show_waveforms_recording (yn);
2529 if ((prop = node.property ("show-measures"))) {
2530 bool yn = (prop->value() == "yes");
2531 _show_measures = !yn;
2532 set_show_measures (yn);
2535 if ((prop = node.property ("follow-playhead"))) {
2536 bool yn = (prop->value() == "yes");
2537 _follow_playhead = !yn;
2538 set_follow_playhead (yn);
2541 if ((prop = node.property ("xfades-visible"))) {
2542 bool yn = (prop->value() == "yes");
2543 _xfade_visibility = !yn;
2544 set_xfade_visibility (yn);
2547 if ((prop = node.property ("region-list-sort-type"))) {
2548 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2549 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2552 if ((prop = node.property ("mouse-mode"))) {
2553 MouseMode m = str2mousemode(prop->value());
2554 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2555 set_mouse_mode (m, true);
2557 mouse_mode = MouseGain; /* lie, to force the mode switch */
2558 set_mouse_mode (MouseObject, true);
2561 if ((prop = node.property ("editor-mixer-button"))) {
2562 editor_mixer_button.set_active(prop->value() == "yes");
2569 Editor::get_state ()
2571 XMLNode* node = new XMLNode ("Editor");
2574 if (is_realized()) {
2575 Glib::RefPtr<Gdk::Window> win = get_window();
2577 int x, y, xoff, yoff, width, height;
2578 win->get_root_origin(x, y);
2579 win->get_position(xoff, yoff);
2580 win->get_size(width, height);
2582 XMLNode* geometry = new XMLNode ("geometry");
2584 snprintf(buf, sizeof(buf), "%d", width);
2585 geometry->add_property("x_size", string(buf));
2586 snprintf(buf, sizeof(buf), "%d", height);
2587 geometry->add_property("y_size", string(buf));
2588 snprintf(buf, sizeof(buf), "%d", x);
2589 geometry->add_property("x_pos", string(buf));
2590 snprintf(buf, sizeof(buf), "%d", y);
2591 geometry->add_property("y_pos", string(buf));
2592 snprintf(buf, sizeof(buf), "%d", xoff);
2593 geometry->add_property("x_off", string(buf));
2594 snprintf(buf, sizeof(buf), "%d", yoff);
2595 geometry->add_property("y_off", string(buf));
2596 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&canvas_region_list_pane)->gobj()));
2597 geometry->add_property("canvas_region_list_pane_pos", string(buf));
2598 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&track_list_canvas_pane)->gobj()));
2599 geometry->add_property("track_list_canvas_pane_pos", string(buf));
2600 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(®ion_selection_vpane)->gobj()));
2601 geometry->add_property("region_selection_pane_pos", string(buf));
2602 snprintf(buf,sizeof(buf), "%d", gtk_paned_get_position (static_cast<Paned*>(&route_group_vpane)->gobj()));
2603 geometry->add_property("route_group_pane_pos", string(buf));
2605 node->add_child_nocopy (*geometry);
2608 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2609 node->add_property ("zoom-focus", buf);
2610 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2611 node->add_property ("zoom", buf);
2612 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2613 node->add_property ("snap-to", buf);
2614 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2615 node->add_property ("snap-mode", buf);
2617 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2618 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2619 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2620 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2621 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2622 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2623 node->add_property ("mouse-mode", enum2str(mouse_mode));
2624 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2632 Editor::trackview_by_y_position (double y)
2634 TrackViewList::iterator iter;
2637 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2645 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2654 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2656 Location* before = 0;
2657 Location* after = 0;
2663 const jack_nframes_t one_second = session->frame_rate();
2664 const jack_nframes_t one_minute = session->frame_rate() * 60;
2666 jack_nframes_t presnap = start;
2668 switch (snap_type) {
2674 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2676 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2679 case SnapToSMPTEFrame:
2681 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2683 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2687 case SnapToSMPTESeconds:
2688 if (session->smpte_offset_negative())
2690 start += session->smpte_offset ();
2692 start -= session->smpte_offset ();
2694 if (direction > 0) {
2695 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2697 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2700 if (session->smpte_offset_negative())
2702 start -= session->smpte_offset ();
2704 start += session->smpte_offset ();
2708 case SnapToSMPTEMinutes:
2709 if (session->smpte_offset_negative())
2711 start += session->smpte_offset ();
2713 start -= session->smpte_offset ();
2716 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2718 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2720 if (session->smpte_offset_negative())
2722 start -= session->smpte_offset ();
2724 start += session->smpte_offset ();
2730 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2732 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2738 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2740 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2745 start = session->tempo_map().round_to_bar (start, direction);
2749 start = session->tempo_map().round_to_beat (start, direction);
2752 case SnapToAThirtysecondBeat:
2753 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2756 case SnapToASixteenthBeat:
2757 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2760 case SnapToAEighthBeat:
2761 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2764 case SnapToAQuarterBeat:
2765 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2768 case SnapToAThirdBeat:
2769 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2772 case SnapToEditCursor:
2773 start = edit_cursor->current_frame;
2781 before = session->locations()->first_location_before (start);
2782 after = session->locations()->first_location_after (start);
2784 if (direction < 0) {
2786 start = before->start();
2790 } else if (direction > 0) {
2792 start = after->start();
2794 start = session->current_end_frame();
2799 /* find nearest of the two */
2800 if ((start - before->start()) < (after->start() - start)) {
2801 start = before->start();
2803 start = after->start();
2806 start = before->start();
2809 start = after->start();
2816 case SnapToRegionStart:
2817 case SnapToRegionEnd:
2818 case SnapToRegionSync:
2819 case SnapToRegionBoundary:
2820 if (!region_boundary_cache.empty()) {
2821 vector<jack_nframes_t>::iterator i;
2823 if (direction > 0) {
2824 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2826 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2829 if (i != region_boundary_cache.end()) {
2832 start = region_boundary_cache.back();
2838 switch (snap_mode) {
2844 if (presnap > start) {
2845 if (presnap > (start + unit_to_frame(snap_threshold))) {
2849 } else if (presnap < start) {
2850 if (presnap < (start - unit_to_frame(snap_threshold))) {
2862 Editor::setup_toolbar ()
2865 vector<ToggleButton *> mouse_mode_buttons;
2867 mouse_mode_buttons.push_back (&mouse_move_button);
2868 mouse_mode_buttons.push_back (&mouse_select_button);
2869 mouse_mode_buttons.push_back (&mouse_gain_button);
2870 mouse_mode_buttons.push_back (&mouse_zoom_button);
2871 mouse_mode_buttons.push_back (&mouse_timefx_button);
2872 mouse_mode_buttons.push_back (&mouse_audition_button);
2873 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2875 mouse_mode_button_table.set_homogeneous (true);
2876 mouse_mode_button_table.set_col_spacings (2);
2877 mouse_mode_button_table.set_row_spacings (2);
2878 mouse_mode_button_table.set_border_width (5);
2880 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2881 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2882 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2884 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2885 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2886 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2888 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2889 mouse_mode_tearoff->set_name ("MouseModeBase");
2891 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2892 static_cast<Gtk::Widget*>(&mouse_mode_button_table)));
2893 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2894 static_cast<Gtk::Widget*> (&mouse_mode_button_table), 1));
2896 mouse_move_button.set_name ("MouseModeButton");
2897 mouse_select_button.set_name ("MouseModeButton");
2898 mouse_gain_button.set_name ("MouseModeButton");
2899 mouse_zoom_button.set_name ("MouseModeButton");
2900 mouse_timefx_button.set_name ("MouseModeButton");
2901 mouse_audition_button.set_name ("MouseModeButton");
2903 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2904 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2905 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2906 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2907 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2908 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2910 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2911 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2912 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2913 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2914 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2915 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2917 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2918 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2920 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2921 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2922 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2923 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2924 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2926 // mouse_move_button.set_active (true);
2928 /* automation control */
2930 global_automation_button.set_name ("MouseModeButton");
2931 automation_mode_button.set_name ("MouseModeButton");
2933 automation_box.set_spacing (2);
2934 automation_box.set_border_width (2);
2935 automation_box.pack_start (global_automation_button, false, false);
2936 automation_box.pack_start (automation_mode_button, false, false);
2940 edit_mode_label.set_name ("ToolBarLabel");
2942 edit_mode_selector.set_name ("EditModeSelector");
2944 edit_mode_box.set_spacing (3);
2945 edit_mode_box.set_border_width (3);
2947 /* XXX another disgusting hack because of the way combo boxes size themselves */
2949 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2, 10);
2950 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2951 edit_mode_box.pack_start (edit_mode_label, false, false);
2952 edit_mode_box.pack_start (edit_mode_selector, false, false);
2954 edit_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2958 snap_type_label.set_name ("ToolBarLabel");
2960 snap_type_selector.set_name ("SnapTypeSelector");
2962 snap_type_box.set_spacing (3);
2963 snap_type_box.set_border_width (3);
2965 /* XXX another disgusting hack because of the way combo boxes size themselves */
2967 const guint32 FUDGE = 10; // Combo's are stupid - they steal space from the entry for the button
2968 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "Region bounds", 2+FUDGE, 10);
2969 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2971 snap_type_box.pack_start (snap_type_label, false, false);
2972 snap_type_box.pack_start (snap_type_selector, false, false);
2974 snap_type_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2976 /* Snap mode, not snap type */
2978 snap_mode_label.set_name ("ToolBarLabel");
2980 snap_mode_selector.set_name ("SnapModeSelector");
2982 snap_mode_box.set_spacing (3);
2983 snap_mode_box.set_border_width (3);
2985 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2, 10);
2986 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2988 snap_mode_box.pack_start (snap_mode_label, false, false);
2989 snap_mode_box.pack_start (snap_mode_selector, false, false);
2991 snap_mode_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2993 /* Zoom focus mode */
2995 zoom_focus_label.set_name ("ToolBarLabel");
2997 zoom_focus_selector.set_name ("ZoomFocusSelector");
2999 zoom_focus_box.set_spacing (3);
3000 zoom_focus_box.set_border_width (3);
3002 /* XXX another disgusting hack because of the way combo boxes size themselves */
3004 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2, 10);
3005 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
3007 zoom_focus_box.pack_start (zoom_focus_label, false, false);
3008 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
3010 zoom_focus_selector.signal_unmap_event().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
3012 /* selection/cursor clocks */
3014 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
3015 selection_start_clock_label.set_name ("ToolBarLabel");
3016 selection_end_clock_label.set_name ("ToolBarLabel");
3017 edit_cursor_clock_label.set_name ("ToolBarLabel");
3019 selection_start_clock_label.set_text (_("Start:"));
3020 selection_end_clock_label.set_text (_("End:"));
3021 edit_cursor_clock_label.set_text (_("Edit:"));
3023 toolbar_selection_clock_table.set_border_width (5);
3024 toolbar_selection_clock_table.set_col_spacings (2);
3025 toolbar_selection_clock_table.set_homogeneous (false);
3027 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
3028 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
3029 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
3031 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
3032 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
3033 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
3036 // toolbar_clock_vbox.set_spacing (2);
3037 // toolbar_clock_vbox.set_border_width (10);
3038 /* the editor/mixer button will be enabled at session connect */
3040 editor_mixer_button.set_active(false);
3041 editor_mixer_button.set_sensitive(false);
3043 HBox* hbox = new HBox;
3045 hbox->pack_start (editor_mixer_button, false, false);
3046 hbox->pack_start (toolbar_selection_clock_table, false, false);
3047 hbox->pack_start (zoom_indicator_vbox, false, false);
3048 hbox->pack_start (zoom_focus_box, false, false);
3049 hbox->pack_start (snap_type_box, false, false);
3050 hbox->pack_start (snap_mode_box, false, false);
3051 hbox->pack_start (edit_mode_box, false, false);
3053 VBox *vbox = manage (new VBox);
3055 vbox->set_spacing (3);
3056 vbox->set_border_width (3);
3058 HBox *nbox = manage (new HBox);
3060 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
3061 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
3063 nbox->pack_start (nudge_backward_button, false, false);
3064 nbox->pack_start (nudge_forward_button, false, false);
3065 nbox->pack_start (nudge_clock, false, false, 5);
3067 nudge_label.set_name ("ToolBarLabel");
3069 vbox->pack_start (nudge_label, false, false);
3070 vbox->pack_start (*nbox, false, false);
3072 hbox->pack_start (*vbox, false, false);
3076 tools_tearoff = new TearOff (*hbox);
3077 tools_tearoff->set_name ("MouseModeBase");
3079 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
3080 static_cast<Gtk::Widget*>(hbox)));
3081 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
3082 static_cast<Gtk::Widget*> (hbox), 0));
3084 toolbar_hbox.set_spacing (8);
3085 toolbar_hbox.set_border_width (2);
3087 toolbar_hbox.pack_start (*tools_tearoff, false, false);
3088 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
3090 toolbar_base.set_name ("ToolBarBase");
3091 toolbar_base.add (toolbar_hbox);
3093 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
3094 toolbar_frame.set_name ("BaseFrame");
3095 toolbar_frame.add (toolbar_base);
3099 Editor::_autoscroll_canvas (void *arg)
3101 return ((Editor *) arg)->autoscroll_canvas ();
3105 Editor::autoscroll_canvas ()
3107 jack_nframes_t new_frame;
3108 bool keep_calling = true;
3110 if (autoscroll_direction < 0) {
3111 if (leftmost_frame < autoscroll_distance) {
3114 new_frame = leftmost_frame - autoscroll_distance;
3117 if (leftmost_frame > max_frames - autoscroll_distance) {
3118 new_frame = max_frames;
3120 new_frame = leftmost_frame + autoscroll_distance;
3124 if (new_frame != leftmost_frame) {
3125 reposition_x_origin (new_frame);
3128 if (new_frame == 0 || new_frame == max_frames) {
3135 if (autoscroll_cnt == 1) {
3137 /* connect the timeout so that we get called repeatedly */
3139 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
3140 keep_calling = false;
3142 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
3144 /* after about a while, speed up a bit by changing the timeout interval */
3146 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
3147 keep_calling = false;
3149 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
3151 /* after about another while, speed up some more */
3153 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
3154 keep_calling = false;
3156 } else if (autoscroll_cnt >= 30) {
3158 /* we've been scrolling for a while ... crank it up */
3160 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
3163 return keep_calling;
3167 Editor::start_canvas_autoscroll (int dir)
3173 stop_canvas_autoscroll ();
3175 autoscroll_direction = dir;
3176 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
3179 /* do it right now, which will start the repeated callbacks */
3181 autoscroll_canvas ();
3185 Editor::stop_canvas_autoscroll ()
3187 if (autoscroll_timeout_tag >= 0) {
3188 gtk_timeout_remove (autoscroll_timeout_tag);
3189 autoscroll_timeout_tag = -1;
3194 Editor::convert_drop_to_paths (vector<string>& paths,
3195 GdkDragContext *context,
3198 GtkSelectionData *data,
3206 gchar *tname = gdk_atom_name (data->type);
3208 if (session == 0 || strcmp (tname, "text/plain") != 0) {
3212 /* Parse the "uri-list" format that Nautilus provides,
3213 where each pathname is delimited by \r\n
3216 path = (char *) data->data;
3219 for (int n = 0; n < data->length; ++n) {
3223 if (path[n] == '\r') {
3230 if (path[n] == '\n') {
3231 paths.push_back (spath);
3235 warning << _("incorrectly formatted URI list, ignored")
3243 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
3245 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3247 // cerr << "dropped text was " << *p << endl;
3251 // cerr << "decoded was " << *p << endl;
3253 if ((*p).substr (0,7) == "file://") {
3254 (*p) = (*p).substr (7);
3262 Editor::track_canvas_drag_data_received (GdkDragContext *context,
3265 GtkSelectionData *data,
3270 AudioTimeAxisView* tv;
3272 vector<string> paths;
3275 jack_nframes_t frame;
3277 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
3281 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
3287 track_canvas.c2w( x, y, wx, wy);
3289 ev.type = GDK_BUTTON_RELEASE;
3293 frame = event_frame (&ev, 0, &cy);
3297 if ((tvp = trackview_by_y_position (cy)) == 0) {
3299 /* drop onto canvas background: create a new track */
3301 insert_paths_as_new_tracks (paths, false);
3304 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
3306 /* check that its an audio track, not a bus */
3308 if (tv->get_diskstream()) {
3310 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
3311 insert_sndfile_into (*p, true, tv, frame);
3318 gtk_drag_finish (context, TRUE, FALSE, time);
3322 Editor::new_tempo_section ()
3328 Editor::map_transport_state ()
3330 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
3332 if (session->transport_stopped()) {
3333 have_pending_keyboard_selection = false;
3339 Editor::State::State ()
3341 selection = new Selection;
3344 Editor::State::~State ()
3350 Editor::get_memento () const
3352 State *state = new State;
3354 store_state (*state);
3355 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
3359 Editor::store_state (State& state) const
3361 *state.selection = *selection;
3365 Editor::restore_state (State *state)
3367 if (*selection == *state->selection) {
3371 *selection = *state->selection;
3372 time_selection_changed ();
3373 region_selection_changed ();
3375 /* XXX other selection change handlers? */
3379 Editor::begin_reversible_command (string name)
3382 UndoAction ua = get_memento();
3383 session->begin_reversible_command (name, &ua);
3388 Editor::commit_reversible_command ()
3391 UndoAction ua = get_memento();
3392 session->commit_reversible_command (&ua);
3397 Editor::flush_track_canvas ()
3399 /* I don't think this is necessary, and only causes more problems.
3400 I'm commenting it out
3401 and if the imageframe folks don't have any issues, we can take
3402 out this method entirely
3405 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
3406 //gtk_main_iteration ();
3410 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
3412 if (!clicked_trackview) {
3417 begin_reversible_command (_("set selected trackview"));
3422 if (selection->selected (clicked_trackview)) {
3424 selection->remove (clicked_trackview);
3427 selection->add (clicked_trackview);
3432 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3433 /* no commit necessary */
3437 selection->set (clicked_trackview);
3441 commit_reversible_command ();
3446 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3448 if (!clicked_control_point) {
3453 begin_reversible_command (_("set selected control point"));
3463 commit_reversible_command ();
3468 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3470 if (!clicked_regionview) {
3474 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3480 RouteGroup* group = atv->route().edit_group();
3481 vector<AudioRegionView*> all_equivalent_regions;
3483 if (group && group->is_active()) {
3485 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3487 AudioTimeAxisView* tatv;
3489 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3491 if (tatv->route().edit_group() != group) {
3496 vector<AudioRegion*> results;
3497 AudioRegionView* marv;
3500 if ((ds = tatv->get_diskstream()) == 0) {
3505 if ((pl = ds->playlist()) != 0) {
3506 pl->get_equivalent_regions (clicked_regionview->region,
3510 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3511 if ((marv = tatv->view->find_view (**ir)) != 0) {
3512 all_equivalent_regions.push_back (marv);
3521 all_equivalent_regions.push_back (clicked_regionview);
3525 begin_reversible_command (_("set selected regionview"));
3529 if (clicked_regionview->get_selected()) {
3530 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3531 /* reduce selection down to just the one clicked */
3532 selection->set (clicked_regionview);
3534 selection->remove (clicked_regionview);
3537 selection->add (all_equivalent_regions);
3540 set_selected_track_from_click (add, false, no_track_remove);
3544 // karsten wiese suggested these two lines to make
3545 // a selected region rise to the top. but this
3546 // leads to a mismatch between actual layering
3547 // and visual layering. resolution required ....
3549 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3550 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3552 if (clicked_regionview->get_selected()) {
3553 /* no commit necessary: we are the one selected. */
3558 selection->set (all_equivalent_regions);
3559 set_selected_track_from_click (add, false, false);
3563 commit_reversible_command () ;
3567 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3569 vector<AudioRegionView*> all_equivalent_regions;
3570 AudioRegion* region;
3572 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3576 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3578 AudioTimeAxisView* tatv;
3580 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3583 vector<AudioRegion*> results;
3584 AudioRegionView* marv;
3587 if ((ds = tatv->get_diskstream()) == 0) {
3592 if ((pl = ds->playlist()) != 0) {
3593 pl->get_region_list_equivalent_regions (*region, results);
3596 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3597 if ((marv = tatv->view->find_view (**ir)) != 0) {
3598 all_equivalent_regions.push_back (marv);
3605 begin_reversible_command (_("set selected regions"));
3609 selection->add (all_equivalent_regions);
3613 selection->set (all_equivalent_regions);
3616 commit_reversible_command () ;
3620 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3622 AudioRegionView* rv;
3625 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3629 if ((rv = sv->find_view (*ar)) == 0) {
3633 /* don't reset the selection if its something other than
3634 a single other region.
3637 if (selection->audio_regions.size() > 1) {
3641 begin_reversible_command (_("set selected regions"));
3643 selection->set (rv);
3645 commit_reversible_command () ;
3651 Editor::set_edit_group_solo (Route& route, bool yn)
3653 RouteGroup *edit_group;
3655 if ((edit_group = route.edit_group()) != 0) {
3656 edit_group->apply (&Route::set_solo, yn, this);
3658 route.set_solo (yn, this);
3663 Editor::set_edit_group_mute (Route& route, bool yn)
3665 RouteGroup *edit_group = 0;
3667 if ((edit_group == route.edit_group()) != 0) {
3668 edit_group->apply (&Route::set_mute, yn, this);
3670 route.set_mute (yn, this);
3675 Editor::set_edit_menu (Menu& menu)
3678 edit_menu->map_.connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3682 Editor::edit_menu_map_handler ()
3684 using namespace Menu_Helpers;
3685 MenuList& edit_items = edit_menu->items();
3688 /* Nuke all the old items */
3690 edit_items.clear ();
3696 if (session->undo_depth() == 0) {
3699 label = string_compose(_("Undo (%1)"), session->next_undo());
3702 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3704 if (session->undo_depth() == 0) {
3705 edit_items.back().set_sensitive (false);
3708 if (session->redo_depth() == 0) {
3711 label = string_compose(_("Redo (%1)"), session->next_redo());
3714 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3715 if (session->redo_depth() == 0) {
3716 edit_items.back().set_sensitive (false);
3719 vector<MenuItem*> mitems;
3721 edit_items.push_back (SeparatorElem());
3722 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3723 mitems.push_back (&edit_items.back());
3724 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3725 mitems.push_back (&edit_items.back());
3726 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3727 mitems.push_back (&edit_items.back());
3728 edit_items.push_back (SeparatorElem());
3729 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3730 mitems.push_back (&edit_items.back());
3731 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3732 mitems.push_back (&edit_items.back());
3733 edit_items.push_back (SeparatorElem());
3735 if (selection->empty()) {
3736 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3737 (*i)->set_sensitive (false);
3741 Menu* import_menu = manage (new Menu());
3742 import_menu->set_name ("ArdourContextMenu");
3743 MenuList& import_items = import_menu->items();
3745 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3746 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3748 Menu* embed_menu = manage (new Menu());
3749 embed_menu->set_name ("ArdourContextMenu");
3750 MenuList& embed_items = embed_menu->items();
3752 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3753 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3755 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3756 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3757 edit_items.push_back (SeparatorElem());
3759 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3760 if (!session->have_captured()) {
3761 edit_items.back().set_sensitive (false);
3766 Editor::duplicate_dialog (bool dup_region)
3769 if (clicked_regionview == 0) {
3773 if (selection->time.length() == 0) {
3778 ArdourDialog win ("duplicate dialog");
3780 Label label (_("Duplicate how many times?"));
3783 Button ok_button (_("OK"));
3784 Button cancel_button (_("Cancel"));
3787 button_box.set_spacing (7);
3788 set_size_request_to_display_given_text (ok_button, _("Cancel"), 20, 15); // this is cancel on purpose
3789 set_size_request_to_display_given_text (cancel_button, _("Cancel"), 20, 15);
3790 button_box.pack_end (ok_button, false, false);
3791 button_box.pack_end (cancel_button, false, false);
3793 hbox.set_spacing (5);
3794 hbox.pack_start (label);
3795 hbox.pack_start (entry, true, true);
3797 vbox.set_spacing (5);
3798 vbox.set_border_width (5);
3799 vbox.pack_start (hbox);
3800 vbox.pack_start (button_box);
3803 win.set_position (Gtk::WIN_POS_MOUSE);
3806 ok_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3807 entry.signal_activate().connect (bind (mem_fun (win, &ArdourDialog::stop), 0));
3808 cancel_button.signal_clicked().connect (bind (mem_fun (win, &ArdourDialog::stop), 1));
3810 entry.signal_focus_in_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_in_event));
3811 entry.signal_focus_out_event().connect (sigc::ptr_fun (ARDOUR_UI::generic_focus_out_event));
3813 entry.set_text ("1");
3814 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3815 entry.select_region (0, entry.get_text_length());
3817 win.set_position (Gtk::WIN_POS_MOUSE);
3819 win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3821 entry.grab_focus ();
3825 if (win.run_status() != 0) {
3829 string text = entry.get_text();
3832 if (sscanf (text.c_str(), "%f", ×) == 1) {
3834 AudioRegionSelection regions;
3835 regions.add (clicked_regionview);
3836 duplicate_some_regions (regions, times);
3838 duplicate_selection (times);
3844 Editor::show_verbose_canvas_cursor ()
3846 verbose_canvas_cursor->raise_to_top();
3847 verbose_canvas_cursor->show();
3848 verbose_cursor_visible = true;
3852 Editor::hide_verbose_canvas_cursor ()
3854 verbose_canvas_cursor->hide();
3855 verbose_cursor_visible = false;
3859 Editor::set_verbose_canvas_cursor (string txt, double x, double y)
3861 /* XXX get origin of canvas relative to root window,
3862 add x and y and check compared to gdk_screen_{width,height}
3864 verbose_canvas_cursor->set_property("text", txt.c_str());
3865 verbose_canvas_cursor->set_property("x", x);
3866 verbose_canvas_cursor->set_property("y", y);
3870 Editor::set_verbose_canvas_cursor_text (string txt)
3872 verbose_canvas_cursor->set_property("text", txt.c_str());
3876 Editor::edit_mode_selection_done (GdkEventAny *ev)
3882 string choice = edit_mode_selector.get_active_text();
3883 EditMode mode = Slide;
3885 if (choice == _("Splice")) {
3887 } else if (choice == _("Slide")) {
3891 session->set_edit_mode (mode);
3897 Editor::snap_type_selection_done (GdkEventAny *ev)
3903 string choice = snap_type_selector.get_active_text();
3904 SnapType snaptype = SnapToFrame;
3906 if (choice == _("Beats/3")) {
3907 snaptype = SnapToAThirdBeat;
3908 } else if (choice == _("Beats/4")) {
3909 snaptype = SnapToAQuarterBeat;
3910 } else if (choice == _("Beats/8")) {
3911 snaptype = SnapToAEighthBeat;
3912 } else if (choice == _("Beats/16")) {
3913 snaptype = SnapToASixteenthBeat;
3914 } else if (choice == _("Beats/32")) {
3915 snaptype = SnapToAThirtysecondBeat;
3916 } else if (choice == _("Beats")) {
3917 snaptype = SnapToBeat;
3918 } else if (choice == _("Bars")) {
3919 snaptype = SnapToBar;
3920 } else if (choice == _("Marks")) {
3921 snaptype = SnapToMark;
3922 } else if (choice == _("Edit Cursor")) {
3923 snaptype = SnapToEditCursor;
3924 } else if (choice == _("Region starts")) {
3925 snaptype = SnapToRegionStart;
3926 } else if (choice == _("Region ends")) {
3927 snaptype = SnapToRegionEnd;
3928 } else if (choice == _("Region bounds")) {
3929 snaptype = SnapToRegionBoundary;
3930 } else if (choice == _("Region syncs")) {
3931 snaptype = SnapToRegionSync;
3932 } else if (choice == _("CD Frames")) {
3933 snaptype = SnapToCDFrame;
3934 } else if (choice == _("SMPTE Frames")) {
3935 snaptype = SnapToSMPTEFrame;
3936 } else if (choice == _("SMPTE Seconds")) {
3937 snaptype = SnapToSMPTESeconds;
3938 } else if (choice == _("SMPTE Minutes")) {
3939 snaptype = SnapToSMPTEMinutes;
3940 } else if (choice == _("Seconds")) {
3941 snaptype = SnapToSeconds;
3942 } else if (choice == _("Minutes")) {
3943 snaptype = SnapToMinutes;
3944 } else if (choice == _("None")) {
3945 snaptype = SnapToFrame;
3948 set_snap_to (snaptype);
3954 Editor::snap_mode_selection_done (GdkEventAny *ev)
3956 if(session == 0) return FALSE;
3958 string choice = snap_mode_selector.get_active_text();
3959 SnapMode mode = SnapNormal;
3961 if (choice == _("Normal")) {
3963 } else if (choice == _("Magnetic")) {
3964 mode = SnapMagnetic;
3967 set_snap_mode (mode);
3973 Editor::zoom_focus_selection_done (GdkEventAny *ev)
3979 string choice = zoom_focus_selector.get_active_text();
3980 ZoomFocus focus_type = ZoomFocusLeft;
3982 if (choice == _("Left")) {
3983 focus_type = ZoomFocusLeft;
3984 } else if (choice == _("Right")) {
3985 focus_type = ZoomFocusRight;
3986 } else if (choice == _("Center")) {
3987 focus_type = ZoomFocusCenter;
3988 } else if (choice == _("Playhead")) {
3989 focus_type = ZoomFocusPlayhead;
3990 } else if (choice == _("Edit Cursor")) {
3991 focus_type = ZoomFocusEdit;
3994 set_zoom_focus (focus_type);
4000 Editor::edit_controls_button_release (GdkEventButton* ev)
4002 if (Keyboard::is_context_menu_event (ev)) {
4003 ARDOUR_UI::instance()->add_route ();
4009 Editor::track_selection_changed ()
4011 switch (selection->tracks.size()){
4015 set_selected_mixer_strip (*(selection->tracks.front()));
4019 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4020 (*i)->set_selected (false);
4021 if (mouse_mode == MouseRange) {
4022 (*i)->hide_selection ();
4026 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4027 (*i)->set_selected (true);
4028 if (mouse_mode == MouseRange) {
4029 (*i)->show_selection (selection->time);
4035 Editor::time_selection_changed ()
4037 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4038 (*i)->hide_selection ();
4041 if (selection->tracks.empty()) {
4042 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4043 (*i)->show_selection (selection->time);
4046 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4047 (*i)->show_selection (selection->time);
4053 Editor::region_selection_changed ()
4055 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4056 (*i)->set_selected_regionviews (selection->audio_regions);
4061 Editor::point_selection_changed ()
4063 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4064 (*i)->set_selected_points (selection->points);
4069 Editor::run_sub_event_loop ()
4071 Keyboard::the_keyboard().allow_focus (true);
4072 sub_event_loop_status = 0;
4077 Editor::finish_sub_event_loop (int status)
4080 Keyboard::the_keyboard().allow_focus (false);
4081 sub_event_loop_status = status;
4085 Editor::finish_sub_event_loop_on_delete (GdkEventAny *ignored, int32_t status)
4087 finish_sub_event_loop (status);
4092 Editor::mouse_select_button_release (GdkEventButton* ev)
4094 /* this handles just right-clicks */
4096 if (ev->button != 3) {
4103 Editor::TrackViewList *
4104 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
4107 TrackViewList::iterator i;
4109 v = new TrackViewList;
4111 if (track == 0 && group == 0) {
4115 for (i = track_views.begin(); i != track_views.end (); ++i) {
4119 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
4121 /* just the view for this track
4124 v->push_back (track);
4128 /* views for all tracks in the edit group */
4130 for (i = track_views.begin(); i != track_views.end (); ++i) {
4132 if (group == 0 || (*i)->edit_group() == group) {
4142 Editor::set_zoom_focus (ZoomFocus f)
4144 if (zoom_focus != f) {
4146 vector<string> txt = internationalize (zoom_focus_strings);
4147 zoom_focus_selector.set_active_text (txt[(int)f]);
4148 ZoomFocusChanged (); /* EMIT_SIGNAL */
4155 Editor::ensure_float (Window& win)
4157 win.set_transient_for (*this);
4161 Editor::pane_allocation_handler (GtkAllocation *alloc, Gtk::Paned* which)
4163 /* recover or initialize pane positions. do this here rather than earlier because
4164 we don't want the positions to change the child allocations, which they seem to do.
4170 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
4172 static int32_t done[4] = { 0, 0, 0, 0 };
4175 if ((geometry = find_named_node (*node, "geometry")) == 0) {
4176 width = default_width;
4177 height = default_height;
4179 width = atoi(geometry->property("x_size")->value());
4180 height = atoi(geometry->property("y_size")->value());
4183 if (which == static_cast<Gtk::Paned*> (&track_list_canvas_pane)) {
4189 if (!geometry || (prop = geometry->property("track_list_canvas_pane_pos")) == 0) {
4191 snprintf (buf, sizeof(buf), "%d", pos);
4193 pos = atoi (prop->value());
4196 if ((done[0] = GTK_WIDGET(track_list_canvas_pane.gobj())->allocation.width > pos)) {
4197 track_list_canvas_pane.set_position (pos);
4200 } else if (which == static_cast<Gtk::Paned*> (&canvas_region_list_pane)) {
4206 if (!geometry || (prop = geometry->property("canvas_region_list_pane_pos")) == 0) {
4207 pos = width - (95 * 2);
4208 snprintf (buf, sizeof(buf), "%d", pos);
4210 pos = atoi (prop->value());
4213 if ((done[1] = GTK_WIDGET(canvas_region_list_pane.gobj())->allocation.width > pos)) {
4214 canvas_region_list_pane.set_position (pos);
4217 } else if (which == static_cast<Gtk::Paned*> (&route_group_vpane)) {
4223 if (!geometry || (prop = geometry->property("route_group_pane_pos")) == 0) {
4224 pos = width - (95 * 2);
4225 snprintf (buf, sizeof(buf), "%d", pos);
4227 pos = atoi (prop->value());
4230 if ((done[2] = GTK_WIDGET(route_group_vpane.gobj())->allocation.height > pos)) {
4231 route_group_vpane.set_position (pos);
4234 } else if (which == static_cast<Gtk::Paned*> (®ion_selection_vpane)) {
4240 if (!geometry || (prop = geometry->property("region_selection_pane_pos")) == 0) {
4241 pos = width - (95 * 2);
4242 snprintf (buf, sizeof(buf), "%d", pos);
4244 pos = atoi (prop->value());
4247 if ((done[3] = GTK_WIDGET(region_selection_vpane.gobj())->allocation.height > pos)) {
4248 region_selection_vpane.set_position (pos);
4254 Editor::detach_tearoff (Gtk::Box* b, Gtk::Widget* w)
4256 if (tools_tearoff->torn_off() &&
4257 mouse_mode_tearoff->torn_off()) {
4258 top_hbox.remove (toolbar_frame);
4261 ensure_float (*w->get_toplevel());
4265 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Widget* w, int32_t n)
4267 if (toolbar_frame.get_parent() == 0) {
4268 top_hbox.pack_end (toolbar_frame);
4273 Editor::set_show_measures (bool yn)
4275 if (_show_measures != yn) {
4278 if ((_show_measures = yn) == true) {
4281 DisplayControlChanged (ShowMeasures);
4287 Editor::set_follow_playhead (bool yn)
4289 if (_follow_playhead != yn) {
4290 if ((_follow_playhead = yn) == true) {
4292 update_current_screen ();
4294 DisplayControlChanged (FollowPlayhead);
4300 Editor::toggle_xfade_active (Crossfade* xfade)
4302 xfade->set_active (!xfade->active());
4306 Editor::toggle_xfade_length (Crossfade* xfade)
4308 xfade->set_follow_overlap (!xfade->following_overlap());
4312 Editor::edit_xfade (Crossfade* xfade)
4314 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
4318 cew.ok_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 1));
4319 cew.cancel_button.signal_clicked().connect (bind (mem_fun (cew, &ArdourDialog::stop), 0));
4320 cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
4324 if (cew.run_status() == 1) {
4326 xfade->StateChanged (Change (~0));
4331 Editor::playlist_selector () const
4333 return *_playlist_selector;
4337 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
4341 ret = nudge_clock.current_duration (pos);
4342 next = ret + 1; /* XXXX fix me */
4348 Editor::end_location_changed (Location* location)
4350 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
4351 track_canvas_scroller.get_hadjustment()->set_upper (location->end() / frames_per_unit);
4355 Editor::playlist_deletion_dialog (Playlist* pl)
4357 ArdourDialog dialog ("playlist deletion dialog");
4358 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4359 "If left alone, no audio files used by it will be cleaned.\n"
4360 "If deleted, audio files used by it alone by will cleaned."),
4363 Button del_button (_("Delete playlist"));
4364 Button keep_button (_("Keep playlist"));
4365 Button abort_button (_("Cancel cleanup"));
4368 button_box.set_spacing (7);
4369 button_box.set_homogeneous (true);
4370 button_box.pack_end (del_button, false, false);
4371 button_box.pack_end (keep_button, false, false);
4372 button_box.pack_end (abort_button, false, false);
4374 vbox.set_spacing (5);
4375 vbox.set_border_width (5);
4376 vbox.pack_start (label);
4377 vbox.pack_start (button_box);
4380 dialog.set_position (Gtk::WIN_POS_CENTER);
4383 del_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 0));
4384 keep_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 1));
4385 abort_button.signal_clicked().connect (bind (mem_fun (dialog, &ArdourDialog::stop), 2));
4388 dialog.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
4392 switch (dialog.run_status()) {
4394 /* keep the playlist */
4398 /* delete the playlist */
4406 /* keep the playlist */
4412 Editor::audio_region_selection_covers (jack_nframes_t where)
4414 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
4415 if ((*a)->region.covers (where)) {
4424 Editor::prepare_for_cleanup ()
4426 cut_buffer->clear_audio_regions ();
4427 cut_buffer->clear_playlists ();
4429 selection->clear_audio_regions ();
4430 selection->clear_playlists ();
4434 Editor::init_colormap ()
4436 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
4437 pair<ColorID,int> newpair;
4439 newpair.first = (ColorID) x;
4440 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
4441 color_map.insert (newpair);
4446 Editor::transport_loop_location()
4449 return session->locations()->auto_loop_location();
4456 Editor::transport_punch_location()
4459 return session->locations()->auto_punch_location();