2 Copyright (C) 2000-2009 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.
20 /* Note: public Editor methods are documented in public_editor.h */
30 #include "ardour_ui.h"
32 * ardour_ui.h include was moved to the top of the list
33 * due to a conflicting definition of 'Style' between
34 * Apple's MacTypes.h and BarController.
37 #include <boost/none.hpp>
39 #include <sigc++/bind.h>
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
48 #include "pbd/timersub.h"
50 #include <glibmm/miscutils.h>
51 #include <glibmm/uriutils.h>
52 #include <gtkmm/image.h>
53 #include <gdkmm/color.h>
54 #include <gdkmm/bitmap.h>
56 #include <gtkmm/menu.h>
57 #include <gtkmm/menuitem.h>
59 #include "gtkmm2ext/bindings.h"
60 #include "gtkmm2ext/grouped_buttons.h"
61 #include "gtkmm2ext/gtk_ui.h"
62 #include "gtkmm2ext/tearoff.h"
63 #include "gtkmm2ext/utils.h"
64 #include "gtkmm2ext/window_title.h"
65 #include "gtkmm2ext/choice.h"
66 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
68 #include "ardour/audio_track.h"
69 #include "ardour/audioengine.h"
70 #include "ardour/audioregion.h"
71 #include "ardour/location.h"
72 #include "ardour/profile.h"
73 #include "ardour/route_group.h"
74 #include "ardour/session_playlists.h"
75 #include "ardour/tempo.h"
76 #include "ardour/utils.h"
78 #include "canvas/debug.h"
79 #include "canvas/text.h"
81 #include "control_protocol/control_protocol.h"
84 #include "analysis_window.h"
85 #include "audio_clock.h"
86 #include "audio_region_view.h"
87 #include "audio_streamview.h"
88 #include "audio_time_axis.h"
89 #include "automation_time_axis.h"
90 #include "bundle_manager.h"
91 #include "crossfade_edit.h"
95 #include "editor_cursors.h"
96 #include "editor_drag.h"
97 #include "editor_group_tabs.h"
98 #include "editor_locations.h"
99 #include "editor_regions.h"
100 #include "editor_route_groups.h"
101 #include "editor_routes.h"
102 #include "editor_snapshots.h"
103 #include "editor_summary.h"
104 #include "global_port_matrix.h"
105 #include "gui_object.h"
106 #include "gui_thread.h"
107 #include "keyboard.h"
109 #include "midi_region_view.h"
110 #include "midi_time_axis.h"
111 #include "mixer_strip.h"
112 #include "mixer_ui.h"
113 #include "mouse_cursors.h"
114 #include "note_base.h"
115 #include "playlist_selector.h"
116 #include "public_editor.h"
117 #include "region_layering_order_editor.h"
118 #include "rgb_macros.h"
119 #include "rhythm_ferret.h"
120 #include "selection.h"
122 #include "tempo_lines.h"
123 #include "time_axis_view.h"
126 #include "verbose_cursor.h"
131 using namespace ARDOUR;
132 using namespace ARDOUR_UI_UTILS;
135 using namespace Glib;
136 using namespace Gtkmm2ext;
137 using namespace Editing;
139 using PBD::internationalize;
141 using Gtkmm2ext::Keyboard;
143 double Editor::timebar_height = 15.0;
145 static const gchar *_snap_type_strings[] = {
179 static const gchar *_snap_mode_strings[] = {
186 static const gchar *_edit_point_strings[] = {
193 static const gchar *_edit_mode_strings[] = {
201 static const gchar *_zoom_focus_strings[] = {
211 #ifdef USE_RUBBERBAND
212 static const gchar *_rb_opt_strings[] = {
215 N_("Balanced multitimbral mixture"),
216 N_("Unpitched percussion with stable notes"),
217 N_("Crisp monophonic instrumental"),
218 N_("Unpitched solo percussion"),
219 N_("Resample without preserving pitch"),
224 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
227 pane_size_watcher (Paned* pane)
229 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
233 Quartz: impossible to access
235 so stop that by preventing it from ever getting too narrow. 35
236 pixels is basically a rough guess at the tab width.
241 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
243 gint pos = pane->get_position ();
245 if (pos > max_width_of_lhs) {
246 pane->set_position (max_width_of_lhs);
251 : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
253 , _mouse_changed_selection (false)
254 /* time display buttons */
255 , minsec_label (_("Mins:Secs"))
256 , bbt_label (_("Bars:Beats"))
257 , timecode_label (_("Timecode"))
258 , samples_label (_("Samples"))
259 , tempo_label (_("Tempo"))
260 , meter_label (_("Meter"))
261 , mark_label (_("Location Markers"))
262 , range_mark_label (_("Range Markers"))
263 , transport_mark_label (_("Loop/Punch Ranges"))
264 , cd_mark_label (_("CD Markers"))
265 , videotl_label (_("Video Timeline"))
266 , edit_packer (4, 4, true)
268 /* the values here don't matter: layout widgets
269 reset them as needed.
272 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
273 , horizontal_adjustment (0.0, 0.0, 1e16)
274 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
276 , controls_layout (unused_adjustment, vertical_adjustment)
278 /* tool bar related */
280 , toolbar_selection_clock_table (2,3)
281 , _mouse_mode_tearoff (0)
282 , automation_mode_button (_("mode"))
286 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
287 , selection_op_cmd_depth (0)
288 , selection_op_history_it (0)
292 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
293 , meters_running(false)
294 , _pending_locate_request (false)
295 , _pending_initial_locate (false)
296 , _last_cut_copy_source_track (0)
298 , _region_selection_change_updates_region_list (true)
299 , _following_mixer_selection (false)
300 , _control_point_toggled_on_press (false)
301 , _stepping_axis_view (0)
305 /* we are a singleton */
307 PublicEditor::_instance = this;
311 selection = new Selection (this);
312 cut_buffer = new Selection (this);
313 _selection_memento = new SelectionMemento ();
314 selection_op_history.clear();
317 clicked_regionview = 0;
318 clicked_axisview = 0;
319 clicked_routeview = 0;
320 clicked_control_point = 0;
321 last_update_frame = 0;
324 _drags = new DragManager (this);
327 current_mixer_strip = 0;
330 snap_type_strings = I18N (_snap_type_strings);
331 snap_mode_strings = I18N (_snap_mode_strings);
332 zoom_focus_strings = I18N (_zoom_focus_strings);
333 edit_mode_strings = I18N (_edit_mode_strings);
334 edit_point_strings = I18N (_edit_point_strings);
335 #ifdef USE_RUBBERBAND
336 rb_opt_strings = I18N (_rb_opt_strings);
340 build_edit_mode_menu();
341 build_zoom_focus_menu();
342 build_track_count_menu();
343 build_snap_mode_menu();
344 build_snap_type_menu();
345 build_edit_point_menu();
347 snap_threshold = 5.0;
348 bbt_beat_subdivision = 4;
349 _visible_canvas_width = 0;
350 _visible_canvas_height = 0;
351 autoscroll_horizontal_allowed = false;
352 autoscroll_vertical_allowed = false;
357 current_interthread_info = 0;
358 _show_measures = true;
360 show_gain_after_trim = false;
362 have_pending_keyboard_selection = false;
363 _follow_playhead = true;
364 _stationary_playhead = false;
365 editor_ruler_menu = 0;
366 no_ruler_shown_update = false;
368 range_marker_menu = 0;
369 marker_menu_item = 0;
370 tempo_or_meter_marker_menu = 0;
371 transport_marker_menu = 0;
372 new_transport_marker_menu = 0;
373 editor_mixer_strip_width = Wide;
374 show_editor_mixer_when_tracks_arrive = false;
375 region_edit_menu_split_multichannel_item = 0;
376 region_edit_menu_split_item = 0;
379 current_stepping_trackview = 0;
381 entered_regionview = 0;
383 clear_entered_track = false;
386 button_release_can_deselect = true;
387 _dragging_playhead = false;
388 _dragging_edit_point = false;
389 select_new_marker = false;
391 layering_order_editor = 0;
392 no_save_visual = false;
394 within_track_canvas = false;
396 scrubbing_direction = 0;
400 location_marker_color = ARDOUR_UI::config()->color ("location marker");
401 location_range_color = ARDOUR_UI::config()->color ("location range");
402 location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker");
403 location_loop_color = ARDOUR_UI::config()->color ("location loop");
404 location_punch_color = ARDOUR_UI::config()->color ("location punch");
406 zoom_focus = ZoomFocusLeft;
407 _edit_point = EditAtMouse;
408 _visible_track_count = -1;
410 samples_per_pixel = 2048; /* too early to use reset_zoom () */
412 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::config()->get_font_scale() / 102400.));
413 TimeAxisView::setup_sizes ();
414 Marker::setup_sizes (timebar_height);
416 _scroll_callbacks = 0;
418 bbt_label.set_name ("EditorRulerLabel");
419 bbt_label.set_size_request (-1, (int)timebar_height);
420 bbt_label.set_alignment (1.0, 0.5);
421 bbt_label.set_padding (5,0);
423 bbt_label.set_no_show_all();
424 minsec_label.set_name ("EditorRulerLabel");
425 minsec_label.set_size_request (-1, (int)timebar_height);
426 minsec_label.set_alignment (1.0, 0.5);
427 minsec_label.set_padding (5,0);
428 minsec_label.hide ();
429 minsec_label.set_no_show_all();
430 timecode_label.set_name ("EditorRulerLabel");
431 timecode_label.set_size_request (-1, (int)timebar_height);
432 timecode_label.set_alignment (1.0, 0.5);
433 timecode_label.set_padding (5,0);
434 timecode_label.hide ();
435 timecode_label.set_no_show_all();
436 samples_label.set_name ("EditorRulerLabel");
437 samples_label.set_size_request (-1, (int)timebar_height);
438 samples_label.set_alignment (1.0, 0.5);
439 samples_label.set_padding (5,0);
440 samples_label.hide ();
441 samples_label.set_no_show_all();
443 tempo_label.set_name ("EditorRulerLabel");
444 tempo_label.set_size_request (-1, (int)timebar_height);
445 tempo_label.set_alignment (1.0, 0.5);
446 tempo_label.set_padding (5,0);
448 tempo_label.set_no_show_all();
450 meter_label.set_name ("EditorRulerLabel");
451 meter_label.set_size_request (-1, (int)timebar_height);
452 meter_label.set_alignment (1.0, 0.5);
453 meter_label.set_padding (5,0);
455 meter_label.set_no_show_all();
457 if (Profile->get_trx()) {
458 mark_label.set_text (_("Markers"));
460 mark_label.set_name ("EditorRulerLabel");
461 mark_label.set_size_request (-1, (int)timebar_height);
462 mark_label.set_alignment (1.0, 0.5);
463 mark_label.set_padding (5,0);
465 mark_label.set_no_show_all();
467 cd_mark_label.set_name ("EditorRulerLabel");
468 cd_mark_label.set_size_request (-1, (int)timebar_height);
469 cd_mark_label.set_alignment (1.0, 0.5);
470 cd_mark_label.set_padding (5,0);
471 cd_mark_label.hide();
472 cd_mark_label.set_no_show_all();
474 videotl_bar_height = 4;
475 videotl_label.set_name ("EditorRulerLabel");
476 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
477 videotl_label.set_alignment (1.0, 0.5);
478 videotl_label.set_padding (5,0);
479 videotl_label.hide();
480 videotl_label.set_no_show_all();
482 range_mark_label.set_name ("EditorRulerLabel");
483 range_mark_label.set_size_request (-1, (int)timebar_height);
484 range_mark_label.set_alignment (1.0, 0.5);
485 range_mark_label.set_padding (5,0);
486 range_mark_label.hide();
487 range_mark_label.set_no_show_all();
489 transport_mark_label.set_name ("EditorRulerLabel");
490 transport_mark_label.set_size_request (-1, (int)timebar_height);
491 transport_mark_label.set_alignment (1.0, 0.5);
492 transport_mark_label.set_padding (5,0);
493 transport_mark_label.hide();
494 transport_mark_label.set_no_show_all();
496 initialize_canvas ();
498 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
500 _summary = new EditorSummary (this);
502 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
503 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
505 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
507 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
508 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
510 edit_controls_vbox.set_spacing (0);
511 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
512 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
514 HBox* h = manage (new HBox);
515 _group_tabs = new EditorGroupTabs (this);
516 if (!ARDOUR::Profile->get_trx()) {
517 h->pack_start (*_group_tabs, PACK_SHRINK);
519 h->pack_start (edit_controls_vbox);
520 controls_layout.add (*h);
522 controls_layout.set_name ("EditControlsBase");
523 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
524 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
525 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
527 _cursors = new MouseCursors;
528 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
529 cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
531 /* Push default cursor to ever-present bottom of cursor stack. */
532 push_canvas_cursor(_cursors->grabber);
534 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
536 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
537 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
538 pad_line_1->set_outline_color (0xFF0000FF);
544 edit_packer.set_col_spacings (0);
545 edit_packer.set_row_spacings (0);
546 edit_packer.set_homogeneous (false);
547 edit_packer.set_border_width (0);
548 edit_packer.set_name ("EditorWindow");
550 time_bars_event_box.add (time_bars_vbox);
551 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
552 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
554 /* labels for the time bars */
555 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
557 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
559 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
561 bottom_hbox.set_border_width (2);
562 bottom_hbox.set_spacing (3);
564 _route_groups = new EditorRouteGroups (this);
565 _routes = new EditorRoutes (this);
566 _regions = new EditorRegions (this);
567 _snapshots = new EditorSnapshots (this);
568 _locations = new EditorLocations (this);
570 /* these are static location signals */
572 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
573 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
574 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
576 add_notebook_page (_("Regions"), _regions->widget ());
577 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
578 add_notebook_page (_("Snapshots"), _snapshots->widget ());
579 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
580 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
582 _the_notebook.set_show_tabs (true);
583 _the_notebook.set_scrollable (true);
584 _the_notebook.popup_disable ();
585 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
586 _the_notebook.show_all ();
588 _notebook_shrunk = false;
590 editor_summary_pane.pack1(edit_packer);
592 Button* summary_arrows_left_left = manage (new Button);
593 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
594 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
595 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
597 Button* summary_arrows_left_right = manage (new Button);
598 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
599 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
600 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
602 VBox* summary_arrows_left = manage (new VBox);
603 summary_arrows_left->pack_start (*summary_arrows_left_left);
604 summary_arrows_left->pack_start (*summary_arrows_left_right);
606 Button* summary_arrows_right_up = manage (new Button);
607 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
608 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
609 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
611 Button* summary_arrows_right_down = manage (new Button);
612 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
613 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
614 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
616 VBox* summary_arrows_right = manage (new VBox);
617 summary_arrows_right->pack_start (*summary_arrows_right_up);
618 summary_arrows_right->pack_start (*summary_arrows_right_down);
620 Frame* summary_frame = manage (new Frame);
621 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
623 summary_frame->add (*_summary);
624 summary_frame->show ();
626 _summary_hbox.pack_start (*summary_arrows_left, false, false);
627 _summary_hbox.pack_start (*summary_frame, true, true);
628 _summary_hbox.pack_start (*summary_arrows_right, false, false);
630 if (!ARDOUR::Profile->get_trx()) {
631 editor_summary_pane.pack2 (_summary_hbox);
634 edit_pane.pack1 (editor_summary_pane, true, true);
635 if (!ARDOUR::Profile->get_trx()) {
636 edit_pane.pack2 (_the_notebook, false, true);
639 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
641 /* XXX: editor_summary_pane might need similar to the edit_pane */
643 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
645 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
646 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
648 top_hbox.pack_start (toolbar_frame);
650 HBox *hbox = manage (new HBox);
651 hbox->pack_start (edit_pane, true, true);
653 global_vpacker.pack_start (top_hbox, false, false);
654 global_vpacker.pack_start (*hbox, true, true);
656 global_hpacker.pack_start (global_vpacker, true, true);
658 set_name ("EditorWindow");
659 add_accel_group (ActionManager::ui_manager->get_accel_group());
661 status_bar_hpacker.show ();
663 vpacker.pack_end (status_bar_hpacker, false, false);
664 vpacker.pack_end (global_hpacker, true, true);
666 /* register actions now so that set_state() can find them and set toggles/checks etc */
669 /* when we start using our own keybinding system for the editor, this
670 * will be uncommented
676 set_zoom_focus (zoom_focus);
677 set_visible_track_count (_visible_track_count);
678 _snap_type = SnapToBeat;
679 set_snap_to (_snap_type);
680 _snap_mode = SnapOff;
681 set_snap_mode (_snap_mode);
682 set_mouse_mode (MouseObject, true);
683 pre_internal_snap_type = _snap_type;
684 pre_internal_snap_mode = _snap_mode;
685 internal_snap_type = _snap_type;
686 internal_snap_mode = _snap_mode;
687 set_edit_point_preference (EditAtMouse, true);
689 _playlist_selector = new PlaylistSelector();
690 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
692 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
696 nudge_forward_button.set_name ("nudge button");
697 nudge_forward_button.set_image(::get_icon("nudge_right"));
699 nudge_backward_button.set_name ("nudge button");
700 nudge_backward_button.set_image(::get_icon("nudge_left"));
702 fade_context_menu.set_name ("ArdourContextMenu");
704 /* icons, titles, WM stuff */
706 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
707 Glib::RefPtr<Gdk::Pixbuf> icon;
709 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
710 window_icons.push_back (icon);
712 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
713 window_icons.push_back (icon);
715 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
716 window_icons.push_back (icon);
718 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
719 window_icons.push_back (icon);
721 if (!window_icons.empty()) {
722 // set_icon_list (window_icons);
723 set_default_icon_list (window_icons);
726 WindowTitle title(Glib::get_application_name());
727 title += _("Editor");
728 set_title (title.get_string());
729 set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
732 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
734 signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
735 signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
737 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
739 /* allow external control surfaces/protocols to do various things */
741 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
742 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
743 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
744 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
745 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
746 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
747 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
748 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
749 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
750 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
751 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
752 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
753 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
754 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
756 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
757 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
758 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
759 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
760 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
762 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
764 /* problematic: has to return a value and thus cannot be x-thread */
766 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
768 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
769 ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
771 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
773 _ignore_region_action = false;
774 _last_region_menu_was_main = false;
775 _popup_region_menu_item = 0;
777 _ignore_follow_edits = false;
779 _show_marker_lines = false;
781 /* Button bindings */
783 button_bindings = new Bindings;
785 XMLNode* node = button_settings();
787 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
788 button_bindings->load (**i);
794 /* grab current parameter state */
795 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
796 ARDOUR_UI::config()->map_parameters (pc);
798 setup_fade_images ();
805 delete button_bindings;
807 delete _route_groups;
808 delete _track_canvas_viewport;
814 Editor::button_settings () const
816 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
817 XMLNode* node = find_named_node (*settings, X_("Buttons"));
820 node = new XMLNode (X_("Buttons"));
827 Editor::add_toplevel_menu (Container& cont)
829 vpacker.pack_start (cont, false, false);
834 Editor::add_transport_frame (Container& cont)
836 if(ARDOUR::Profile->get_mixbus()) {
837 global_vpacker.pack_start (cont, false, false);
838 global_vpacker.reorder_child (cont, 0);
841 vpacker.pack_start (cont, false, false);
846 Editor::get_smart_mode () const
848 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
852 Editor::catch_vanishing_regionview (RegionView *rv)
854 /* note: the selection will take care of the vanishing
855 audioregionview by itself.
858 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
862 if (clicked_regionview == rv) {
863 clicked_regionview = 0;
866 if (entered_regionview == rv) {
867 set_entered_regionview (0);
870 if (!_all_region_actions_sensitized) {
871 sensitize_all_region_actions (true);
876 Editor::set_entered_regionview (RegionView* rv)
878 if (rv == entered_regionview) {
882 if (entered_regionview) {
883 entered_regionview->exited ();
886 entered_regionview = rv;
888 if (entered_regionview != 0) {
889 entered_regionview->entered ();
892 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
893 /* This RegionView entry might have changed what region actions
894 are allowed, so sensitize them all in case a key is pressed.
896 sensitize_all_region_actions (true);
901 Editor::set_entered_track (TimeAxisView* tav)
904 entered_track->exited ();
910 entered_track->entered ();
915 Editor::show_window ()
917 if (!is_visible ()) {
921 /* XXX: this is a bit unfortunate; it would probably
922 be nicer if we could just call show () above rather
923 than needing the show_all ()
926 /* re-hide stuff if necessary */
927 editor_list_button_toggled ();
928 parameter_changed ("show-summary");
929 parameter_changed ("show-group-tabs");
930 parameter_changed ("show-zoom-tools");
932 /* now reset all audio_time_axis heights, because widgets might need
938 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
939 tv = (static_cast<TimeAxisView*>(*i));
943 if (current_mixer_strip) {
944 current_mixer_strip->hide_things ();
945 current_mixer_strip->parameter_changed ("mixer-element-visibility");
953 Editor::instant_save ()
955 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
960 _session->add_instant_xml(get_state());
962 Config->add_instant_xml(get_state());
967 Editor::control_vertical_zoom_in_all ()
969 tav_zoom_smooth (false, true);
973 Editor::control_vertical_zoom_out_all ()
975 tav_zoom_smooth (true, true);
979 Editor::control_vertical_zoom_in_selected ()
981 tav_zoom_smooth (false, false);
985 Editor::control_vertical_zoom_out_selected ()
987 tav_zoom_smooth (true, false);
991 Editor::control_view (uint32_t view)
993 goto_visual_state (view);
997 Editor::control_unselect ()
999 selection->clear_tracks ();
1003 Editor::control_select (uint32_t rid, Selection::Operation op)
1005 /* handles the (static) signal from the ControlProtocol class that
1006 * requests setting the selected track to a given RID
1013 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1019 TimeAxisView* tav = axis_view_from_route (r);
1023 case Selection::Add:
1024 selection->add (tav);
1026 case Selection::Toggle:
1027 selection->toggle (tav);
1029 case Selection::Extend:
1031 case Selection::Set:
1032 selection->set (tav);
1036 selection->clear_tracks ();
1041 Editor::control_step_tracks_up ()
1043 scroll_tracks_up_line ();
1047 Editor::control_step_tracks_down ()
1049 scroll_tracks_down_line ();
1053 Editor::control_scroll (float fraction)
1055 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1061 double step = fraction * current_page_samples();
1064 _control_scroll_target is an optional<T>
1066 it acts like a pointer to an framepos_t, with
1067 a operator conversion to boolean to check
1068 that it has a value could possibly use
1069 playhead_cursor->current_frame to store the
1070 value and a boolean in the class to know
1071 when it's out of date
1074 if (!_control_scroll_target) {
1075 _control_scroll_target = _session->transport_frame();
1076 _dragging_playhead = true;
1079 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1080 *_control_scroll_target = 0;
1081 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1082 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1084 *_control_scroll_target += (framepos_t) trunc (step);
1087 /* move visuals, we'll catch up with it later */
1089 playhead_cursor->set_position (*_control_scroll_target);
1090 UpdateAllTransportClocks (*_control_scroll_target);
1092 if (*_control_scroll_target > (current_page_samples() / 2)) {
1093 /* try to center PH in window */
1094 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1100 Now we do a timeout to actually bring the session to the right place
1101 according to the playhead. This is to avoid reading disk buffers on every
1102 call to control_scroll, which is driven by ScrollTimeline and therefore
1103 probably by a control surface wheel which can generate lots of events.
1105 /* cancel the existing timeout */
1107 control_scroll_connection.disconnect ();
1109 /* add the next timeout */
1111 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1115 Editor::deferred_control_scroll (framepos_t /*target*/)
1117 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1118 // reset for next stream
1119 _control_scroll_target = boost::none;
1120 _dragging_playhead = false;
1125 Editor::access_action (std::string action_group, std::string action_item)
1131 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1134 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1142 Editor::on_realize ()
1144 Window::on_realize ();
1147 if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1148 start_lock_event_timing ();
1151 signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
1155 Editor::start_lock_event_timing ()
1157 /* check if we should lock the GUI every 30 seconds */
1159 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1163 Editor::generic_event_handler (GdkEvent* ev)
1166 case GDK_BUTTON_PRESS:
1167 case GDK_BUTTON_RELEASE:
1168 case GDK_MOTION_NOTIFY:
1170 case GDK_KEY_RELEASE:
1171 gettimeofday (&last_event_time, 0);
1174 case GDK_LEAVE_NOTIFY:
1175 switch (ev->crossing.detail) {
1176 case GDK_NOTIFY_UNKNOWN:
1177 case GDK_NOTIFY_INFERIOR:
1178 case GDK_NOTIFY_ANCESTOR:
1180 case GDK_NOTIFY_VIRTUAL:
1181 case GDK_NOTIFY_NONLINEAR:
1182 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1183 /* leaving window, so reset focus, thus ending any and
1184 all text entry operations.
1199 Editor::lock_timeout_callback ()
1201 struct timeval now, delta;
1203 gettimeofday (&now, 0);
1205 timersub (&now, &last_event_time, &delta);
1207 if (delta.tv_sec > (time_t) ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1209 /* don't call again. Returning false will effectively
1210 disconnect us from the timer callback.
1212 unlock() will call start_lock_event_timing() to get things
1222 Editor::map_position_change (framepos_t frame)
1224 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1226 if (_session == 0) {
1230 if (_follow_playhead) {
1231 center_screen (frame);
1234 playhead_cursor->set_position (frame);
1238 Editor::center_screen (framepos_t frame)
1240 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1242 /* if we're off the page, then scroll.
1245 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1246 center_screen_internal (frame, page);
1251 Editor::center_screen_internal (framepos_t frame, float page)
1256 frame -= (framepos_t) page;
1261 reset_x_origin (frame);
1266 Editor::update_title ()
1268 ENSURE_GUI_THREAD (*this, &Editor::update_title)
1271 bool dirty = _session->dirty();
1273 string session_name;
1275 if (_session->snap_name() != _session->name()) {
1276 session_name = _session->snap_name();
1278 session_name = _session->name();
1282 session_name = "*" + session_name;
1285 WindowTitle title(session_name);
1286 title += Glib::get_application_name();
1287 set_title (title.get_string());
1289 /* ::session_going_away() will have taken care of it */
1294 Editor::set_session (Session *t)
1296 SessionHandlePtr::set_session (t);
1302 _playlist_selector->set_session (_session);
1303 nudge_clock->set_session (_session);
1304 _summary->set_session (_session);
1305 _group_tabs->set_session (_session);
1306 _route_groups->set_session (_session);
1307 _regions->set_session (_session);
1308 _snapshots->set_session (_session);
1309 _routes->set_session (_session);
1310 _locations->set_session (_session);
1312 if (rhythm_ferret) {
1313 rhythm_ferret->set_session (_session);
1316 if (analysis_window) {
1317 analysis_window->set_session (_session);
1321 sfbrowser->set_session (_session);
1324 compute_fixed_ruler_scale ();
1326 /* Make sure we have auto loop and auto punch ranges */
1328 Location* loc = _session->locations()->auto_loop_location();
1330 loc->set_name (_("Loop"));
1333 loc = _session->locations()->auto_punch_location();
1336 loc->set_name (_("Punch"));
1339 refresh_location_display ();
1341 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1342 the selected Marker; this needs the LocationMarker list to be available.
1344 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1345 set_state (*node, Stateful::loading_state_version);
1347 /* catch up with the playhead */
1349 _session->request_locate (playhead_cursor->current_frame ());
1350 _pending_initial_locate = true;
1354 /* These signals can all be emitted by a non-GUI thread. Therefore the
1355 handlers for them must not attempt to directly interact with the GUI,
1356 but use PBD::Signal<T>::connect() which accepts an event loop
1357 ("context") where the handler will be asked to run.
1360 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1361 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1362 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1363 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1364 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1365 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1366 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1367 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1368 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1369 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1370 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1371 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1372 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1374 playhead_cursor->show ();
1376 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1377 Config->map_parameters (pc);
1378 _session->config.map_parameters (pc);
1380 restore_ruler_visibility ();
1381 //tempo_map_changed (PropertyChange (0));
1382 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1384 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1385 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1388 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1389 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1392 switch (_snap_type) {
1393 case SnapToRegionStart:
1394 case SnapToRegionEnd:
1395 case SnapToRegionSync:
1396 case SnapToRegionBoundary:
1397 build_region_boundary_cache ();
1404 /* register for undo history */
1405 _session->register_with_memento_command_factory(id(), this);
1406 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1408 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1410 start_updating_meters ();
1414 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1416 if (a->get_name() == "RegionMenu") {
1417 /* When the main menu's region menu is opened, we setup the actions so that they look right
1418 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1419 so we resensitize all region actions when the entered regionview or the region selection
1420 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1421 happens after the region context menu is opened. So we set a flag here, too.
1425 sensitize_the_right_region_actions ();
1426 _last_region_menu_was_main = true;
1431 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1433 using namespace Menu_Helpers;
1435 void (Editor::*emf)(FadeShape);
1436 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1439 images = &_xfade_in_images;
1440 emf = &Editor::set_fade_in_shape;
1442 images = &_xfade_out_images;
1443 emf = &Editor::set_fade_out_shape;
1448 _("Linear (for highly correlated material)"),
1449 *(*images)[FadeLinear],
1450 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1454 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1458 _("Constant power"),
1459 *(*images)[FadeConstantPower],
1460 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1463 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1468 *(*images)[FadeSymmetric],
1469 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1473 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1478 *(*images)[FadeSlow],
1479 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1482 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1487 *(*images)[FadeFast],
1488 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1491 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1494 /** Pop up a context menu for when the user clicks on a start crossfade */
1496 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1498 using namespace Menu_Helpers;
1499 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1504 MenuList& items (xfade_in_context_menu.items());
1507 if (arv->audio_region()->fade_in_active()) {
1508 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1510 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1513 items.push_back (SeparatorElem());
1514 fill_xfade_menu (items, true);
1516 xfade_in_context_menu.popup (button, time);
1519 /** Pop up a context menu for when the user clicks on an end crossfade */
1521 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1523 using namespace Menu_Helpers;
1524 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1529 MenuList& items (xfade_out_context_menu.items());
1532 if (arv->audio_region()->fade_out_active()) {
1533 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1535 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1538 items.push_back (SeparatorElem());
1539 fill_xfade_menu (items, false);
1541 xfade_out_context_menu.popup (button, time);
1545 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1547 using namespace Menu_Helpers;
1548 Menu* (Editor::*build_menu_function)();
1551 switch (item_type) {
1553 case RegionViewName:
1554 case RegionViewNameHighlight:
1555 case LeftFrameHandle:
1556 case RightFrameHandle:
1557 if (with_selection) {
1558 build_menu_function = &Editor::build_track_selection_context_menu;
1560 build_menu_function = &Editor::build_track_region_context_menu;
1565 if (with_selection) {
1566 build_menu_function = &Editor::build_track_selection_context_menu;
1568 build_menu_function = &Editor::build_track_context_menu;
1573 if (clicked_routeview->track()) {
1574 build_menu_function = &Editor::build_track_context_menu;
1576 build_menu_function = &Editor::build_track_bus_context_menu;
1581 /* probably shouldn't happen but if it does, we don't care */
1585 menu = (this->*build_menu_function)();
1586 menu->set_name ("ArdourContextMenu");
1588 /* now handle specific situations */
1590 switch (item_type) {
1592 case RegionViewName:
1593 case RegionViewNameHighlight:
1594 case LeftFrameHandle:
1595 case RightFrameHandle:
1596 if (!with_selection) {
1597 if (region_edit_menu_split_item) {
1598 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1599 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1601 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1604 if (region_edit_menu_split_multichannel_item) {
1605 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1606 region_edit_menu_split_multichannel_item->set_sensitive (true);
1608 region_edit_menu_split_multichannel_item->set_sensitive (false);
1621 /* probably shouldn't happen but if it does, we don't care */
1625 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1627 /* Bounce to disk */
1629 using namespace Menu_Helpers;
1630 MenuList& edit_items = menu->items();
1632 edit_items.push_back (SeparatorElem());
1634 switch (clicked_routeview->audio_track()->freeze_state()) {
1635 case AudioTrack::NoFreeze:
1636 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1639 case AudioTrack::Frozen:
1640 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1643 case AudioTrack::UnFrozen:
1644 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1650 if (item_type == StreamItem && clicked_routeview) {
1651 clicked_routeview->build_underlay_menu(menu);
1654 /* When the region menu is opened, we setup the actions so that they look right
1657 sensitize_the_right_region_actions ();
1658 _last_region_menu_was_main = false;
1660 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1661 menu->popup (button, time);
1665 Editor::build_track_context_menu ()
1667 using namespace Menu_Helpers;
1669 MenuList& edit_items = track_context_menu.items();
1672 add_dstream_context_items (edit_items);
1673 return &track_context_menu;
1677 Editor::build_track_bus_context_menu ()
1679 using namespace Menu_Helpers;
1681 MenuList& edit_items = track_context_menu.items();
1684 add_bus_context_items (edit_items);
1685 return &track_context_menu;
1689 Editor::build_track_region_context_menu ()
1691 using namespace Menu_Helpers;
1692 MenuList& edit_items = track_region_context_menu.items();
1695 /* we've just cleared the track region context menu, so the menu that these
1696 two items were on will have disappeared; stop them dangling.
1698 region_edit_menu_split_item = 0;
1699 region_edit_menu_split_multichannel_item = 0;
1701 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1704 boost::shared_ptr<Track> tr;
1705 boost::shared_ptr<Playlist> pl;
1707 if ((tr = rtv->track())) {
1708 add_region_context_items (edit_items, tr);
1712 add_dstream_context_items (edit_items);
1714 return &track_region_context_menu;
1718 Editor::analyze_region_selection ()
1720 if (analysis_window == 0) {
1721 analysis_window = new AnalysisWindow();
1724 analysis_window->set_session(_session);
1726 analysis_window->show_all();
1729 analysis_window->set_regionmode();
1730 analysis_window->analyze();
1732 analysis_window->present();
1736 Editor::analyze_range_selection()
1738 if (analysis_window == 0) {
1739 analysis_window = new AnalysisWindow();
1742 analysis_window->set_session(_session);
1744 analysis_window->show_all();
1747 analysis_window->set_rangemode();
1748 analysis_window->analyze();
1750 analysis_window->present();
1754 Editor::build_track_selection_context_menu ()
1756 using namespace Menu_Helpers;
1757 MenuList& edit_items = track_selection_context_menu.items();
1758 edit_items.clear ();
1760 add_selection_context_items (edit_items);
1761 // edit_items.push_back (SeparatorElem());
1762 // add_dstream_context_items (edit_items);
1764 return &track_selection_context_menu;
1768 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1770 using namespace Menu_Helpers;
1772 /* OK, stick the region submenu at the top of the list, and then add
1776 RegionSelection rs = get_regions_from_selection_and_entered ();
1778 string::size_type pos = 0;
1779 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1781 /* we have to hack up the region name because "_" has a special
1782 meaning for menu titles.
1785 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1786 menu_item_name.replace (pos, 1, "__");
1790 if (_popup_region_menu_item == 0) {
1791 _popup_region_menu_item = new MenuItem (menu_item_name);
1792 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1793 _popup_region_menu_item->show ();
1795 _popup_region_menu_item->set_label (menu_item_name);
1798 const framepos_t position = get_preferred_edit_position (false, true);
1800 edit_items.push_back (*_popup_region_menu_item);
1801 if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1802 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1804 edit_items.push_back (SeparatorElem());
1807 /** Add context menu items relevant to selection ranges.
1808 * @param edit_items List to add the items to.
1811 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1813 using namespace Menu_Helpers;
1815 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1816 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1818 edit_items.push_back (SeparatorElem());
1819 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1821 edit_items.push_back (SeparatorElem());
1822 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1824 edit_items.push_back (SeparatorElem());
1826 edit_items.push_back (
1828 _("Move Range Start to Previous Region Boundary"),
1829 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1833 edit_items.push_back (
1835 _("Move Range Start to Next Region Boundary"),
1836 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1840 edit_items.push_back (
1842 _("Move Range End to Previous Region Boundary"),
1843 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1847 edit_items.push_back (
1849 _("Move Range End to Next Region Boundary"),
1850 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1854 edit_items.push_back (SeparatorElem());
1855 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1856 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1858 edit_items.push_back (SeparatorElem());
1859 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1861 edit_items.push_back (SeparatorElem());
1862 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1863 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1864 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1866 edit_items.push_back (SeparatorElem());
1867 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1869 edit_items.push_back (SeparatorElem());
1870 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1871 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1872 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1874 edit_items.push_back (SeparatorElem());
1875 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1876 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1877 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1878 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1879 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1880 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1881 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1887 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1889 using namespace Menu_Helpers;
1893 Menu *play_menu = manage (new Menu);
1894 MenuList& play_items = play_menu->items();
1895 play_menu->set_name ("ArdourContextMenu");
1897 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1898 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1899 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1900 play_items.push_back (SeparatorElem());
1901 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1903 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1907 Menu *select_menu = manage (new Menu);
1908 MenuList& select_items = select_menu->items();
1909 select_menu->set_name ("ArdourContextMenu");
1911 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1912 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1913 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1914 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1915 select_items.push_back (SeparatorElem());
1916 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1917 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1918 select_items.push_back (SeparatorElem());
1919 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1920 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1921 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1922 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1923 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1924 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1925 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1927 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1931 Menu *cutnpaste_menu = manage (new Menu);
1932 MenuList& cutnpaste_items = cutnpaste_menu->items();
1933 cutnpaste_menu->set_name ("ArdourContextMenu");
1935 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1936 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1937 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1939 cutnpaste_items.push_back (SeparatorElem());
1941 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1942 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1944 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1946 /* Adding new material */
1948 edit_items.push_back (SeparatorElem());
1949 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1950 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1954 Menu *nudge_menu = manage (new Menu());
1955 MenuList& nudge_items = nudge_menu->items();
1956 nudge_menu->set_name ("ArdourContextMenu");
1958 edit_items.push_back (SeparatorElem());
1959 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1960 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1961 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1962 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1964 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1968 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1970 using namespace Menu_Helpers;
1974 Menu *play_menu = manage (new Menu);
1975 MenuList& play_items = play_menu->items();
1976 play_menu->set_name ("ArdourContextMenu");
1978 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1979 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1980 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1984 Menu *select_menu = manage (new Menu);
1985 MenuList& select_items = select_menu->items();
1986 select_menu->set_name ("ArdourContextMenu");
1988 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1989 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1990 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1991 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1992 select_items.push_back (SeparatorElem());
1993 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1994 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1995 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1996 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1998 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2002 Menu *cutnpaste_menu = manage (new Menu);
2003 MenuList& cutnpaste_items = cutnpaste_menu->items();
2004 cutnpaste_menu->set_name ("ArdourContextMenu");
2006 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2007 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2008 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2010 Menu *nudge_menu = manage (new Menu());
2011 MenuList& nudge_items = nudge_menu->items();
2012 nudge_menu->set_name ("ArdourContextMenu");
2014 edit_items.push_back (SeparatorElem());
2015 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2016 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2017 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2018 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2020 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2024 Editor::snap_type() const
2030 Editor::snap_mode() const
2036 Editor::set_snap_to (SnapType st)
2038 unsigned int snap_ind = (unsigned int)st;
2040 if (internal_editing()) {
2041 internal_snap_type = st;
2043 pre_internal_snap_type = st;
2048 if (snap_ind > snap_type_strings.size() - 1) {
2050 _snap_type = (SnapType)snap_ind;
2053 string str = snap_type_strings[snap_ind];
2055 if (str != snap_type_selector.get_text()) {
2056 snap_type_selector.set_text (str);
2061 switch (_snap_type) {
2062 case SnapToBeatDiv128:
2063 case SnapToBeatDiv64:
2064 case SnapToBeatDiv32:
2065 case SnapToBeatDiv28:
2066 case SnapToBeatDiv24:
2067 case SnapToBeatDiv20:
2068 case SnapToBeatDiv16:
2069 case SnapToBeatDiv14:
2070 case SnapToBeatDiv12:
2071 case SnapToBeatDiv10:
2072 case SnapToBeatDiv8:
2073 case SnapToBeatDiv7:
2074 case SnapToBeatDiv6:
2075 case SnapToBeatDiv5:
2076 case SnapToBeatDiv4:
2077 case SnapToBeatDiv3:
2078 case SnapToBeatDiv2: {
2079 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2080 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2082 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2083 current_bbt_points_begin, current_bbt_points_end);
2084 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2085 current_bbt_points_begin, current_bbt_points_end);
2086 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2090 case SnapToRegionStart:
2091 case SnapToRegionEnd:
2092 case SnapToRegionSync:
2093 case SnapToRegionBoundary:
2094 build_region_boundary_cache ();
2102 redisplay_tempo (false);
2104 SnapChanged (); /* EMIT SIGNAL */
2108 Editor::set_snap_mode (SnapMode mode)
2110 string str = snap_mode_strings[(int)mode];
2112 if (internal_editing()) {
2113 internal_snap_mode = mode;
2115 pre_internal_snap_mode = mode;
2120 if (str != snap_mode_selector.get_text ()) {
2121 snap_mode_selector.set_text (str);
2127 Editor::set_edit_point_preference (EditPoint ep, bool force)
2129 bool changed = (_edit_point != ep);
2132 if (Profile->get_mixbus())
2133 if (ep == EditAtSelectedMarker)
2134 ep = EditAtPlayhead;
2136 string str = edit_point_strings[(int)ep];
2137 if (str != edit_point_selector.get_text ()) {
2138 edit_point_selector.set_text (str);
2141 update_all_enter_cursors();
2143 if (!force && !changed) {
2147 const char* action=NULL;
2149 switch (_edit_point) {
2150 case EditAtPlayhead:
2151 action = "edit-at-playhead";
2153 case EditAtSelectedMarker:
2154 action = "edit-at-marker";
2157 action = "edit-at-mouse";
2161 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2163 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2167 bool in_track_canvas;
2169 if (!mouse_frame (foo, in_track_canvas)) {
2170 in_track_canvas = false;
2173 reset_canvas_action_sensitivity (in_track_canvas);
2179 Editor::set_state (const XMLNode& node, int /*version*/)
2181 const XMLProperty* prop;
2188 g.base_width = default_width;
2189 g.base_height = default_height;
2193 if ((geometry = find_named_node (node, "geometry")) != 0) {
2197 if ((prop = geometry->property("x_size")) == 0) {
2198 prop = geometry->property ("x-size");
2201 g.base_width = atoi(prop->value());
2203 if ((prop = geometry->property("y_size")) == 0) {
2204 prop = geometry->property ("y-size");
2207 g.base_height = atoi(prop->value());
2210 if ((prop = geometry->property ("x_pos")) == 0) {
2211 prop = geometry->property ("x-pos");
2214 x = atoi (prop->value());
2217 if ((prop = geometry->property ("y_pos")) == 0) {
2218 prop = geometry->property ("y-pos");
2221 y = atoi (prop->value());
2225 set_default_size (g.base_width, g.base_height);
2228 if (_session && (prop = node.property ("playhead"))) {
2230 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2232 playhead_cursor->set_position (pos);
2234 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2235 playhead_cursor->set_position (0);
2238 playhead_cursor->set_position (0);
2241 if ((prop = node.property ("mixer-width"))) {
2242 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2245 if ((prop = node.property ("zoom-focus"))) {
2246 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2249 if ((prop = node.property ("zoom"))) {
2250 /* older versions of ardour used floating point samples_per_pixel */
2251 double f = PBD::atof (prop->value());
2252 reset_zoom (llrintf (f));
2254 reset_zoom (samples_per_pixel);
2257 if ((prop = node.property ("visible-track-count"))) {
2258 set_visible_track_count (PBD::atoi (prop->value()));
2261 if ((prop = node.property ("snap-to"))) {
2262 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2265 if ((prop = node.property ("snap-mode"))) {
2266 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2269 if ((prop = node.property ("internal-snap-to"))) {
2270 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2273 if ((prop = node.property ("internal-snap-mode"))) {
2274 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2277 if ((prop = node.property ("pre-internal-snap-to"))) {
2278 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2281 if ((prop = node.property ("pre-internal-snap-mode"))) {
2282 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2285 if ((prop = node.property ("mouse-mode"))) {
2286 MouseMode m = str2mousemode(prop->value());
2287 set_mouse_mode (m, true);
2289 set_mouse_mode (MouseObject, true);
2292 if ((prop = node.property ("left-frame")) != 0) {
2294 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2298 reset_x_origin (pos);
2302 if ((prop = node.property ("y-origin")) != 0) {
2303 reset_y_origin (atof (prop->value ()));
2306 if ((prop = node.property ("join-object-range"))) {
2307 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2308 bool yn = string_is_affirmative (prop->value());
2310 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2311 tact->set_active (!yn);
2312 tact->set_active (yn);
2314 set_mouse_mode(mouse_mode, true);
2317 if ((prop = node.property ("edit-point"))) {
2318 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2321 if ((prop = node.property ("show-measures"))) {
2322 bool yn = string_is_affirmative (prop->value());
2323 _show_measures = yn;
2324 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2326 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2327 /* do it twice to force the change */
2328 tact->set_active (!yn);
2329 tact->set_active (yn);
2333 if ((prop = node.property ("follow-playhead"))) {
2334 bool yn = string_is_affirmative (prop->value());
2335 set_follow_playhead (yn);
2336 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2338 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2339 if (tact->get_active() != yn) {
2340 tact->set_active (yn);
2345 if ((prop = node.property ("stationary-playhead"))) {
2346 bool yn = string_is_affirmative (prop->value());
2347 set_stationary_playhead (yn);
2348 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2350 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2351 if (tact->get_active() != yn) {
2352 tact->set_active (yn);
2357 if ((prop = node.property ("region-list-sort-type"))) {
2358 RegionListSortType st;
2359 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2362 if ((prop = node.property ("show-editor-mixer"))) {
2364 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2367 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2368 bool yn = string_is_affirmative (prop->value());
2370 /* do it twice to force the change */
2372 tact->set_active (!yn);
2373 tact->set_active (yn);
2376 if ((prop = node.property ("show-editor-list"))) {
2378 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2381 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2382 bool yn = string_is_affirmative (prop->value());
2384 /* do it twice to force the change */
2386 tact->set_active (!yn);
2387 tact->set_active (yn);
2390 if ((prop = node.property (X_("editor-list-page")))) {
2391 _the_notebook.set_current_page (atoi (prop->value ()));
2394 if ((prop = node.property (X_("show-marker-lines")))) {
2395 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2397 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2398 bool yn = string_is_affirmative (prop->value ());
2400 tact->set_active (!yn);
2401 tact->set_active (yn);
2404 XMLNodeList children = node.children ();
2405 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2406 selection->set_state (**i, Stateful::current_state_version);
2407 _regions->set_state (**i);
2410 if ((prop = node.property ("maximised"))) {
2411 bool yn = string_is_affirmative (prop->value());
2412 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2414 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2415 bool fs = tact && tact->get_active();
2417 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2421 if ((prop = node.property ("nudge-clock-value"))) {
2423 sscanf (prop->value().c_str(), "%" PRId64, &f);
2424 nudge_clock->set (f);
2426 nudge_clock->set_mode (AudioClock::Timecode);
2427 nudge_clock->set (_session->frame_rate() * 5, true);
2434 Editor::get_state ()
2436 XMLNode* node = new XMLNode ("Editor");
2439 id().print (buf, sizeof (buf));
2440 node->add_property ("id", buf);
2442 if (is_realized()) {
2443 Glib::RefPtr<Gdk::Window> win = get_window();
2445 int x, y, width, height;
2446 win->get_root_origin(x, y);
2447 win->get_size(width, height);
2449 XMLNode* geometry = new XMLNode ("geometry");
2451 snprintf(buf, sizeof(buf), "%d", width);
2452 geometry->add_property("x-size", string(buf));
2453 snprintf(buf, sizeof(buf), "%d", height);
2454 geometry->add_property("y-size", string(buf));
2455 snprintf(buf, sizeof(buf), "%d", x);
2456 geometry->add_property("x-pos", string(buf));
2457 snprintf(buf, sizeof(buf), "%d", y);
2458 geometry->add_property("y-pos", string(buf));
2459 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2460 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2461 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2462 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2463 geometry->add_property("edit-vertical-pane-pos", string(buf));
2465 node->add_child_nocopy (*geometry);
2468 maybe_add_mixer_strip_width (*node);
2470 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2472 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2473 node->add_property ("zoom", buf);
2474 node->add_property ("snap-to", enum_2_string (_snap_type));
2475 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2476 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2477 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2478 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2479 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2480 node->add_property ("edit-point", enum_2_string (_edit_point));
2481 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2482 node->add_property ("visible-track-count", buf);
2484 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2485 node->add_property ("playhead", buf);
2486 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2487 node->add_property ("left-frame", buf);
2488 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2489 node->add_property ("y-origin", buf);
2491 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2492 node->add_property ("maximised", _maximised ? "yes" : "no");
2493 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2494 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2495 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2496 node->add_property ("mouse-mode", enum2str(mouse_mode));
2497 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2499 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2501 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2502 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2505 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2507 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2508 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2511 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2512 node->add_property (X_("editor-list-page"), buf);
2514 if (button_bindings) {
2515 XMLNode* bb = new XMLNode (X_("Buttons"));
2516 button_bindings->save (*bb);
2517 node->add_child_nocopy (*bb);
2520 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2522 node->add_child_nocopy (selection->get_state ());
2523 node->add_child_nocopy (_regions->get_state ());
2525 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2526 node->add_property ("nudge-clock-value", buf);
2531 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2532 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2534 * @return pair: TimeAxisView that y is over, layer index.
2536 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2537 * in stacked or expanded region display mode, otherwise 0.
2539 std::pair<TimeAxisView *, double>
2540 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2542 if (!trackview_relative_offset) {
2543 y -= _trackview_group->canvas_origin().y;
2547 return std::make_pair ( (TimeAxisView *) 0, 0);
2550 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2552 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2559 return std::make_pair ( (TimeAxisView *) 0, 0);
2562 /** Snap a position to the grid, if appropriate, taking into account current
2563 * grid settings and also the state of any snap modifier keys that may be pressed.
2564 * @param start Position to snap.
2565 * @param event Event to get current key modifier information from, or 0.
2568 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2570 if (!_session || !event) {
2574 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2575 if (_snap_mode == SnapOff) {
2576 snap_to_internal (start, direction, for_mark);
2579 if (_snap_mode != SnapOff) {
2580 snap_to_internal (start, direction, for_mark);
2586 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark)
2588 if (!_session || _snap_mode == SnapOff) {
2592 snap_to_internal (start, direction, for_mark);
2596 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2598 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2599 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2601 switch (_snap_type) {
2602 case SnapToTimecodeFrame:
2603 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2604 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2605 /* start is already on a whole timecode frame, do nothing */
2606 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2607 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2609 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2613 case SnapToTimecodeSeconds:
2614 if (_session->config.get_timecode_offset_negative()) {
2615 start += _session->config.get_timecode_offset ();
2617 start -= _session->config.get_timecode_offset ();
2619 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2620 (start % one_timecode_second == 0)) {
2621 /* start is already on a whole second, do nothing */
2622 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2623 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2625 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2628 if (_session->config.get_timecode_offset_negative()) {
2629 start -= _session->config.get_timecode_offset ();
2631 start += _session->config.get_timecode_offset ();
2635 case SnapToTimecodeMinutes:
2636 if (_session->config.get_timecode_offset_negative()) {
2637 start += _session->config.get_timecode_offset ();
2639 start -= _session->config.get_timecode_offset ();
2641 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2642 (start % one_timecode_minute == 0)) {
2643 /* start is already on a whole minute, do nothing */
2644 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2645 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2647 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2649 if (_session->config.get_timecode_offset_negative()) {
2650 start -= _session->config.get_timecode_offset ();
2652 start += _session->config.get_timecode_offset ();
2656 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2657 abort(); /*NOTREACHED*/
2662 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark)
2664 const framepos_t one_second = _session->frame_rate();
2665 const framepos_t one_minute = _session->frame_rate() * 60;
2666 framepos_t presnap = start;
2670 switch (_snap_type) {
2671 case SnapToTimecodeFrame:
2672 case SnapToTimecodeSeconds:
2673 case SnapToTimecodeMinutes:
2674 return timecode_snap_to_internal (start, direction, for_mark);
2677 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2678 start % (one_second/75) == 0) {
2679 /* start is already on a whole CD frame, do nothing */
2680 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2681 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2683 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2688 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2689 start % one_second == 0) {
2690 /* start is already on a whole second, do nothing */
2691 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2692 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2694 start = (framepos_t) floor ((double) start / one_second) * one_second;
2699 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2700 start % one_minute == 0) {
2701 /* start is already on a whole minute, do nothing */
2702 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2703 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2705 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2710 start = _session->tempo_map().round_to_bar (start, direction);
2714 start = _session->tempo_map().round_to_beat (start, direction);
2717 case SnapToBeatDiv128:
2718 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2720 case SnapToBeatDiv64:
2721 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2723 case SnapToBeatDiv32:
2724 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2726 case SnapToBeatDiv28:
2727 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2729 case SnapToBeatDiv24:
2730 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2732 case SnapToBeatDiv20:
2733 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2735 case SnapToBeatDiv16:
2736 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2738 case SnapToBeatDiv14:
2739 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2741 case SnapToBeatDiv12:
2742 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2744 case SnapToBeatDiv10:
2745 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2747 case SnapToBeatDiv8:
2748 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2750 case SnapToBeatDiv7:
2751 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2753 case SnapToBeatDiv6:
2754 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2756 case SnapToBeatDiv5:
2757 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2759 case SnapToBeatDiv4:
2760 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2762 case SnapToBeatDiv3:
2763 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2765 case SnapToBeatDiv2:
2766 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2774 _session->locations()->marks_either_side (start, before, after);
2776 if (before == max_framepos && after == max_framepos) {
2777 /* No marks to snap to, so just don't snap */
2779 } else if (before == max_framepos) {
2781 } else if (after == max_framepos) {
2783 } else if (before != max_framepos && after != max_framepos) {
2784 /* have before and after */
2785 if ((start - before) < (after - start)) {
2794 case SnapToRegionStart:
2795 case SnapToRegionEnd:
2796 case SnapToRegionSync:
2797 case SnapToRegionBoundary:
2798 if (!region_boundary_cache.empty()) {
2800 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2801 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2803 if (direction > 0) {
2804 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2806 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2809 if (next != region_boundary_cache.begin ()) {
2814 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2815 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2817 if (start > (p + n) / 2) {
2826 switch (_snap_mode) {
2832 if (presnap > start) {
2833 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2837 } else if (presnap < start) {
2838 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2844 /* handled at entry */
2852 Editor::setup_toolbar ()
2854 HBox* mode_box = manage(new HBox);
2855 mode_box->set_border_width (2);
2856 mode_box->set_spacing(2);
2858 HBox* mouse_mode_box = manage (new HBox);
2859 HBox* mouse_mode_hbox = manage (new HBox);
2860 VBox* mouse_mode_vbox = manage (new VBox);
2861 Alignment* mouse_mode_align = manage (new Alignment);
2863 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2864 mouse_mode_size_group->add_widget (smart_mode_button);
2865 mouse_mode_size_group->add_widget (mouse_move_button);
2866 mouse_mode_size_group->add_widget (mouse_cut_button);
2867 mouse_mode_size_group->add_widget (mouse_select_button);
2868 mouse_mode_size_group->add_widget (mouse_timefx_button);
2869 mouse_mode_size_group->add_widget (mouse_audition_button);
2870 mouse_mode_size_group->add_widget (mouse_draw_button);
2871 mouse_mode_size_group->add_widget (mouse_content_button);
2873 mouse_mode_size_group->add_widget (zoom_in_button);
2874 mouse_mode_size_group->add_widget (zoom_out_button);
2875 mouse_mode_size_group->add_widget (zoom_preset_selector);
2876 mouse_mode_size_group->add_widget (zoom_out_full_button);
2877 mouse_mode_size_group->add_widget (zoom_focus_selector);
2879 mouse_mode_size_group->add_widget (tav_shrink_button);
2880 mouse_mode_size_group->add_widget (tav_expand_button);
2881 mouse_mode_size_group->add_widget (visible_tracks_selector);
2883 mouse_mode_size_group->add_widget (snap_type_selector);
2884 mouse_mode_size_group->add_widget (snap_mode_selector);
2886 mouse_mode_size_group->add_widget (edit_point_selector);
2887 mouse_mode_size_group->add_widget (edit_mode_selector);
2889 mouse_mode_size_group->add_widget (*nudge_clock);
2890 mouse_mode_size_group->add_widget (nudge_forward_button);
2891 mouse_mode_size_group->add_widget (nudge_backward_button);
2893 mouse_mode_hbox->set_spacing (2);
2895 if (!ARDOUR::Profile->get_trx()) {
2896 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2899 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2900 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2902 if (!ARDOUR::Profile->get_mixbus()) {
2903 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2906 if (!ARDOUR::Profile->get_trx()) {
2907 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2908 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2909 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2910 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2913 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2915 mouse_mode_align->add (*mouse_mode_vbox);
2916 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2918 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2920 edit_mode_selector.set_name ("mouse mode button");
2922 if (!ARDOUR::Profile->get_trx()) {
2923 mode_box->pack_start (edit_mode_selector, false, false);
2925 mode_box->pack_start (*mouse_mode_box, false, false);
2927 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2928 _mouse_mode_tearoff->set_name ("MouseModeBase");
2929 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2931 if (Profile->get_sae() || Profile->get_mixbus() ) {
2932 _mouse_mode_tearoff->set_can_be_torn_off (false);
2935 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2936 &_mouse_mode_tearoff->tearoff_window()));
2937 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2938 &_mouse_mode_tearoff->tearoff_window(), 1));
2939 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2940 &_mouse_mode_tearoff->tearoff_window()));
2941 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2942 &_mouse_mode_tearoff->tearoff_window(), 1));
2946 _zoom_box.set_spacing (2);
2947 _zoom_box.set_border_width (2);
2951 zoom_preset_selector.set_name ("zoom button");
2952 zoom_preset_selector.set_image(::get_icon ("time_exp"));
2953 zoom_preset_selector.set_size_request (42, -1);
2955 zoom_in_button.set_name ("zoom button");
2956 zoom_in_button.set_image(::get_icon ("zoom_in"));
2957 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2958 zoom_in_button.set_related_action (act);
2960 zoom_out_button.set_name ("zoom button");
2961 zoom_out_button.set_image(::get_icon ("zoom_out"));
2962 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2963 zoom_out_button.set_related_action (act);
2965 zoom_out_full_button.set_name ("zoom button");
2966 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2967 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2968 zoom_out_full_button.set_related_action (act);
2970 zoom_focus_selector.set_name ("zoom button");
2972 if (ARDOUR::Profile->get_mixbus()) {
2973 _zoom_box.pack_start (zoom_preset_selector, false, false);
2974 } else if (ARDOUR::Profile->get_trx()) {
2975 mode_box->pack_start (zoom_out_button, false, false);
2976 mode_box->pack_start (zoom_in_button, false, false);
2978 _zoom_box.pack_start (zoom_out_button, false, false);
2979 _zoom_box.pack_start (zoom_in_button, false, false);
2980 _zoom_box.pack_start (zoom_out_full_button, false, false);
2981 _zoom_box.pack_start (zoom_focus_selector, false, false);
2984 /* Track zoom buttons */
2985 visible_tracks_selector.set_name ("zoom button");
2986 if (Profile->get_mixbus()) {
2987 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2988 visible_tracks_selector.set_size_request (42, -1);
2990 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
2993 tav_expand_button.set_name ("zoom button");
2994 tav_expand_button.set_image(::get_icon ("tav_exp"));
2995 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2996 tav_expand_button.set_related_action (act);
2998 tav_shrink_button.set_name ("zoom button");
2999 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
3000 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3001 tav_shrink_button.set_related_action (act);
3003 if (ARDOUR::Profile->get_mixbus()) {
3004 _zoom_box.pack_start (visible_tracks_selector);
3005 } else if (ARDOUR::Profile->get_trx()) {
3006 _zoom_box.pack_start (tav_shrink_button);
3007 _zoom_box.pack_start (tav_expand_button);
3009 _zoom_box.pack_start (visible_tracks_selector);
3010 _zoom_box.pack_start (tav_shrink_button);
3011 _zoom_box.pack_start (tav_expand_button);
3014 if (!ARDOUR::Profile->get_trx()) {
3015 _zoom_tearoff = manage (new TearOff (_zoom_box));
3017 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3018 &_zoom_tearoff->tearoff_window()));
3019 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3020 &_zoom_tearoff->tearoff_window(), 0));
3021 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3022 &_zoom_tearoff->tearoff_window()));
3023 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3024 &_zoom_tearoff->tearoff_window(), 0));
3027 if (Profile->get_sae() || Profile->get_mixbus() ) {
3028 _zoom_tearoff->set_can_be_torn_off (false);
3031 snap_box.set_spacing (2);
3032 snap_box.set_border_width (2);
3034 snap_type_selector.set_name ("mouse mode button");
3036 snap_mode_selector.set_name ("mouse mode button");
3038 edit_point_selector.set_name ("mouse mode button");
3040 snap_box.pack_start (snap_mode_selector, false, false);
3041 snap_box.pack_start (snap_type_selector, false, false);
3042 snap_box.pack_start (edit_point_selector, false, false);
3046 HBox *nudge_box = manage (new HBox);
3047 nudge_box->set_spacing (2);
3048 nudge_box->set_border_width (2);
3050 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3051 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3053 nudge_box->pack_start (nudge_backward_button, false, false);
3054 nudge_box->pack_start (nudge_forward_button, false, false);
3055 nudge_box->pack_start (*nudge_clock, false, false);
3058 /* Pack everything in... */
3060 HBox* hbox = manage (new HBox);
3061 hbox->set_spacing(2);
3063 _tools_tearoff = manage (new TearOff (*hbox));
3064 _tools_tearoff->set_name ("MouseModeBase");
3065 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3067 if (Profile->get_sae() || Profile->get_mixbus()) {
3068 _tools_tearoff->set_can_be_torn_off (false);
3071 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3072 &_tools_tearoff->tearoff_window()));
3073 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3074 &_tools_tearoff->tearoff_window(), 0));
3075 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3076 &_tools_tearoff->tearoff_window()));
3077 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3078 &_tools_tearoff->tearoff_window(), 0));
3080 toolbar_hbox.set_spacing (2);
3081 toolbar_hbox.set_border_width (1);
3083 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3084 if (!ARDOUR::Profile->get_trx()) {
3085 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3086 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3089 if (!ARDOUR::Profile->get_trx()) {
3090 hbox->pack_start (snap_box, false, false);
3091 if ( !Profile->get_small_screen() || Profile->get_mixbus() ) {
3092 hbox->pack_start (*nudge_box, false, false);
3094 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3097 hbox->pack_start (panic_box, false, false);
3101 toolbar_base.set_name ("ToolBarBase");
3102 toolbar_base.add (toolbar_hbox);
3104 _toolbar_viewport.add (toolbar_base);
3105 /* stick to the required height but allow width to vary if there's not enough room */
3106 _toolbar_viewport.set_size_request (1, -1);
3108 toolbar_frame.set_shadow_type (SHADOW_OUT);
3109 toolbar_frame.set_name ("BaseFrame");
3110 toolbar_frame.add (_toolbar_viewport);
3114 Editor::build_edit_point_menu ()
3116 using namespace Menu_Helpers;
3118 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3119 if(!Profile->get_mixbus())
3120 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3121 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3123 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3127 Editor::build_edit_mode_menu ()
3129 using namespace Menu_Helpers;
3131 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3132 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3133 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3134 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3136 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3140 Editor::build_snap_mode_menu ()
3142 using namespace Menu_Helpers;
3144 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3145 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3146 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3148 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3152 Editor::build_snap_type_menu ()
3154 using namespace Menu_Helpers;
3156 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3157 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3158 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3159 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3160 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3161 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3162 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3163 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3164 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3165 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3166 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3167 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3168 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3169 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3170 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3171 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3172 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3173 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3174 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3175 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3176 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3177 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3178 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3179 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3180 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3181 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3182 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3183 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3184 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3185 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3187 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3192 Editor::setup_tooltips ()
3194 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Grab mode)"));
3195 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Grab Mode (select/move objects)"));
3196 ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split regions)"));
3197 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select time ranges)"));
3198 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3199 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3200 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3201 ARDOUR_UI::instance()->set_tip (mouse_content_button, _("Internal Edit Mode (edit notes and gain curves inside regions)"));
3202 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3203 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3204 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3205 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3206 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3207 ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3208 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3209 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3210 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3211 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3212 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3213 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3214 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3215 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3216 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3217 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3221 Editor::convert_drop_to_paths (
3222 vector<string>& paths,
3223 const RefPtr<Gdk::DragContext>& /*context*/,
3226 const SelectionData& data,
3230 if (_session == 0) {
3234 vector<string> uris = data.get_uris();
3238 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3239 are actually URI lists. So do it by hand.
3242 if (data.get_target() != "text/plain") {
3246 /* Parse the "uri-list" format that Nautilus provides,
3247 where each pathname is delimited by \r\n.
3249 THERE MAY BE NO NULL TERMINATING CHAR!!!
3252 string txt = data.get_text();
3256 p = (char *) malloc (txt.length() + 1);
3257 txt.copy (p, txt.length(), 0);
3258 p[txt.length()] = '\0';
3264 while (g_ascii_isspace (*p))
3268 while (*q && (*q != '\n') && (*q != '\r')) {
3275 while (q > p && g_ascii_isspace (*q))
3280 uris.push_back (string (p, q - p + 1));
3284 p = strchr (p, '\n');
3296 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3297 if ((*i).substr (0,7) == "file://") {
3298 paths.push_back (Glib::filename_from_uri (*i));
3306 Editor::new_tempo_section ()
3311 Editor::map_transport_state ()
3313 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3315 if (_session && _session->transport_stopped()) {
3316 have_pending_keyboard_selection = false;
3319 update_loop_range_view ();
3325 Editor::begin_selection_op_history ()
3327 selection_op_cmd_depth = 0;
3328 selection_op_history_it = 0;
3330 while(!selection_op_history.empty()) {
3331 delete selection_op_history.front();
3332 selection_op_history.pop_front();
3335 selection_undo_action->set_sensitive (false);
3336 selection_redo_action->set_sensitive (false);
3337 selection_op_history.push_front (&_selection_memento->get_state ());
3341 Editor::begin_reversible_selection_op (string name)
3344 //cerr << name << endl;
3345 /* begin/commit pairs can be nested */
3346 selection_op_cmd_depth++;
3351 Editor::commit_reversible_selection_op ()
3354 if (selection_op_cmd_depth == 1) {
3356 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3358 The user has undone some selection ops and then made a new one,
3359 making anything earlier in the list invalid.
3362 list<XMLNode *>::iterator it = selection_op_history.begin();
3363 list<XMLNode *>::iterator e_it = it;
3364 advance (e_it, selection_op_history_it);
3366 for ( ; it != e_it; ++it) {
3369 selection_op_history.erase (selection_op_history.begin(), e_it);
3372 selection_op_history.push_front (&_selection_memento->get_state ());
3373 selection_op_history_it = 0;
3375 selection_undo_action->set_sensitive (true);
3376 selection_redo_action->set_sensitive (false);
3379 if (selection_op_cmd_depth > 0) {
3380 selection_op_cmd_depth--;
3386 Editor::undo_selection_op ()
3389 selection_op_history_it++;
3391 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3392 if (n == selection_op_history_it) {
3393 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3394 selection_redo_action->set_sensitive (true);
3398 /* is there an earlier entry? */
3399 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3400 selection_undo_action->set_sensitive (false);
3406 Editor::redo_selection_op ()
3409 if (selection_op_history_it > 0) {
3410 selection_op_history_it--;
3413 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3414 if (n == selection_op_history_it) {
3415 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3416 selection_undo_action->set_sensitive (true);
3421 if (selection_op_history_it == 0) {
3422 selection_redo_action->set_sensitive (false);
3428 Editor::begin_reversible_command (string name)
3431 before.push_back (&_selection_memento->get_state ());
3432 _session->begin_reversible_command (name);
3437 Editor::begin_reversible_command (GQuark q)
3440 before.push_back (&_selection_memento->get_state ());
3441 _session->begin_reversible_command (q);
3446 Editor::abort_reversible_command ()
3449 while(!before.empty()) {
3450 delete before.front();
3453 _session->abort_reversible_command ();
3458 Editor::commit_reversible_command ()
3461 if (before.size() == 1) {
3462 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3463 redo_action->set_sensitive(false);
3464 undo_action->set_sensitive(true);
3465 begin_selection_op_history ();
3468 if (before.empty()) {
3469 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3474 _session->commit_reversible_command ();
3479 Editor::history_changed ()
3483 if (undo_action && _session) {
3484 if (_session->undo_depth() == 0) {
3485 label = S_("Command|Undo");
3487 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3489 undo_action->property_label() = label;
3492 if (redo_action && _session) {
3493 if (_session->redo_depth() == 0) {
3496 label = string_compose(_("Redo (%1)"), _session->next_redo());
3498 redo_action->property_label() = label;
3503 Editor::duplicate_range (bool with_dialog)
3507 RegionSelection rs = get_regions_from_selection_and_entered ();
3509 if ( selection->time.length() == 0 && rs.empty()) {
3515 ArdourDialog win (_("Duplicate"));
3516 Label label (_("Number of duplications:"));
3517 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3518 SpinButton spinner (adjustment, 0.0, 1);
3521 win.get_vbox()->set_spacing (12);
3522 win.get_vbox()->pack_start (hbox);
3523 hbox.set_border_width (6);
3524 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3526 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3527 place, visually. so do this by hand.
3530 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3531 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3532 spinner.grab_focus();
3538 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3539 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3540 win.set_default_response (RESPONSE_ACCEPT);
3542 spinner.grab_focus ();
3544 switch (win.run ()) {
3545 case RESPONSE_ACCEPT:
3551 times = adjustment.get_value();
3554 if ((current_mouse_mode() == Editing::MouseRange)) {
3555 if (selection->time.length()) {
3556 duplicate_selection (times);
3558 } else if (get_smart_mode()) {
3559 if (selection->time.length()) {
3560 duplicate_selection (times);
3562 duplicate_some_regions (rs, times);
3564 duplicate_some_regions (rs, times);
3569 Editor::set_edit_mode (EditMode m)
3571 Config->set_edit_mode (m);
3575 Editor::cycle_edit_mode ()
3577 switch (Config->get_edit_mode()) {
3579 if (Profile->get_sae()) {
3580 Config->set_edit_mode (Lock);
3582 Config->set_edit_mode (Ripple);
3587 Config->set_edit_mode (Lock);
3590 Config->set_edit_mode (Slide);
3596 Editor::edit_mode_selection_done ( EditMode m )
3598 Config->set_edit_mode ( m );
3602 Editor::snap_type_selection_done (SnapType snaptype)
3604 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3606 ract->set_active ();
3611 Editor::snap_mode_selection_done (SnapMode mode)
3613 RefPtr<RadioAction> ract = snap_mode_action (mode);
3616 ract->set_active (true);
3621 Editor::cycle_edit_point (bool with_marker)
3623 if(Profile->get_mixbus())
3624 with_marker = false;
3626 switch (_edit_point) {
3628 set_edit_point_preference (EditAtPlayhead);
3630 case EditAtPlayhead:
3632 set_edit_point_preference (EditAtSelectedMarker);
3634 set_edit_point_preference (EditAtMouse);
3637 case EditAtSelectedMarker:
3638 set_edit_point_preference (EditAtMouse);
3644 Editor::edit_point_selection_done (EditPoint ep)
3646 set_edit_point_preference ( ep );
3650 Editor::build_zoom_focus_menu ()
3652 using namespace Menu_Helpers;
3654 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3655 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3656 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3657 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3658 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3659 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3661 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3665 Editor::zoom_focus_selection_done ( ZoomFocus f )
3667 RefPtr<RadioAction> ract = zoom_focus_action (f);
3669 ract->set_active ();
3674 Editor::build_track_count_menu ()
3676 using namespace Menu_Helpers;
3678 if (!Profile->get_mixbus()) {
3679 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3680 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3681 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3682 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3683 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3684 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3685 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3686 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3687 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3688 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3689 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3690 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3691 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3693 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3694 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3695 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3696 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3697 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3698 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3699 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3700 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3701 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3702 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3704 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3705 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3706 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3707 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3708 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3709 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3710 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3711 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3712 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3713 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3714 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3719 Editor::set_zoom_preset (int64_t ms)
3722 temporal_zoom_session();
3726 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3727 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3731 Editor::set_visible_track_count (int32_t n)
3733 _visible_track_count = n;
3735 /* if the canvas hasn't really been allocated any size yet, just
3736 record the desired number of visible tracks and return. when canvas
3737 allocation happens, we will get called again and then we can do the
3741 if (_visible_canvas_height <= 1) {
3747 DisplaySuspender ds;
3749 if (_visible_track_count > 0) {
3750 h = trackviews_height() / _visible_track_count;
3751 std::ostringstream s;
3752 s << _visible_track_count;
3754 } else if (_visible_track_count == 0) {
3756 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3757 if ((*i)->marked_for_display()) {
3761 h = trackviews_height() / n;
3764 /* negative value means that the visible track count has
3765 been overridden by explicit track height changes.
3767 visible_tracks_selector.set_text (X_("*"));
3771 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3772 (*i)->set_height (h);
3775 if (str != visible_tracks_selector.get_text()) {
3776 visible_tracks_selector.set_text (str);
3781 Editor::override_visible_track_count ()
3783 _visible_track_count = -1;
3784 visible_tracks_selector.set_text ( _("*") );
3788 Editor::edit_controls_button_release (GdkEventButton* ev)
3790 if (Keyboard::is_context_menu_event (ev)) {
3791 ARDOUR_UI::instance()->add_route (this);
3792 } else if (ev->button == 1) {
3793 selection->clear_tracks ();
3800 Editor::mouse_select_button_release (GdkEventButton* ev)
3802 /* this handles just right-clicks */
3804 if (ev->button != 3) {
3812 Editor::set_zoom_focus (ZoomFocus f)
3814 string str = zoom_focus_strings[(int)f];
3816 if (str != zoom_focus_selector.get_text()) {
3817 zoom_focus_selector.set_text (str);
3820 if (zoom_focus != f) {
3827 Editor::cycle_zoom_focus ()
3829 switch (zoom_focus) {
3831 set_zoom_focus (ZoomFocusRight);
3833 case ZoomFocusRight:
3834 set_zoom_focus (ZoomFocusCenter);
3836 case ZoomFocusCenter:
3837 set_zoom_focus (ZoomFocusPlayhead);
3839 case ZoomFocusPlayhead:
3840 set_zoom_focus (ZoomFocusMouse);
3842 case ZoomFocusMouse:
3843 set_zoom_focus (ZoomFocusEdit);
3846 set_zoom_focus (ZoomFocusLeft);
3852 Editor::ensure_float (Window& win)
3854 win.set_transient_for (*this);
3858 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3860 /* recover or initialize pane positions. do this here rather than earlier because
3861 we don't want the positions to change the child allocations, which they seem to do.
3867 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3876 XMLNode* geometry = find_named_node (*node, "geometry");
3878 if (which == static_cast<Paned*> (&edit_pane)) {
3880 if (done & Horizontal) {
3884 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3885 _notebook_shrunk = string_is_affirmative (prop->value ());
3888 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3889 /* initial allocation is 90% to canvas, 10% to notebook */
3890 pos = (int) floor (alloc.get_width() * 0.90f);
3891 snprintf (buf, sizeof(buf), "%d", pos);
3893 pos = atoi (prop->value());
3896 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3897 edit_pane.set_position (pos);
3900 done = (Pane) (done | Horizontal);
3902 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3904 if (done & Vertical) {
3908 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3909 /* initial allocation is 90% to canvas, 10% to summary */
3910 pos = (int) floor (alloc.get_height() * 0.90f);
3911 snprintf (buf, sizeof(buf), "%d", pos);
3914 pos = atoi (prop->value());
3917 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3918 editor_summary_pane.set_position (pos);
3921 done = (Pane) (done | Vertical);
3926 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3928 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3929 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3930 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3931 top_hbox.remove (toolbar_frame);
3936 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3938 if (toolbar_frame.get_parent() == 0) {
3939 top_hbox.pack_end (toolbar_frame);
3944 Editor::set_show_measures (bool yn)
3946 if (_show_measures != yn) {
3949 if ((_show_measures = yn) == true) {
3951 tempo_lines->show();
3954 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3955 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3957 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3958 draw_measures (begin, end);
3966 Editor::toggle_follow_playhead ()
3968 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3970 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3971 set_follow_playhead (tact->get_active());
3975 /** @param yn true to follow playhead, otherwise false.
3976 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3979 Editor::set_follow_playhead (bool yn, bool catch_up)
3981 if (_follow_playhead != yn) {
3982 if ((_follow_playhead = yn) == true && catch_up) {
3984 reset_x_origin_to_follow_playhead ();
3991 Editor::toggle_stationary_playhead ()
3993 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3995 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3996 set_stationary_playhead (tact->get_active());
4001 Editor::set_stationary_playhead (bool yn)
4003 if (_stationary_playhead != yn) {
4004 if ((_stationary_playhead = yn) == true) {
4006 // FIXME need a 3.0 equivalent of this 2.X call
4007 // update_current_screen ();
4014 Editor::playlist_selector () const
4016 return *_playlist_selector;
4020 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4022 if (paste_count == 0) {
4023 /* don't bother calculating an offset that will be zero anyway */
4027 /* calculate basic unsnapped multi-paste offset */
4028 framecnt_t offset = paste_count * duration;
4030 /* snap offset so pos + offset is aligned to the grid */
4031 framepos_t offset_pos = pos + offset;
4032 snap_to(offset_pos, RoundUpMaybe);
4033 offset = offset_pos - pos;
4039 Editor::get_grid_beat_divisions(framepos_t position)
4041 switch (_snap_type) {
4042 case SnapToBeatDiv128: return 128;
4043 case SnapToBeatDiv64: return 64;
4044 case SnapToBeatDiv32: return 32;
4045 case SnapToBeatDiv28: return 28;
4046 case SnapToBeatDiv24: return 24;
4047 case SnapToBeatDiv20: return 20;
4048 case SnapToBeatDiv16: return 16;
4049 case SnapToBeatDiv14: return 14;
4050 case SnapToBeatDiv12: return 12;
4051 case SnapToBeatDiv10: return 10;
4052 case SnapToBeatDiv8: return 8;
4053 case SnapToBeatDiv7: return 7;
4054 case SnapToBeatDiv6: return 6;
4055 case SnapToBeatDiv5: return 5;
4056 case SnapToBeatDiv4: return 4;
4057 case SnapToBeatDiv3: return 3;
4058 case SnapToBeatDiv2: return 2;
4065 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4069 const unsigned divisions = get_grid_beat_divisions(position);
4071 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4074 switch (_snap_type) {
4076 return Evoral::Beats(1.0);
4079 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4087 return Evoral::Beats();
4091 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4095 ret = nudge_clock->current_duration (pos);
4096 next = ret + 1; /* XXXX fix me */
4102 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4104 ArdourDialog dialog (_("Playlist Deletion"));
4105 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4106 "If it is kept, its audio files will not be cleaned.\n"
4107 "If it is deleted, audio files used by it alone will be cleaned."),
4110 dialog.set_position (WIN_POS_CENTER);
4111 dialog.get_vbox()->pack_start (label);
4115 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4116 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4117 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4119 switch (dialog.run ()) {
4120 case RESPONSE_ACCEPT:
4121 /* delete the playlist */
4125 case RESPONSE_REJECT:
4126 /* keep the playlist */
4138 Editor::audio_region_selection_covers (framepos_t where)
4140 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4141 if ((*a)->region()->covers (where)) {
4150 Editor::prepare_for_cleanup ()
4152 cut_buffer->clear_regions ();
4153 cut_buffer->clear_playlists ();
4155 selection->clear_regions ();
4156 selection->clear_playlists ();
4158 _regions->suspend_redisplay ();
4162 Editor::finish_cleanup ()
4164 _regions->resume_redisplay ();
4168 Editor::transport_loop_location()
4171 return _session->locations()->auto_loop_location();
4178 Editor::transport_punch_location()
4181 return _session->locations()->auto_punch_location();
4188 Editor::control_layout_scroll (GdkEventScroll* ev)
4190 /* Just forward to the normal canvas scroll method. The coordinate
4191 systems are different but since the canvas is always larger than the
4192 track headers, and aligned with the trackview area, this will work.
4194 In the not too distant future this layout is going away anyway and
4195 headers will be on the canvas.
4197 return canvas_scroll_event (ev, false);
4201 Editor::session_state_saved (string)
4204 _snapshots->redisplay ();
4208 Editor::update_tearoff_visibility()
4210 bool visible = ARDOUR_UI::config()->get_keep_tearoffs();
4211 _mouse_mode_tearoff->set_visible (visible);
4212 _tools_tearoff->set_visible (visible);
4213 if (_zoom_tearoff) {
4214 _zoom_tearoff->set_visible (visible);
4219 Editor::reattach_all_tearoffs ()
4221 if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
4222 if (_tools_tearoff) _tools_tearoff->put_it_back ();
4223 if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
4227 Editor::maximise_editing_space ()
4239 Editor::restore_editing_space ()
4251 * Make new playlists for a given track and also any others that belong
4252 * to the same active route group with the `select' property.
4257 Editor::new_playlists (TimeAxisView* v)
4259 begin_reversible_command (_("new playlists"));
4260 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4261 _session->playlists->get (playlists);
4262 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4263 commit_reversible_command ();
4267 * Use a copy of the current playlist for a given track and also any others that belong
4268 * to the same active route group with the `select' property.
4273 Editor::copy_playlists (TimeAxisView* v)
4275 begin_reversible_command (_("copy playlists"));
4276 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4277 _session->playlists->get (playlists);
4278 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4279 commit_reversible_command ();
4282 /** Clear the current playlist for a given track and also any others that belong
4283 * to the same active route group with the `select' property.
4288 Editor::clear_playlists (TimeAxisView* v)
4290 begin_reversible_command (_("clear playlists"));
4291 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4292 _session->playlists->get (playlists);
4293 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4294 commit_reversible_command ();
4298 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4300 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4304 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4306 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4310 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4312 atv.clear_playlist ();
4316 Editor::on_key_press_event (GdkEventKey* ev)
4318 return key_press_focus_accelerator_handler (*this, ev);
4322 Editor::on_key_release_event (GdkEventKey* ev)
4324 return Gtk::Window::on_key_release_event (ev);
4325 // return key_press_focus_accelerator_handler (*this, ev);
4329 Editor::get_y_origin () const
4331 return vertical_adjustment.get_value ();
4334 /** Queue up a change to the viewport x origin.
4335 * @param frame New x origin.
4338 Editor::reset_x_origin (framepos_t frame)
4340 pending_visual_change.add (VisualChange::TimeOrigin);
4341 pending_visual_change.time_origin = frame;
4342 ensure_visual_change_idle_handler ();
4346 Editor::reset_y_origin (double y)
4348 pending_visual_change.add (VisualChange::YOrigin);
4349 pending_visual_change.y_origin = y;
4350 ensure_visual_change_idle_handler ();
4354 Editor::reset_zoom (framecnt_t spp)
4356 if (spp == samples_per_pixel) {
4360 pending_visual_change.add (VisualChange::ZoomLevel);
4361 pending_visual_change.samples_per_pixel = spp;
4362 ensure_visual_change_idle_handler ();
4366 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4368 reset_x_origin (frame);
4371 if (!no_save_visual) {
4372 undo_visual_stack.push_back (current_visual_state(false));
4376 Editor::VisualState::VisualState (bool with_tracks)
4377 : gui_state (with_tracks ? new GUIObjectState : 0)
4381 Editor::VisualState::~VisualState ()
4386 Editor::VisualState*
4387 Editor::current_visual_state (bool with_tracks)
4389 VisualState* vs = new VisualState (with_tracks);
4390 vs->y_position = vertical_adjustment.get_value();
4391 vs->samples_per_pixel = samples_per_pixel;
4392 vs->leftmost_frame = leftmost_frame;
4393 vs->zoom_focus = zoom_focus;
4396 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4403 Editor::undo_visual_state ()
4405 if (undo_visual_stack.empty()) {
4409 VisualState* vs = undo_visual_stack.back();
4410 undo_visual_stack.pop_back();
4413 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4416 use_visual_state (*vs);
4421 Editor::redo_visual_state ()
4423 if (redo_visual_stack.empty()) {
4427 VisualState* vs = redo_visual_stack.back();
4428 redo_visual_stack.pop_back();
4430 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4431 // why do we check here?
4432 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4435 use_visual_state (*vs);
4440 Editor::swap_visual_state ()
4442 if (undo_visual_stack.empty()) {
4443 redo_visual_state ();
4445 undo_visual_state ();
4450 Editor::use_visual_state (VisualState& vs)
4452 PBD::Unwinder<bool> nsv (no_save_visual, true);
4453 DisplaySuspender ds;
4455 vertical_adjustment.set_value (vs.y_position);
4457 set_zoom_focus (vs.zoom_focus);
4458 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4461 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4463 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4464 (*i)->reset_visual_state ();
4468 _routes->update_visibility ();
4471 /** This is the core function that controls the zoom level of the canvas. It is called
4472 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4473 * @param spp new number of samples per pixel
4476 Editor::set_samples_per_pixel (framecnt_t spp)
4482 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4483 const framecnt_t lots_of_pixels = 4000;
4485 /* if the zoom level is greater than what you'd get trying to display 3
4486 * days of audio on a really big screen, then it's too big.
4489 if (spp * lots_of_pixels > three_days) {
4493 samples_per_pixel = spp;
4496 tempo_lines->tempo_map_changed();
4499 bool const showing_time_selection = selection->time.length() > 0;
4501 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4502 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4503 (*i)->reshow_selection (selection->time);
4507 ZoomChanged (); /* EMIT_SIGNAL */
4509 ArdourCanvas::GtkCanvasViewport* c;
4511 c = get_track_canvas();
4513 c->canvas()->zoomed ();
4516 if (playhead_cursor) {
4517 playhead_cursor->set_position (playhead_cursor->current_frame ());
4520 refresh_location_display();
4521 _summary->set_overlays_dirty ();
4523 update_marker_labels ();
4529 Editor::queue_visual_videotimeline_update ()
4532 * pending_visual_change.add (VisualChange::VideoTimeline);
4533 * or maybe even more specific: which videotimeline-image
4534 * currently it calls update_video_timeline() to update
4535 * _all outdated_ images on the video-timeline.
4536 * see 'exposeimg()' in video_image_frame.cc
4538 ensure_visual_change_idle_handler ();
4542 Editor::ensure_visual_change_idle_handler ()
4544 if (pending_visual_change.idle_handler_id < 0) {
4545 // see comment in add_to_idle_resize above.
4546 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4547 pending_visual_change.being_handled = false;
4552 Editor::_idle_visual_changer (void* arg)
4554 return static_cast<Editor*>(arg)->idle_visual_changer ();
4558 Editor::idle_visual_changer ()
4560 /* set_horizontal_position() below (and maybe other calls) call
4561 gtk_main_iteration(), so it's possible that a signal will be handled
4562 half-way through this method. If this signal wants an
4563 idle_visual_changer we must schedule another one after this one, so
4564 mark the idle_handler_id as -1 here to allow that. Also make a note
4565 that we are doing the visual change, so that changes in response to
4566 super-rapid-screen-update can be dropped if we are still processing
4570 pending_visual_change.idle_handler_id = -1;
4571 pending_visual_change.being_handled = true;
4573 VisualChange vc = pending_visual_change;
4575 pending_visual_change.pending = (VisualChange::Type) 0;
4577 visual_changer (vc);
4579 pending_visual_change.being_handled = false;
4581 return 0; /* this is always a one-shot call */
4585 Editor::visual_changer (const VisualChange& vc)
4587 double const last_time_origin = horizontal_position ();
4589 if (vc.pending & VisualChange::ZoomLevel) {
4590 set_samples_per_pixel (vc.samples_per_pixel);
4592 compute_fixed_ruler_scale ();
4594 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4595 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4597 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4598 current_bbt_points_begin, current_bbt_points_end);
4599 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4600 current_bbt_points_begin, current_bbt_points_end);
4601 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4603 update_video_timeline();
4606 if (vc.pending & VisualChange::TimeOrigin) {
4607 set_horizontal_position (vc.time_origin / samples_per_pixel);
4610 if (vc.pending & VisualChange::YOrigin) {
4611 vertical_adjustment.set_value (vc.y_origin);
4614 if (last_time_origin == horizontal_position ()) {
4615 /* changed signal not emitted */
4616 update_fixed_rulers ();
4617 redisplay_tempo (true);
4620 if (!(vc.pending & VisualChange::ZoomLevel)) {
4621 update_video_timeline();
4624 _summary->set_overlays_dirty ();
4627 struct EditorOrderTimeAxisSorter {
4628 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4629 return a->order () < b->order ();
4634 Editor::sort_track_selection (TrackViewList& sel)
4636 EditorOrderTimeAxisSorter cmp;
4641 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu, bool from_outside_canvas)
4644 framepos_t where = 0;
4645 EditPoint ep = _edit_point;
4647 if(Profile->get_mixbus())
4648 if (ep == EditAtSelectedMarker)
4651 if (from_outside_canvas && (ep == EditAtMouse)) {
4652 ep = EditAtPlayhead;
4653 } else if (from_context_menu && (ep == EditAtMouse)) {
4654 return canvas_event_sample (&context_click_event, 0, 0);
4657 if (entered_marker) {
4658 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4659 return entered_marker->position();
4662 if (ignore_playhead && ep == EditAtPlayhead) {
4663 ep = EditAtSelectedMarker;
4667 case EditAtPlayhead:
4668 if (_dragging_playhead) {
4669 if (!mouse_frame (where, ignored)) {
4670 /* XXX not right but what can we do ? */
4674 where = _session->audible_frame();
4675 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4678 case EditAtSelectedMarker:
4679 if (!selection->markers.empty()) {
4681 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4684 where = loc->start();
4688 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4696 if (!mouse_frame (where, ignored)) {
4697 /* XXX not right but what can we do ? */
4701 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4709 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4711 if (!_session) return;
4713 begin_reversible_command (cmd);
4717 if ((tll = transport_loop_location()) == 0) {
4718 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4719 XMLNode &before = _session->locations()->get_state();
4720 _session->locations()->add (loc, true);
4721 _session->set_auto_loop_location (loc);
4722 XMLNode &after = _session->locations()->get_state();
4723 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4725 XMLNode &before = tll->get_state();
4726 tll->set_hidden (false, this);
4727 tll->set (start, end);
4728 XMLNode &after = tll->get_state();
4729 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4732 commit_reversible_command ();
4736 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4738 if (!_session) return;
4740 begin_reversible_command (cmd);
4744 if ((tpl = transport_punch_location()) == 0) {
4745 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4746 XMLNode &before = _session->locations()->get_state();
4747 _session->locations()->add (loc, true);
4748 _session->set_auto_punch_location (loc);
4749 XMLNode &after = _session->locations()->get_state();
4750 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4752 XMLNode &before = tpl->get_state();
4753 tpl->set_hidden (false, this);
4754 tpl->set (start, end);
4755 XMLNode &after = tpl->get_state();
4756 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4759 commit_reversible_command ();
4762 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4763 * @param rs List to which found regions are added.
4764 * @param where Time to look at.
4765 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4768 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4770 const TrackViewList* tracks;
4773 tracks = &track_views;
4778 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4780 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4783 boost::shared_ptr<Track> tr;
4784 boost::shared_ptr<Playlist> pl;
4786 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4788 boost::shared_ptr<RegionList> regions = pl->regions_at (
4789 (framepos_t) floor ( (double) where * tr->speed()));
4791 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4792 RegionView* rv = rtv->view()->find_view (*i);
4803 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4805 const TrackViewList* tracks;
4808 tracks = &track_views;
4813 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4814 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4816 boost::shared_ptr<Track> tr;
4817 boost::shared_ptr<Playlist> pl;
4819 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4821 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4822 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4824 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4826 RegionView* rv = rtv->view()->find_view (*i);
4837 /** Get regions using the following method:
4839 * Make a region list using:
4840 * (a) any selected regions
4841 * (b) the intersection of any selected tracks and the edit point(*)
4842 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4844 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4846 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4850 Editor::get_regions_from_selection_and_edit_point ()
4852 RegionSelection regions;
4854 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4855 regions.add (entered_regionview);
4857 regions = selection->regions;
4860 if ( regions.empty() ) {
4861 TrackViewList tracks = selection->tracks;
4863 if (!tracks.empty()) {
4864 /* no region selected or entered, but some selected tracks:
4865 * act on all regions on the selected tracks at the edit point
4867 framepos_t const where = get_preferred_edit_position ();
4868 get_regions_at(regions, where, tracks);
4875 /** Get regions using the following method:
4877 * Make a region list using:
4878 * (a) any selected regions
4879 * (b) the intersection of any selected tracks and the edit point(*)
4880 * (c) if neither exists, then whatever region is under the mouse
4882 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4884 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4887 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4889 RegionSelection regions;
4891 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4892 regions.add (entered_regionview);
4894 regions = selection->regions;
4897 if ( regions.empty() ) {
4898 TrackViewList tracks = selection->tracks;
4900 if (!tracks.empty()) {
4901 /* no region selected or entered, but some selected tracks:
4902 * act on all regions on the selected tracks at the edit point
4904 get_regions_at(regions, pos, tracks);
4911 /** Start with regions that are selected, or the entered regionview if none are selected.
4912 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4913 * of the regions that we started with.
4917 Editor::get_regions_from_selection_and_entered ()
4919 RegionSelection regions = selection->regions;
4921 if (regions.empty() && entered_regionview) {
4922 regions.add (entered_regionview);
4929 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4931 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4932 RouteTimeAxisView* rtav;
4934 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4935 boost::shared_ptr<Playlist> pl;
4936 std::vector<boost::shared_ptr<Region> > results;
4937 boost::shared_ptr<Track> tr;
4939 if ((tr = rtav->track()) == 0) {
4944 if ((pl = (tr->playlist())) != 0) {
4945 boost::shared_ptr<Region> r = pl->region_by_id (id);
4947 RegionView* rv = rtav->view()->find_view (r);
4949 regions.push_back (rv);
4958 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4961 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4962 MidiTimeAxisView* mtav;
4964 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4966 mtav->get_per_region_note_selection (selection);
4973 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4975 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4977 RouteTimeAxisView* tatv;
4979 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4981 boost::shared_ptr<Playlist> pl;
4982 vector<boost::shared_ptr<Region> > results;
4984 boost::shared_ptr<Track> tr;
4986 if ((tr = tatv->track()) == 0) {
4991 if ((pl = (tr->playlist())) != 0) {
4992 if (src_comparison) {
4993 pl->get_source_equivalent_regions (region, results);
4995 pl->get_region_list_equivalent_regions (region, results);
4999 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
5000 if ((marv = tatv->view()->find_view (*ir)) != 0) {
5001 regions.push_back (marv);
5010 Editor::show_rhythm_ferret ()
5012 if (rhythm_ferret == 0) {
5013 rhythm_ferret = new RhythmFerret(*this);
5016 rhythm_ferret->set_session (_session);
5017 rhythm_ferret->show ();
5018 rhythm_ferret->present ();
5022 Editor::first_idle ()
5024 MessageDialog* dialog = 0;
5026 if (track_views.size() > 1) {
5027 dialog = new MessageDialog (
5029 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5033 ARDOUR_UI::instance()->flush_pending ();
5036 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5040 // first idle adds route children (automation tracks), so we need to redisplay here
5041 _routes->redisplay ();
5045 if (_session->undo_depth() == 0) {
5046 undo_action->set_sensitive(false);
5048 redo_action->set_sensitive(false);
5049 begin_selection_op_history ();
5055 Editor::_idle_resize (gpointer arg)
5057 return ((Editor*)arg)->idle_resize ();
5061 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5063 if (resize_idle_id < 0) {
5064 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5065 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5066 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5068 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5069 _pending_resize_amount = 0;
5072 /* make a note of the smallest resulting height, so that we can clamp the
5073 lower limit at TimeAxisView::hSmall */
5075 int32_t min_resulting = INT32_MAX;
5077 _pending_resize_amount += h;
5078 _pending_resize_view = view;
5080 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5082 if (selection->tracks.contains (_pending_resize_view)) {
5083 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5084 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5088 if (min_resulting < 0) {
5093 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5094 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5098 /** Handle pending resizing of tracks */
5100 Editor::idle_resize ()
5102 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5104 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5105 selection->tracks.contains (_pending_resize_view)) {
5107 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5108 if (*i != _pending_resize_view) {
5109 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5114 _pending_resize_amount = 0;
5115 _group_tabs->set_dirty ();
5116 resize_idle_id = -1;
5124 ENSURE_GUI_THREAD (*this, &Editor::located);
5127 playhead_cursor->set_position (_session->audible_frame ());
5128 if (_follow_playhead && !_pending_initial_locate) {
5129 reset_x_origin_to_follow_playhead ();
5133 _pending_locate_request = false;
5134 _pending_initial_locate = false;
5138 Editor::region_view_added (RegionView * rv)
5140 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5141 if (rv->region ()->id () == (*pr)) {
5142 selection->add (rv);
5143 selection->regions.pending.erase (pr);
5148 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5150 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5151 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5152 if (rv->region()->id () == (*rnote).first) {
5153 mrv->select_notes ((*rnote).second);
5154 selection->pending_midi_note_selection.erase(rnote);
5160 _summary->set_background_dirty ();
5164 Editor::region_view_removed ()
5166 _summary->set_background_dirty ();
5170 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5172 TrackViewList::const_iterator j = track_views.begin ();
5173 while (j != track_views.end()) {
5174 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5175 if (rtv && rtv->route() == r) {
5186 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5190 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5191 TimeAxisView* tv = axis_view_from_route (*i);
5201 Editor::suspend_route_redisplay ()
5204 _routes->suspend_redisplay();
5209 Editor::resume_route_redisplay ()
5212 _routes->resume_redisplay();
5217 Editor::add_routes (RouteList& routes)
5219 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5221 RouteTimeAxisView *rtv;
5222 list<RouteTimeAxisView*> new_views;
5224 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5225 boost::shared_ptr<Route> route = (*x);
5227 if (route->is_auditioner() || route->is_monitor()) {
5231 DataType dt = route->input()->default_type();
5233 if (dt == ARDOUR::DataType::AUDIO) {
5234 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5235 rtv->set_route (route);
5236 } else if (dt == ARDOUR::DataType::MIDI) {
5237 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5238 rtv->set_route (route);
5240 throw unknown_type();
5243 new_views.push_back (rtv);
5244 track_views.push_back (rtv);
5246 rtv->effective_gain_display ();
5248 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5249 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5252 if (new_views.size() > 0) {
5253 _routes->routes_added (new_views);
5254 _summary->routes_added (new_views);
5257 if (show_editor_mixer_when_tracks_arrive) {
5258 show_editor_mixer (true);
5261 editor_list_button.set_sensitive (true);
5265 Editor::timeaxisview_deleted (TimeAxisView *tv)
5267 if (tv == entered_track) {
5271 if (_session && _session->deletion_in_progress()) {
5272 /* the situation is under control */
5276 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5278 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5280 _routes->route_removed (tv);
5282 TimeAxisView::Children c = tv->get_child_list ();
5283 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5284 if (entered_track == i->get()) {
5289 /* remove it from the list of track views */
5291 TrackViewList::iterator i;
5293 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5294 i = track_views.erase (i);
5297 /* update whatever the current mixer strip is displaying, if revelant */
5299 boost::shared_ptr<Route> route;
5302 route = rtav->route ();
5305 if (current_mixer_strip && current_mixer_strip->route() == route) {
5307 TimeAxisView* next_tv;
5309 if (track_views.empty()) {
5311 } else if (i == track_views.end()) {
5312 next_tv = track_views.front();
5319 set_selected_mixer_strip (*next_tv);
5321 /* make the editor mixer strip go away setting the
5322 * button to inactive (which also unticks the menu option)
5325 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5331 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5333 if (apply_to_selection) {
5334 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5336 TrackSelection::iterator j = i;
5339 hide_track_in_display (*i, false);
5344 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5346 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5347 // this will hide the mixer strip
5348 set_selected_mixer_strip (*tv);
5351 _routes->hide_track_in_display (*tv);
5356 Editor::sync_track_view_list_and_routes ()
5358 track_views = TrackViewList (_routes->views ());
5360 _summary->set_dirty ();
5361 _group_tabs->set_dirty ();
5363 return false; // do not call again (until needed)
5367 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5369 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5374 /** Find a RouteTimeAxisView by the ID of its route */
5376 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5378 RouteTimeAxisView* v;
5380 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5381 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5382 if(v->route()->id() == id) {
5392 Editor::fit_route_group (RouteGroup *g)
5394 TrackViewList ts = axis_views_from_routes (g->route_list ());
5399 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5401 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5404 _session->cancel_audition ();
5408 if (_session->is_auditioning()) {
5409 _session->cancel_audition ();
5410 if (r == last_audition_region) {
5415 _session->audition_region (r);
5416 last_audition_region = r;
5421 Editor::hide_a_region (boost::shared_ptr<Region> r)
5423 r->set_hidden (true);
5427 Editor::show_a_region (boost::shared_ptr<Region> r)
5429 r->set_hidden (false);
5433 Editor::audition_region_from_region_list ()
5435 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5439 Editor::hide_region_from_region_list ()
5441 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5445 Editor::show_region_in_region_list ()
5447 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5451 Editor::step_edit_status_change (bool yn)
5454 start_step_editing ();
5456 stop_step_editing ();
5461 Editor::start_step_editing ()
5463 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5467 Editor::stop_step_editing ()
5469 step_edit_connection.disconnect ();
5473 Editor::check_step_edit ()
5475 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5476 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5478 mtv->check_step_edit ();
5482 return true; // do it again, till we stop
5486 Editor::scroll_press (Direction dir)
5488 ++_scroll_callbacks;
5490 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5491 /* delay the first auto-repeat */
5497 scroll_backward (1);
5505 scroll_up_one_track ();
5509 scroll_down_one_track ();
5513 /* do hacky auto-repeat */
5514 if (!_scroll_connection.connected ()) {
5516 _scroll_connection = Glib::signal_timeout().connect (
5517 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5520 _scroll_callbacks = 0;
5527 Editor::scroll_release ()
5529 _scroll_connection.disconnect ();
5532 /** Queue a change for the Editor viewport x origin to follow the playhead */
5534 Editor::reset_x_origin_to_follow_playhead ()
5536 framepos_t const frame = playhead_cursor->current_frame ();
5538 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5540 if (_session->transport_speed() < 0) {
5542 if (frame > (current_page_samples() / 2)) {
5543 center_screen (frame-(current_page_samples()/2));
5545 center_screen (current_page_samples()/2);
5552 if (frame < leftmost_frame) {
5554 if (_session->transport_rolling()) {
5555 /* rolling; end up with the playhead at the right of the page */
5556 l = frame - current_page_samples ();
5558 /* not rolling: end up with the playhead 1/4 of the way along the page */
5559 l = frame - current_page_samples() / 4;
5563 if (_session->transport_rolling()) {
5564 /* rolling: end up with the playhead on the left of the page */
5567 /* not rolling: end up with the playhead 3/4 of the way along the page */
5568 l = frame - 3 * current_page_samples() / 4;
5576 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5582 Editor::super_rapid_screen_update ()
5584 if (!_session || !_session->engine().running()) {
5588 /* METERING / MIXER STRIPS */
5590 /* update track meters, if required */
5591 if (is_mapped() && meters_running) {
5592 RouteTimeAxisView* rtv;
5593 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5594 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5595 rtv->fast_update ();
5600 /* and any current mixer strip */
5601 if (current_mixer_strip) {
5602 current_mixer_strip->fast_update ();
5605 /* PLAYHEAD AND VIEWPORT */
5607 framepos_t const frame = _session->audible_frame();
5609 /* There are a few reasons why we might not update the playhead / viewport stuff:
5611 * 1. we don't update things when there's a pending locate request, otherwise
5612 * when the editor requests a locate there is a chance that this method
5613 * will move the playhead before the locate request is processed, causing
5615 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5616 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5619 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5621 last_update_frame = frame;
5623 if (!_dragging_playhead) {
5624 playhead_cursor->set_position (frame);
5627 if (!_stationary_playhead) {
5629 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5630 /* We only do this if we aren't already
5631 handling a visual change (ie if
5632 pending_visual_change.being_handled is
5633 false) so that these requests don't stack
5634 up there are too many of them to handle in
5637 reset_x_origin_to_follow_playhead ();
5642 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5646 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5647 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5648 if (target <= 0.0) {
5651 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5652 target = (target * 0.15) + (current * 0.85);
5658 set_horizontal_position (current);
5667 Editor::session_going_away ()
5669 _have_idled = false;
5671 _session_connections.drop_connections ();
5673 super_rapid_screen_update_connection.disconnect ();
5675 selection->clear ();
5676 cut_buffer->clear ();
5678 clicked_regionview = 0;
5679 clicked_axisview = 0;
5680 clicked_routeview = 0;
5681 entered_regionview = 0;
5683 last_update_frame = 0;
5686 playhead_cursor->hide ();
5688 /* rip everything out of the list displays */
5692 _route_groups->clear ();
5694 /* do this first so that deleting a track doesn't reset cms to null
5695 and thus cause a leak.
5698 if (current_mixer_strip) {
5699 if (current_mixer_strip->get_parent() != 0) {
5700 global_hpacker.remove (*current_mixer_strip);
5702 delete current_mixer_strip;
5703 current_mixer_strip = 0;
5706 /* delete all trackviews */
5708 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5711 track_views.clear ();
5713 nudge_clock->set_session (0);
5715 editor_list_button.set_active(false);
5716 editor_list_button.set_sensitive(false);
5718 /* clear tempo/meter rulers */
5719 remove_metric_marks ();
5721 clear_marker_display ();
5723 stop_step_editing ();
5725 /* get rid of any existing editor mixer strip */
5727 WindowTitle title(Glib::get_application_name());
5728 title += _("Editor");
5730 set_title (title.get_string());
5732 SessionHandlePtr::session_going_away ();
5737 Editor::show_editor_list (bool yn)
5740 _the_notebook.show ();
5742 _the_notebook.hide ();
5747 Editor::change_region_layering_order (bool from_context_menu)
5749 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5751 if (!clicked_routeview) {
5752 if (layering_order_editor) {
5753 layering_order_editor->hide ();
5758 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5764 boost::shared_ptr<Playlist> pl = track->playlist();
5770 if (layering_order_editor == 0) {
5771 layering_order_editor = new RegionLayeringOrderEditor (*this);
5774 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5775 layering_order_editor->maybe_present ();
5779 Editor::update_region_layering_order_editor ()
5781 if (layering_order_editor && layering_order_editor->is_visible ()) {
5782 change_region_layering_order (true);
5787 Editor::setup_fade_images ()
5789 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5790 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5791 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5792 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5793 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5795 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5796 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5797 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5798 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5799 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5801 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5802 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5803 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5804 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5805 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5807 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5808 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5809 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5810 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5811 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5815 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5817 Editor::action_menu_item (std::string const & name)
5819 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5822 return *manage (a->create_menu_item ());
5826 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5828 EventBox* b = manage (new EventBox);
5829 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5830 Label* l = manage (new Label (name));
5834 _the_notebook.append_page (widget, *b);
5838 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5840 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5841 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5844 if (ev->type == GDK_2BUTTON_PRESS) {
5846 /* double-click on a notebook tab shrinks or expands the notebook */
5848 if (_notebook_shrunk) {
5849 if (pre_notebook_shrink_pane_width) {
5850 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5852 _notebook_shrunk = false;
5854 pre_notebook_shrink_pane_width = edit_pane.get_position();
5856 /* this expands the LHS of the edit pane to cover the notebook
5857 PAGE but leaves the tabs visible.
5859 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5860 _notebook_shrunk = true;
5868 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5870 using namespace Menu_Helpers;
5872 MenuList& items = _control_point_context_menu.items ();
5875 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5876 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5877 if (!can_remove_control_point (item)) {
5878 items.back().set_sensitive (false);
5881 _control_point_context_menu.popup (event->button.button, event->button.time);
5885 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5887 using namespace Menu_Helpers;
5889 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5894 /* We need to get the selection here and pass it to the operations, since
5895 popping up the menu will cause a region leave event which clears
5896 entered_regionview. */
5898 MidiRegionView& mrv = note->region_view();
5899 const RegionSelection rs = get_regions_from_selection_and_entered ();
5901 MenuList& items = _note_context_menu.items();
5904 items.push_back(MenuElem(_("Delete"),
5905 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5906 items.push_back(MenuElem(_("Edit..."),
5907 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5908 items.push_back(MenuElem(_("Legatize"),
5909 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5910 items.push_back(MenuElem(_("Quantize..."),
5911 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5912 items.push_back(MenuElem(_("Remove Overlap"),
5913 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5914 items.push_back(MenuElem(_("Transform..."),
5915 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5917 _note_context_menu.popup (event->button.button, event->button.time);
5921 Editor::zoom_vertical_modifier_released()
5923 _stepping_axis_view = 0;
5927 Editor::ui_parameter_changed (string parameter)
5929 if (parameter == "icon-set") {
5930 while (!_cursor_stack.empty()) {
5931 _cursor_stack.pop_back();
5933 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5934 _cursor_stack.push_back(_cursors->grabber);
5935 } else if (parameter == "draggable-playhead") {
5936 if (_verbose_cursor) {
5937 playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());