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/keyboard.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/analysis_graph.h"
69 #include "ardour/audio_track.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/audioregion.h"
72 #include "ardour/lmath.h"
73 #include "ardour/location.h"
74 #include "ardour/profile.h"
75 #include "ardour/route_group.h"
76 #include "ardour/session_playlists.h"
77 #include "ardour/tempo.h"
78 #include "ardour/utils.h"
80 #include "canvas/debug.h"
81 #include "canvas/text.h"
83 #include "control_protocol/control_protocol.h"
86 #include "analysis_window.h"
87 #include "audio_clock.h"
88 #include "audio_region_view.h"
89 #include "audio_streamview.h"
90 #include "audio_time_axis.h"
91 #include "automation_time_axis.h"
92 #include "bundle_manager.h"
93 #include "crossfade_edit.h"
97 #include "editor_cursors.h"
98 #include "editor_drag.h"
99 #include "editor_group_tabs.h"
100 #include "editor_locations.h"
101 #include "editor_regions.h"
102 #include "editor_route_groups.h"
103 #include "editor_routes.h"
104 #include "editor_snapshots.h"
105 #include "editor_summary.h"
106 #include "export_report.h"
107 #include "global_port_matrix.h"
108 #include "gui_object.h"
109 #include "gui_thread.h"
110 #include "keyboard.h"
111 #include "keyeditor.h"
112 #include "luainstance.h"
114 #include "midi_region_view.h"
115 #include "midi_time_axis.h"
116 #include "mixer_strip.h"
117 #include "mixer_ui.h"
118 #include "mouse_cursors.h"
119 #include "note_base.h"
120 #include "playlist_selector.h"
121 #include "public_editor.h"
122 #include "quantize_dialog.h"
123 #include "region_layering_order_editor.h"
124 #include "rgb_macros.h"
125 #include "rhythm_ferret.h"
126 #include "selection.h"
127 #include "simple_progress_dialog.h"
129 #include "tempo_lines.h"
130 #include "time_axis_view.h"
132 #include "tooltips.h"
133 #include "ui_config.h"
135 #include "verbose_cursor.h"
140 using namespace ARDOUR;
141 using namespace ARDOUR_UI_UTILS;
144 using namespace Glib;
145 using namespace Gtkmm2ext;
146 using namespace Editing;
148 using PBD::internationalize;
150 using Gtkmm2ext::Keyboard;
152 double Editor::timebar_height = 15.0;
154 static const gchar *_snap_type_strings[] = {
188 static const gchar *_snap_mode_strings[] = {
195 static const gchar *_edit_point_strings[] = {
202 static const gchar *_edit_mode_strings[] = {
210 static const gchar *_zoom_focus_strings[] = {
220 #ifdef USE_RUBBERBAND
221 static const gchar *_rb_opt_strings[] = {
224 N_("Balanced multitimbral mixture"),
225 N_("Unpitched percussion with stable notes"),
226 N_("Crisp monophonic instrumental"),
227 N_("Unpitched solo percussion"),
228 N_("Resample without preserving pitch"),
233 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
236 pane_size_watcher (Paned* pane)
238 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
242 Quartz: impossible to access
244 so stop that by preventing it from ever getting too narrow. 35
245 pixels is basically a rough guess at the tab width.
250 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
252 gint pos = pane->get_position ();
254 if (pos > max_width_of_lhs) {
255 pane->set_position (max_width_of_lhs);
260 : PublicEditor (global_hpacker)
261 , editor_mixer_strip_width (Wide)
262 , constructed (false)
263 , _playlist_selector (0)
264 , no_save_visual (false)
266 , samples_per_pixel (2048)
267 , zoom_focus (ZoomFocusPlayhead)
268 , mouse_mode (MouseObject)
269 , pre_internal_snap_type (SnapToBeat)
270 , pre_internal_snap_mode (SnapOff)
271 , internal_snap_type (SnapToBeat)
272 , internal_snap_mode (SnapOff)
273 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
274 , _notebook_shrunk (false)
275 , location_marker_color (0)
276 , location_range_color (0)
277 , location_loop_color (0)
278 , location_punch_color (0)
279 , location_cd_marker_color (0)
281 , _show_marker_lines (false)
282 , clicked_axisview (0)
283 , clicked_routeview (0)
284 , clicked_regionview (0)
285 , clicked_selection (0)
286 , clicked_control_point (0)
287 , button_release_can_deselect (true)
288 , _mouse_changed_selection (false)
289 , region_edit_menu_split_item (0)
290 , region_edit_menu_split_multichannel_item (0)
291 , track_region_edit_playlist_menu (0)
292 , track_edit_playlist_submenu (0)
293 , track_selection_edit_playlist_submenu (0)
294 , _popup_region_menu_item (0)
296 , _track_canvas_viewport (0)
297 , within_track_canvas (false)
298 , _verbose_cursor (0)
302 , range_marker_group (0)
303 , transport_marker_group (0)
304 , cd_marker_group (0)
305 , _time_markers_group (0)
306 , hv_scroll_group (0)
308 , cursor_scroll_group (0)
309 , no_scroll_group (0)
310 , _trackview_group (0)
311 , _drag_motion_group (0)
312 , _canvas_drop_zone (0)
313 , no_ruler_shown_update (false)
314 , ruler_grabbed_widget (0)
316 , minsec_mark_interval (0)
317 , minsec_mark_modulo (0)
319 , timecode_mark_modulo (0)
320 , timecode_nmarks (0)
321 , _samples_ruler_interval (0)
324 , bbt_bar_helper_on (0)
325 , bbt_accent_modulo (0)
330 , visible_timebars (0)
331 , editor_ruler_menu (0)
335 , range_marker_bar (0)
336 , transport_marker_bar (0)
338 , minsec_label (_("Mins:Secs"))
339 , bbt_label (_("Bars:Beats"))
340 , timecode_label (_("Timecode"))
341 , samples_label (_("Samples"))
342 , tempo_label (_("Tempo"))
343 , meter_label (_("Meter"))
344 , mark_label (_("Location Markers"))
345 , range_mark_label (_("Range Markers"))
346 , transport_mark_label (_("Loop/Punch Ranges"))
347 , cd_mark_label (_("CD Markers"))
348 , videotl_label (_("Video Timeline"))
350 , playhead_cursor (0)
351 , edit_packer (4, 4, true)
352 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
353 , horizontal_adjustment (0.0, 0.0, 1e16)
354 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
355 , controls_layout (unused_adjustment, vertical_adjustment)
356 , _scroll_callbacks (0)
357 , _visible_canvas_width (0)
358 , _visible_canvas_height (0)
359 , _full_canvas_height (0)
360 , edit_controls_left_menu (0)
361 , edit_controls_right_menu (0)
362 , last_update_frame (0)
363 , cut_buffer_start (0)
364 , cut_buffer_length (0)
365 , button_bindings (0)
369 , current_interthread_info (0)
370 , analysis_window (0)
371 , select_new_marker (false)
373 , scrubbing_direction (0)
374 , scrub_reversals (0)
375 , scrub_reverse_distance (0)
376 , have_pending_keyboard_selection (false)
377 , pending_keyboard_selection_start (0)
378 , _snap_type (SnapToBeat)
379 , _snap_mode (SnapOff)
380 , snap_threshold (5.0)
381 , ignore_gui_changes (false)
382 , _drags (new DragManager (this))
384 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
385 , _dragging_playhead (false)
386 , _dragging_edit_point (false)
387 , _show_measures (true)
388 , _follow_playhead (true)
389 , _stationary_playhead (false)
392 , global_rect_group (0)
393 , time_line_group (0)
394 , tempo_marker_menu (0)
395 , meter_marker_menu (0)
397 , range_marker_menu (0)
398 , transport_marker_menu (0)
399 , new_transport_marker_menu (0)
401 , marker_menu_item (0)
402 , bbt_beat_subdivision (4)
403 , _visible_track_count (-1)
404 , toolbar_selection_clock_table (2,3)
405 , automation_mode_button (_("mode"))
406 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
407 , selection (new Selection (this))
408 , cut_buffer (new Selection (this))
409 , _selection_memento (new SelectionMemento())
410 , _all_region_actions_sensitized (false)
411 , _ignore_region_action (false)
412 , _last_region_menu_was_main (false)
413 , _ignore_follow_edits (false)
414 , cd_marker_bar_drag_rect (0)
415 , range_bar_drag_rect (0)
416 , transport_bar_drag_rect (0)
417 , transport_bar_range_rect (0)
418 , transport_bar_preroll_rect (0)
419 , transport_bar_postroll_rect (0)
420 , transport_loop_range_rect (0)
421 , transport_punch_range_rect (0)
422 , transport_punchin_line (0)
423 , transport_punchout_line (0)
424 , transport_preroll_rect (0)
425 , transport_postroll_rect (0)
427 , rubberband_rect (0)
433 , autoscroll_horizontal_allowed (false)
434 , autoscroll_vertical_allowed (false)
436 , autoscroll_widget (0)
437 , show_gain_after_trim (false)
438 , selection_op_cmd_depth (0)
439 , selection_op_history_it (0)
440 , no_save_instant (false)
442 , current_mixer_strip (0)
443 , show_editor_mixer_when_tracks_arrive (false)
444 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
445 , current_stepping_trackview (0)
446 , last_track_height_step_timestamp (0)
448 , entered_regionview (0)
449 , clear_entered_track (false)
450 , _edit_point (EditAtMouse)
451 , meters_running (false)
453 , _have_idled (false)
454 , resize_idle_id (-1)
455 , _pending_resize_amount (0)
456 , _pending_resize_view (0)
457 , _pending_locate_request (false)
458 , _pending_initial_locate (false)
462 , layering_order_editor (0)
463 , _last_cut_copy_source_track (0)
464 , _region_selection_change_updates_region_list (true)
466 , _following_mixer_selection (false)
467 , _control_point_toggled_on_press (false)
468 , _stepping_axis_view (0)
469 , quantize_dialog (0)
470 , _main_menu_disabler (0)
471 , myactions (X_("editor"))
473 /* we are a singleton */
475 PublicEditor::_instance = this;
479 last_event_time.tv_sec = 0;
480 last_event_time.tv_usec = 0;
482 selection_op_history.clear();
485 snap_type_strings = I18N (_snap_type_strings);
486 snap_mode_strings = I18N (_snap_mode_strings);
487 zoom_focus_strings = I18N (_zoom_focus_strings);
488 edit_mode_strings = I18N (_edit_mode_strings);
489 edit_point_strings = I18N (_edit_point_strings);
490 #ifdef USE_RUBBERBAND
491 rb_opt_strings = I18N (_rb_opt_strings);
495 build_edit_mode_menu();
496 build_zoom_focus_menu();
497 build_track_count_menu();
498 build_snap_mode_menu();
499 build_snap_type_menu();
500 build_edit_point_menu();
502 location_marker_color = UIConfiguration::instance().color ("location marker");
503 location_range_color = UIConfiguration::instance().color ("location range");
504 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
505 location_loop_color = UIConfiguration::instance().color ("location loop");
506 location_punch_color = UIConfiguration::instance().color ("location punch");
508 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
510 TimeAxisView::setup_sizes ();
511 ArdourMarker::setup_sizes (timebar_height);
512 TempoCurve::setup_sizes (timebar_height);
514 bbt_label.set_name ("EditorRulerLabel");
515 bbt_label.set_size_request (-1, (int)timebar_height);
516 bbt_label.set_alignment (1.0, 0.5);
517 bbt_label.set_padding (5,0);
519 bbt_label.set_no_show_all();
520 minsec_label.set_name ("EditorRulerLabel");
521 minsec_label.set_size_request (-1, (int)timebar_height);
522 minsec_label.set_alignment (1.0, 0.5);
523 minsec_label.set_padding (5,0);
524 minsec_label.hide ();
525 minsec_label.set_no_show_all();
526 timecode_label.set_name ("EditorRulerLabel");
527 timecode_label.set_size_request (-1, (int)timebar_height);
528 timecode_label.set_alignment (1.0, 0.5);
529 timecode_label.set_padding (5,0);
530 timecode_label.hide ();
531 timecode_label.set_no_show_all();
532 samples_label.set_name ("EditorRulerLabel");
533 samples_label.set_size_request (-1, (int)timebar_height);
534 samples_label.set_alignment (1.0, 0.5);
535 samples_label.set_padding (5,0);
536 samples_label.hide ();
537 samples_label.set_no_show_all();
539 tempo_label.set_name ("EditorRulerLabel");
540 tempo_label.set_size_request (-1, (int)timebar_height);
541 tempo_label.set_alignment (1.0, 0.5);
542 tempo_label.set_padding (5,0);
544 tempo_label.set_no_show_all();
546 meter_label.set_name ("EditorRulerLabel");
547 meter_label.set_size_request (-1, (int)timebar_height);
548 meter_label.set_alignment (1.0, 0.5);
549 meter_label.set_padding (5,0);
551 meter_label.set_no_show_all();
553 if (Profile->get_trx()) {
554 mark_label.set_text (_("Markers"));
556 mark_label.set_name ("EditorRulerLabel");
557 mark_label.set_size_request (-1, (int)timebar_height);
558 mark_label.set_alignment (1.0, 0.5);
559 mark_label.set_padding (5,0);
561 mark_label.set_no_show_all();
563 cd_mark_label.set_name ("EditorRulerLabel");
564 cd_mark_label.set_size_request (-1, (int)timebar_height);
565 cd_mark_label.set_alignment (1.0, 0.5);
566 cd_mark_label.set_padding (5,0);
567 cd_mark_label.hide();
568 cd_mark_label.set_no_show_all();
570 videotl_bar_height = 4;
571 videotl_label.set_name ("EditorRulerLabel");
572 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
573 videotl_label.set_alignment (1.0, 0.5);
574 videotl_label.set_padding (5,0);
575 videotl_label.hide();
576 videotl_label.set_no_show_all();
578 range_mark_label.set_name ("EditorRulerLabel");
579 range_mark_label.set_size_request (-1, (int)timebar_height);
580 range_mark_label.set_alignment (1.0, 0.5);
581 range_mark_label.set_padding (5,0);
582 range_mark_label.hide();
583 range_mark_label.set_no_show_all();
585 transport_mark_label.set_name ("EditorRulerLabel");
586 transport_mark_label.set_size_request (-1, (int)timebar_height);
587 transport_mark_label.set_alignment (1.0, 0.5);
588 transport_mark_label.set_padding (5,0);
589 transport_mark_label.hide();
590 transport_mark_label.set_no_show_all();
592 initialize_canvas ();
594 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
596 _summary = new EditorSummary (this);
598 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
599 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
601 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
603 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
604 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
606 edit_controls_vbox.set_spacing (0);
607 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
608 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
610 HBox* h = manage (new HBox);
611 _group_tabs = new EditorGroupTabs (this);
612 if (!ARDOUR::Profile->get_trx()) {
613 h->pack_start (*_group_tabs, PACK_SHRINK);
615 h->pack_start (edit_controls_vbox);
616 controls_layout.add (*h);
618 controls_layout.set_name ("EditControlsBase");
619 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
620 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
621 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
623 _cursors = new MouseCursors;
624 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
625 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
627 /* Push default cursor to ever-present bottom of cursor stack. */
628 push_canvas_cursor(_cursors->grabber);
630 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
632 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
633 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
634 pad_line_1->set_outline_color (0xFF0000FF);
640 edit_packer.set_col_spacings (0);
641 edit_packer.set_row_spacings (0);
642 edit_packer.set_homogeneous (false);
643 edit_packer.set_border_width (0);
644 edit_packer.set_name ("EditorWindow");
646 time_bars_event_box.add (time_bars_vbox);
647 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
648 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
650 /* labels for the time bars */
651 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
653 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
655 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
657 bottom_hbox.set_border_width (2);
658 bottom_hbox.set_spacing (3);
660 _route_groups = new EditorRouteGroups (this);
661 _routes = new EditorRoutes (this);
662 _regions = new EditorRegions (this);
663 _snapshots = new EditorSnapshots (this);
664 _locations = new EditorLocations (this);
666 /* these are static location signals */
668 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
669 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
670 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
672 add_notebook_page (_("Regions"), _regions->widget ());
673 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
674 add_notebook_page (_("Snapshots"), _snapshots->widget ());
675 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
676 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
678 _the_notebook.set_show_tabs (true);
679 _the_notebook.set_scrollable (true);
680 _the_notebook.popup_disable ();
681 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
682 _the_notebook.show_all ();
684 _notebook_shrunk = false;
686 editor_summary_pane.pack1(edit_packer);
688 Button* summary_arrows_left_left = manage (new Button);
689 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
690 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
691 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
693 Button* summary_arrows_left_right = manage (new Button);
694 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
695 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
696 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
698 VBox* summary_arrows_left = manage (new VBox);
699 summary_arrows_left->pack_start (*summary_arrows_left_left);
700 summary_arrows_left->pack_start (*summary_arrows_left_right);
702 Button* summary_arrows_right_up = manage (new Button);
703 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
704 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
705 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
707 Button* summary_arrows_right_down = manage (new Button);
708 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
709 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
710 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
712 VBox* summary_arrows_right = manage (new VBox);
713 summary_arrows_right->pack_start (*summary_arrows_right_up);
714 summary_arrows_right->pack_start (*summary_arrows_right_down);
716 Frame* summary_frame = manage (new Frame);
717 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
719 summary_frame->add (*_summary);
720 summary_frame->show ();
722 _summary_hbox.pack_start (*summary_arrows_left, false, false);
723 _summary_hbox.pack_start (*summary_frame, true, true);
724 _summary_hbox.pack_start (*summary_arrows_right, false, false);
726 if (!ARDOUR::Profile->get_trx()) {
727 editor_summary_pane.pack2 (_summary_hbox);
730 edit_pane.pack1 (editor_summary_pane, true, true);
731 if (!ARDOUR::Profile->get_trx()) {
732 edit_pane.pack2 (_the_notebook, false, true);
735 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
737 /* XXX: editor_summary_pane might need similar to the edit_pane */
739 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
741 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
742 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
744 top_hbox.pack_start (toolbar_frame);
746 HBox *hbox = manage (new HBox);
747 hbox->pack_start (edit_pane, true, true);
749 global_vpacker.pack_start (top_hbox, false, false);
750 global_vpacker.pack_start (*hbox, true, true);
751 global_hpacker.pack_start (global_vpacker, true, true);
753 /* need to show the "contents" widget so that notebook will show if tab is switched to
756 global_hpacker.show ();
758 /* register actions now so that set_state() can find them and set toggles/checks etc */
765 _playlist_selector = new PlaylistSelector();
766 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
768 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
772 nudge_forward_button.set_name ("nudge button");
773 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
775 nudge_backward_button.set_name ("nudge button");
776 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
778 fade_context_menu.set_name ("ArdourContextMenu");
780 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
782 /* allow external control surfaces/protocols to do various things */
784 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
785 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
786 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
787 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
788 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
789 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
790 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
791 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
792 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
793 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
794 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
795 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
796 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
797 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
799 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
800 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
801 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
802 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
803 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
805 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
807 /* problematic: has to return a value and thus cannot be x-thread */
809 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
811 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
812 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
814 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
816 _ignore_region_action = false;
817 _last_region_menu_was_main = false;
818 _popup_region_menu_item = 0;
820 _ignore_follow_edits = false;
822 _show_marker_lines = false;
824 /* Button bindings */
826 button_bindings = new Bindings ("editor-mouse");
828 XMLNode* node = button_settings();
830 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
831 button_bindings->load_operation (**i);
837 /* grab current parameter state */
838 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
839 UIConfiguration::instance().map_parameters (pc);
841 setup_fade_images ();
843 LuaInstance::instance(); // instantiate
844 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &Editor::set_script_action_name));
851 delete button_bindings;
853 delete _route_groups;
854 delete _track_canvas_viewport;
857 delete quantize_dialog;
863 delete _playlist_selector;
865 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
871 Editor::button_settings () const
873 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
874 XMLNode* node = find_named_node (*settings, X_("Buttons"));
877 node = new XMLNode (X_("Buttons"));
884 Editor::get_smart_mode () const
886 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
890 Editor::catch_vanishing_regionview (RegionView *rv)
892 /* note: the selection will take care of the vanishing
893 audioregionview by itself.
896 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
900 if (clicked_regionview == rv) {
901 clicked_regionview = 0;
904 if (entered_regionview == rv) {
905 set_entered_regionview (0);
908 if (!_all_region_actions_sensitized) {
909 sensitize_all_region_actions (true);
914 Editor::set_entered_regionview (RegionView* rv)
916 if (rv == entered_regionview) {
920 if (entered_regionview) {
921 entered_regionview->exited ();
924 entered_regionview = rv;
926 if (entered_regionview != 0) {
927 entered_regionview->entered ();
930 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
931 /* This RegionView entry might have changed what region actions
932 are allowed, so sensitize them all in case a key is pressed.
934 sensitize_all_region_actions (true);
939 Editor::set_entered_track (TimeAxisView* tav)
942 entered_track->exited ();
948 entered_track->entered ();
953 Editor::instant_save ()
955 if (!constructed || !ARDOUR_UI::instance()->session_loaded || no_save_instant) {
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 ()
1146 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1147 start_lock_event_timing ();
1152 Editor::start_lock_event_timing ()
1154 /* check if we should lock the GUI every 30 seconds */
1156 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1160 Editor::generic_event_handler (GdkEvent* ev)
1163 case GDK_BUTTON_PRESS:
1164 case GDK_BUTTON_RELEASE:
1165 case GDK_MOTION_NOTIFY:
1167 case GDK_KEY_RELEASE:
1168 if (contents().is_mapped()) {
1169 gettimeofday (&last_event_time, 0);
1173 case GDK_LEAVE_NOTIFY:
1174 switch (ev->crossing.detail) {
1175 case GDK_NOTIFY_UNKNOWN:
1176 case GDK_NOTIFY_INFERIOR:
1177 case GDK_NOTIFY_ANCESTOR:
1179 case GDK_NOTIFY_VIRTUAL:
1180 case GDK_NOTIFY_NONLINEAR:
1181 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1182 /* leaving window, so reset focus, thus ending any and
1183 all text entry operations.
1185 reset_focus (&contents());
1198 Editor::lock_timeout_callback ()
1200 struct timeval now, delta;
1202 gettimeofday (&now, 0);
1204 timersub (&now, &last_event_time, &delta);
1206 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1208 /* don't call again. Returning false will effectively
1209 disconnect us from the timer callback.
1211 unlock() will call start_lock_event_timing() to get things
1221 Editor::map_position_change (framepos_t frame)
1223 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1225 if (_session == 0) {
1229 if (_follow_playhead) {
1230 center_screen (frame);
1233 playhead_cursor->set_position (frame);
1237 Editor::center_screen (framepos_t frame)
1239 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1241 /* if we're off the page, then scroll.
1244 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1245 center_screen_internal (frame, page);
1250 Editor::center_screen_internal (framepos_t frame, float page)
1255 frame -= (framepos_t) page;
1260 reset_x_origin (frame);
1265 Editor::update_title ()
1267 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1269 if (!own_window()) {
1274 bool dirty = _session->dirty();
1276 string session_name;
1278 if (_session->snap_name() != _session->name()) {
1279 session_name = _session->snap_name();
1281 session_name = _session->name();
1285 session_name = "*" + session_name;
1288 WindowTitle title(session_name);
1289 title += S_("Window|Editor");
1290 title += Glib::get_application_name();
1291 own_window()->set_title (title.get_string());
1293 /* ::session_going_away() will have taken care of it */
1298 Editor::set_session (Session *t)
1300 SessionHandlePtr::set_session (t);
1306 _playlist_selector->set_session (_session);
1307 nudge_clock->set_session (_session);
1308 _summary->set_session (_session);
1309 _group_tabs->set_session (_session);
1310 _route_groups->set_session (_session);
1311 _regions->set_session (_session);
1312 _snapshots->set_session (_session);
1313 _routes->set_session (_session);
1314 _locations->set_session (_session);
1316 if (rhythm_ferret) {
1317 rhythm_ferret->set_session (_session);
1320 if (analysis_window) {
1321 analysis_window->set_session (_session);
1325 sfbrowser->set_session (_session);
1328 compute_fixed_ruler_scale ();
1330 /* Make sure we have auto loop and auto punch ranges */
1332 Location* loc = _session->locations()->auto_loop_location();
1334 loc->set_name (_("Loop"));
1337 loc = _session->locations()->auto_punch_location();
1340 loc->set_name (_("Punch"));
1343 refresh_location_display ();
1345 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1346 the selected Marker; this needs the LocationMarker list to be available.
1348 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1349 set_state (*node, Stateful::loading_state_version);
1351 /* catch up with the playhead */
1353 _session->request_locate (playhead_cursor->current_frame ());
1354 _pending_initial_locate = true;
1358 /* These signals can all be emitted by a non-GUI thread. Therefore the
1359 handlers for them must not attempt to directly interact with the GUI,
1360 but use PBD::Signal<T>::connect() which accepts an event loop
1361 ("context") where the handler will be asked to run.
1364 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1365 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1366 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1367 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1368 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1369 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1370 _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::marker_position_changed, this), gui_context());
1371 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1372 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1373 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1374 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1375 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1376 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1377 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1379 playhead_cursor->show ();
1381 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1382 Config->map_parameters (pc);
1383 _session->config.map_parameters (pc);
1385 restore_ruler_visibility ();
1386 //tempo_map_changed (PropertyChange (0));
1387 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1389 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1390 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1393 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1394 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1397 switch (_snap_type) {
1398 case SnapToRegionStart:
1399 case SnapToRegionEnd:
1400 case SnapToRegionSync:
1401 case SnapToRegionBoundary:
1402 build_region_boundary_cache ();
1409 /* register for undo history */
1410 _session->register_with_memento_command_factory(id(), this);
1411 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1413 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1415 LuaInstance::instance()->set_session(_session);
1417 start_updating_meters ();
1421 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1423 if (a->get_name() == "RegionMenu") {
1424 /* When the main menu's region menu is opened, we setup the actions so that they look right
1425 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1426 so we resensitize all region actions when the entered regionview or the region selection
1427 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1428 happens after the region context menu is opened. So we set a flag here, too.
1432 sensitize_the_right_region_actions ();
1433 _last_region_menu_was_main = true;
1438 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1440 using namespace Menu_Helpers;
1442 void (Editor::*emf)(FadeShape);
1443 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1446 images = &_xfade_in_images;
1447 emf = &Editor::set_fade_in_shape;
1449 images = &_xfade_out_images;
1450 emf = &Editor::set_fade_out_shape;
1455 _("Linear (for highly correlated material)"),
1456 *(*images)[FadeLinear],
1457 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1461 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1465 _("Constant power"),
1466 *(*images)[FadeConstantPower],
1467 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1470 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1475 *(*images)[FadeSymmetric],
1476 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1480 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1485 *(*images)[FadeSlow],
1486 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1489 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1494 *(*images)[FadeFast],
1495 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1498 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1501 /** Pop up a context menu for when the user clicks on a start crossfade */
1503 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1505 using namespace Menu_Helpers;
1506 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1511 MenuList& items (xfade_in_context_menu.items());
1514 if (arv->audio_region()->fade_in_active()) {
1515 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1517 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1520 items.push_back (SeparatorElem());
1521 fill_xfade_menu (items, true);
1523 xfade_in_context_menu.popup (button, time);
1526 /** Pop up a context menu for when the user clicks on an end crossfade */
1528 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1530 using namespace Menu_Helpers;
1531 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1536 MenuList& items (xfade_out_context_menu.items());
1539 if (arv->audio_region()->fade_out_active()) {
1540 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1542 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1545 items.push_back (SeparatorElem());
1546 fill_xfade_menu (items, false);
1548 xfade_out_context_menu.popup (button, time);
1552 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1554 using namespace Menu_Helpers;
1555 Menu* (Editor::*build_menu_function)();
1558 switch (item_type) {
1560 case RegionViewName:
1561 case RegionViewNameHighlight:
1562 case LeftFrameHandle:
1563 case RightFrameHandle:
1564 if (with_selection) {
1565 build_menu_function = &Editor::build_track_selection_context_menu;
1567 build_menu_function = &Editor::build_track_region_context_menu;
1572 if (with_selection) {
1573 build_menu_function = &Editor::build_track_selection_context_menu;
1575 build_menu_function = &Editor::build_track_context_menu;
1580 if (clicked_routeview->track()) {
1581 build_menu_function = &Editor::build_track_context_menu;
1583 build_menu_function = &Editor::build_track_bus_context_menu;
1588 /* probably shouldn't happen but if it does, we don't care */
1592 menu = (this->*build_menu_function)();
1593 menu->set_name ("ArdourContextMenu");
1595 /* now handle specific situations */
1597 switch (item_type) {
1599 case RegionViewName:
1600 case RegionViewNameHighlight:
1601 case LeftFrameHandle:
1602 case RightFrameHandle:
1603 if (!with_selection) {
1604 if (region_edit_menu_split_item) {
1605 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1606 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1608 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1611 if (region_edit_menu_split_multichannel_item) {
1612 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1613 region_edit_menu_split_multichannel_item->set_sensitive (true);
1615 region_edit_menu_split_multichannel_item->set_sensitive (false);
1628 /* probably shouldn't happen but if it does, we don't care */
1632 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1634 /* Bounce to disk */
1636 using namespace Menu_Helpers;
1637 MenuList& edit_items = menu->items();
1639 edit_items.push_back (SeparatorElem());
1641 switch (clicked_routeview->audio_track()->freeze_state()) {
1642 case AudioTrack::NoFreeze:
1643 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1646 case AudioTrack::Frozen:
1647 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1650 case AudioTrack::UnFrozen:
1651 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1657 if (item_type == StreamItem && clicked_routeview) {
1658 clicked_routeview->build_underlay_menu(menu);
1661 /* When the region menu is opened, we setup the actions so that they look right
1664 sensitize_the_right_region_actions ();
1665 _last_region_menu_was_main = false;
1667 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1668 menu->popup (button, time);
1672 Editor::build_track_context_menu ()
1674 using namespace Menu_Helpers;
1676 MenuList& edit_items = track_context_menu.items();
1679 add_dstream_context_items (edit_items);
1680 return &track_context_menu;
1684 Editor::build_track_bus_context_menu ()
1686 using namespace Menu_Helpers;
1688 MenuList& edit_items = track_context_menu.items();
1691 add_bus_context_items (edit_items);
1692 return &track_context_menu;
1696 Editor::build_track_region_context_menu ()
1698 using namespace Menu_Helpers;
1699 MenuList& edit_items = track_region_context_menu.items();
1702 /* we've just cleared the track region context menu, so the menu that these
1703 two items were on will have disappeared; stop them dangling.
1705 region_edit_menu_split_item = 0;
1706 region_edit_menu_split_multichannel_item = 0;
1708 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1711 boost::shared_ptr<Track> tr;
1712 boost::shared_ptr<Playlist> pl;
1714 if ((tr = rtv->track())) {
1715 add_region_context_items (edit_items, tr);
1719 add_dstream_context_items (edit_items);
1721 return &track_region_context_menu;
1725 Editor::loudness_analyze_region_selection ()
1730 Selection& s (PublicEditor::instance ().get_selection ());
1731 RegionSelection ars = s.regions;
1732 ARDOUR::AnalysisGraph ag (_session);
1733 framecnt_t total_work = 0;
1735 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1736 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1740 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1743 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1744 total_work += arv->region ()->length ();
1747 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1749 ag.set_total_frames (total_work);
1750 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1753 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1754 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1758 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1762 ag.analyze_region (ar);
1765 if (!ag.canceled ()) {
1766 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1772 Editor::loudness_analyze_range_selection ()
1777 Selection& s (PublicEditor::instance ().get_selection ());
1778 TimeSelection ts = s.time;
1779 ARDOUR::AnalysisGraph ag (_session);
1780 framecnt_t total_work = 0;
1782 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1783 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1787 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1791 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1792 total_work += j->length ();
1796 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1798 ag.set_total_frames (total_work);
1799 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1802 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1803 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1807 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1811 ag.analyze_range (rui->route (), pl, ts);
1814 if (!ag.canceled ()) {
1815 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1821 Editor::spectral_analyze_region_selection ()
1823 if (analysis_window == 0) {
1824 analysis_window = new AnalysisWindow();
1827 analysis_window->set_session(_session);
1829 analysis_window->show_all();
1832 analysis_window->set_regionmode();
1833 analysis_window->analyze();
1835 analysis_window->present();
1839 Editor::spectral_analyze_range_selection()
1841 if (analysis_window == 0) {
1842 analysis_window = new AnalysisWindow();
1845 analysis_window->set_session(_session);
1847 analysis_window->show_all();
1850 analysis_window->set_rangemode();
1851 analysis_window->analyze();
1853 analysis_window->present();
1857 Editor::build_track_selection_context_menu ()
1859 using namespace Menu_Helpers;
1860 MenuList& edit_items = track_selection_context_menu.items();
1861 edit_items.clear ();
1863 add_selection_context_items (edit_items);
1864 // edit_items.push_back (SeparatorElem());
1865 // add_dstream_context_items (edit_items);
1867 return &track_selection_context_menu;
1871 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1873 using namespace Menu_Helpers;
1875 /* OK, stick the region submenu at the top of the list, and then add
1879 RegionSelection rs = get_regions_from_selection_and_entered ();
1881 string::size_type pos = 0;
1882 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1884 /* we have to hack up the region name because "_" has a special
1885 meaning for menu titles.
1888 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1889 menu_item_name.replace (pos, 1, "__");
1893 if (_popup_region_menu_item == 0) {
1894 _popup_region_menu_item = new MenuItem (menu_item_name);
1895 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1896 _popup_region_menu_item->show ();
1898 _popup_region_menu_item->set_label (menu_item_name);
1901 /* No latering allowed in later is higher layering model */
1902 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1903 if (act && Config->get_layer_model() == LaterHigher) {
1904 act->set_sensitive (false);
1906 act->set_sensitive (true);
1909 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1911 edit_items.push_back (*_popup_region_menu_item);
1912 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1913 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1915 edit_items.push_back (SeparatorElem());
1918 /** Add context menu items relevant to selection ranges.
1919 * @param edit_items List to add the items to.
1922 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1924 using namespace Menu_Helpers;
1926 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1927 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1929 edit_items.push_back (SeparatorElem());
1930 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1932 edit_items.push_back (SeparatorElem());
1933 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1934 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1936 edit_items.push_back (SeparatorElem());
1938 edit_items.push_back (
1940 _("Move Range Start to Previous Region Boundary"),
1941 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1945 edit_items.push_back (
1947 _("Move Range Start to Next Region Boundary"),
1948 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1952 edit_items.push_back (
1954 _("Move Range End to Previous Region Boundary"),
1955 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1959 edit_items.push_back (
1961 _("Move Range End to Next Region Boundary"),
1962 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1966 edit_items.push_back (SeparatorElem());
1967 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1968 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1970 edit_items.push_back (SeparatorElem());
1971 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1973 edit_items.push_back (SeparatorElem());
1974 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1975 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1976 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1978 edit_items.push_back (SeparatorElem());
1979 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1981 edit_items.push_back (SeparatorElem());
1982 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1983 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1985 edit_items.push_back (SeparatorElem());
1986 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1987 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1988 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1989 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1990 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1991 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1992 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1998 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2000 using namespace Menu_Helpers;
2004 Menu *play_menu = manage (new Menu);
2005 MenuList& play_items = play_menu->items();
2006 play_menu->set_name ("ArdourContextMenu");
2008 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2009 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2010 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2011 play_items.push_back (SeparatorElem());
2012 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2014 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2018 Menu *select_menu = manage (new Menu);
2019 MenuList& select_items = select_menu->items();
2020 select_menu->set_name ("ArdourContextMenu");
2022 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2023 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2024 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2025 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2026 select_items.push_back (SeparatorElem());
2027 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2028 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2029 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2030 select_items.push_back (SeparatorElem());
2031 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2032 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2033 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2034 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2035 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2036 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2037 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2039 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2043 Menu *cutnpaste_menu = manage (new Menu);
2044 MenuList& cutnpaste_items = cutnpaste_menu->items();
2045 cutnpaste_menu->set_name ("ArdourContextMenu");
2047 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2048 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2049 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2051 cutnpaste_items.push_back (SeparatorElem());
2053 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2054 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2056 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2058 /* Adding new material */
2060 edit_items.push_back (SeparatorElem());
2061 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2062 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2066 Menu *nudge_menu = manage (new Menu());
2067 MenuList& nudge_items = nudge_menu->items();
2068 nudge_menu->set_name ("ArdourContextMenu");
2070 edit_items.push_back (SeparatorElem());
2071 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2072 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2073 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2074 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2076 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2080 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2082 using namespace Menu_Helpers;
2086 Menu *play_menu = manage (new Menu);
2087 MenuList& play_items = play_menu->items();
2088 play_menu->set_name ("ArdourContextMenu");
2090 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2091 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2092 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2096 Menu *select_menu = manage (new Menu);
2097 MenuList& select_items = select_menu->items();
2098 select_menu->set_name ("ArdourContextMenu");
2100 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2101 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2102 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2103 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2104 select_items.push_back (SeparatorElem());
2105 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2106 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2107 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2108 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2110 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2114 Menu *cutnpaste_menu = manage (new Menu);
2115 MenuList& cutnpaste_items = cutnpaste_menu->items();
2116 cutnpaste_menu->set_name ("ArdourContextMenu");
2118 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2119 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2120 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2122 Menu *nudge_menu = manage (new Menu());
2123 MenuList& nudge_items = nudge_menu->items();
2124 nudge_menu->set_name ("ArdourContextMenu");
2126 edit_items.push_back (SeparatorElem());
2127 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2128 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2129 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2130 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2132 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2136 Editor::snap_type() const
2142 Editor::snap_musical() const
2144 switch (_snap_type) {
2145 case SnapToBeatDiv128:
2146 case SnapToBeatDiv64:
2147 case SnapToBeatDiv32:
2148 case SnapToBeatDiv28:
2149 case SnapToBeatDiv24:
2150 case SnapToBeatDiv20:
2151 case SnapToBeatDiv16:
2152 case SnapToBeatDiv14:
2153 case SnapToBeatDiv12:
2154 case SnapToBeatDiv10:
2155 case SnapToBeatDiv8:
2156 case SnapToBeatDiv7:
2157 case SnapToBeatDiv6:
2158 case SnapToBeatDiv5:
2159 case SnapToBeatDiv4:
2160 case SnapToBeatDiv3:
2161 case SnapToBeatDiv2:
2173 Editor::snap_mode() const
2179 Editor::set_snap_to (SnapType st)
2181 unsigned int snap_ind = (unsigned int)st;
2183 if (internal_editing()) {
2184 internal_snap_type = st;
2186 pre_internal_snap_type = st;
2191 if (snap_ind > snap_type_strings.size() - 1) {
2193 _snap_type = (SnapType)snap_ind;
2196 string str = snap_type_strings[snap_ind];
2198 if (str != snap_type_selector.get_text()) {
2199 snap_type_selector.set_text (str);
2204 switch (_snap_type) {
2205 case SnapToBeatDiv128:
2206 case SnapToBeatDiv64:
2207 case SnapToBeatDiv32:
2208 case SnapToBeatDiv28:
2209 case SnapToBeatDiv24:
2210 case SnapToBeatDiv20:
2211 case SnapToBeatDiv16:
2212 case SnapToBeatDiv14:
2213 case SnapToBeatDiv12:
2214 case SnapToBeatDiv10:
2215 case SnapToBeatDiv8:
2216 case SnapToBeatDiv7:
2217 case SnapToBeatDiv6:
2218 case SnapToBeatDiv5:
2219 case SnapToBeatDiv4:
2220 case SnapToBeatDiv3:
2221 case SnapToBeatDiv2: {
2222 std::vector<TempoMap::BBTPoint> grid;
2223 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
2224 compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples());
2225 update_tempo_based_rulers (grid);
2229 case SnapToRegionStart:
2230 case SnapToRegionEnd:
2231 case SnapToRegionSync:
2232 case SnapToRegionBoundary:
2233 build_region_boundary_cache ();
2241 redisplay_tempo (false);
2243 SnapChanged (); /* EMIT SIGNAL */
2247 Editor::set_snap_mode (SnapMode mode)
2249 string str = snap_mode_strings[(int)mode];
2251 if (internal_editing()) {
2252 internal_snap_mode = mode;
2254 pre_internal_snap_mode = mode;
2259 if (str != snap_mode_selector.get_text ()) {
2260 snap_mode_selector.set_text (str);
2267 Editor::set_edit_point_preference (EditPoint ep, bool force)
2269 bool changed = (_edit_point != ep);
2272 if (Profile->get_mixbus())
2273 if (ep == EditAtSelectedMarker)
2274 ep = EditAtPlayhead;
2276 string str = edit_point_strings[(int)ep];
2277 if (str != edit_point_selector.get_text ()) {
2278 edit_point_selector.set_text (str);
2281 update_all_enter_cursors();
2283 if (!force && !changed) {
2287 const char* action=NULL;
2289 switch (_edit_point) {
2290 case EditAtPlayhead:
2291 action = "edit-at-playhead";
2293 case EditAtSelectedMarker:
2294 action = "edit-at-marker";
2297 action = "edit-at-mouse";
2301 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2303 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2307 bool in_track_canvas;
2309 if (!mouse_frame (foo, in_track_canvas)) {
2310 in_track_canvas = false;
2313 reset_canvas_action_sensitivity (in_track_canvas);
2319 Editor::set_state (const XMLNode& node, int version)
2321 XMLProperty const * prop;
2323 PBD::Unwinder<bool> nsi (no_save_instant, true);
2325 Tabbable::set_state (node, version);
2327 if (_session && (prop = node.property ("playhead"))) {
2329 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2331 playhead_cursor->set_position (pos);
2333 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2334 playhead_cursor->set_position (0);
2337 playhead_cursor->set_position (0);
2340 if ((prop = node.property ("mixer-width"))) {
2341 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2344 if ((prop = node.property ("zoom-focus"))) {
2345 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2348 if ((prop = node.property ("zoom"))) {
2349 /* older versions of ardour used floating point samples_per_pixel */
2350 double f = PBD::atof (prop->value());
2351 reset_zoom (llrintf (f));
2353 reset_zoom (samples_per_pixel);
2356 if ((prop = node.property ("visible-track-count"))) {
2357 set_visible_track_count (PBD::atoi (prop->value()));
2360 if ((prop = node.property ("snap-to"))) {
2361 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2362 set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
2365 if ((prop = node.property ("snap-mode"))) {
2366 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2367 /* set text of Dropdown. in case _snap_mode == SnapOff (default)
2368 * snap_mode_selection_done() will only mark an already active item as active
2369 * which does not trigger set_text().
2371 set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode));
2374 if ((prop = node.property ("internal-snap-to"))) {
2375 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2378 if ((prop = node.property ("internal-snap-mode"))) {
2379 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2382 if ((prop = node.property ("pre-internal-snap-to"))) {
2383 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2386 if ((prop = node.property ("pre-internal-snap-mode"))) {
2387 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2390 if ((prop = node.property ("mouse-mode"))) {
2391 MouseMode m = str2mousemode(prop->value());
2392 set_mouse_mode (m, true);
2394 set_mouse_mode (MouseObject, true);
2397 if ((prop = node.property ("left-frame")) != 0) {
2399 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2403 reset_x_origin (pos);
2407 if ((prop = node.property ("y-origin")) != 0) {
2408 reset_y_origin (atof (prop->value ()));
2411 if ((prop = node.property ("join-object-range"))) {
2412 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2413 bool yn = string_is_affirmative (prop->value());
2415 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2416 tact->set_active (!yn);
2417 tact->set_active (yn);
2419 set_mouse_mode(mouse_mode, true);
2422 if ((prop = node.property ("edit-point"))) {
2423 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2426 if ((prop = node.property ("show-measures"))) {
2427 bool yn = string_is_affirmative (prop->value());
2428 _show_measures = yn;
2431 if ((prop = node.property ("follow-playhead"))) {
2432 bool yn = string_is_affirmative (prop->value());
2433 set_follow_playhead (yn);
2436 if ((prop = node.property ("stationary-playhead"))) {
2437 bool yn = string_is_affirmative (prop->value());
2438 set_stationary_playhead (yn);
2441 if ((prop = node.property ("region-list-sort-type"))) {
2442 RegionListSortType st;
2443 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2446 if ((prop = node.property ("show-editor-mixer"))) {
2448 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2451 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2452 bool yn = string_is_affirmative (prop->value());
2454 /* do it twice to force the change */
2456 tact->set_active (!yn);
2457 tact->set_active (yn);
2460 if ((prop = node.property ("show-editor-list"))) {
2462 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2465 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2466 bool yn = string_is_affirmative (prop->value());
2468 /* do it twice to force the change */
2470 tact->set_active (!yn);
2471 tact->set_active (yn);
2474 if ((prop = node.property (X_("editor-list-page")))) {
2475 _the_notebook.set_current_page (atoi (prop->value ()));
2478 if ((prop = node.property (X_("show-marker-lines")))) {
2479 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2481 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2482 bool yn = string_is_affirmative (prop->value ());
2484 tact->set_active (!yn);
2485 tact->set_active (yn);
2488 XMLNodeList children = node.children ();
2489 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2490 selection->set_state (**i, Stateful::current_state_version);
2491 _regions->set_state (**i);
2494 if ((prop = node.property ("maximised"))) {
2495 bool yn = string_is_affirmative (prop->value());
2496 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2498 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2499 bool fs = tact && tact->get_active();
2501 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2505 if ((prop = node.property ("nudge-clock-value"))) {
2507 sscanf (prop->value().c_str(), "%" PRId64, &f);
2508 nudge_clock->set (f);
2510 nudge_clock->set_mode (AudioClock::Timecode);
2511 nudge_clock->set (_session->frame_rate() * 5, true);
2516 * Not all properties may have been in XML, but
2517 * those that are linked to a private variable may need changing
2522 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2524 yn = _show_measures;
2525 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2526 /* do it twice to force the change */
2527 tact->set_active (!yn);
2528 tact->set_active (yn);
2531 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2532 yn = _follow_playhead;
2534 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2535 if (tact->get_active() != yn) {
2536 tact->set_active (yn);
2540 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2541 yn = _stationary_playhead;
2543 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2544 if (tact->get_active() != yn) {
2545 tact->set_active (yn);
2550 return LuaInstance::instance()->set_state(node);
2554 Editor::get_state ()
2556 XMLNode* node = new XMLNode (X_("Editor"));
2559 id().print (buf, sizeof (buf));
2560 node->add_property ("id", buf);
2562 node->add_child_nocopy (Tabbable::get_state());
2564 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2565 node->add_property("edit-horizontal-pane-pos", string(buf));
2566 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2567 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2568 node->add_property("edit-vertical-pane-pos", string(buf));
2570 maybe_add_mixer_strip_width (*node);
2572 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2574 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2575 node->add_property ("zoom", buf);
2576 node->add_property ("snap-to", enum_2_string (_snap_type));
2577 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2578 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2579 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2580 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2581 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2582 node->add_property ("edit-point", enum_2_string (_edit_point));
2583 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2584 node->add_property ("visible-track-count", buf);
2586 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2587 node->add_property ("playhead", buf);
2588 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2589 node->add_property ("left-frame", buf);
2590 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2591 node->add_property ("y-origin", buf);
2593 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2594 node->add_property ("maximised", _maximised ? "yes" : "no");
2595 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2596 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2597 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2598 node->add_property ("mouse-mode", enum2str(mouse_mode));
2599 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2601 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2603 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2604 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2607 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2609 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2610 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2613 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2614 node->add_property (X_("editor-list-page"), buf);
2616 if (button_bindings) {
2617 XMLNode* bb = new XMLNode (X_("Buttons"));
2618 button_bindings->save (*bb);
2619 node->add_child_nocopy (*bb);
2622 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2624 node->add_child_nocopy (selection->get_state ());
2625 node->add_child_nocopy (_regions->get_state ());
2627 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2628 node->add_property ("nudge-clock-value", buf);
2630 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2631 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2636 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2637 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2639 * @return pair: TimeAxisView that y is over, layer index.
2641 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2642 * in stacked or expanded region display mode, otherwise 0.
2644 std::pair<TimeAxisView *, double>
2645 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2647 if (!trackview_relative_offset) {
2648 y -= _trackview_group->canvas_origin().y;
2652 return std::make_pair ( (TimeAxisView *) 0, 0);
2655 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2657 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2664 return std::make_pair ( (TimeAxisView *) 0, 0);
2667 /** Snap a position to the grid, if appropriate, taking into account current
2668 * grid settings and also the state of any snap modifier keys that may be pressed.
2669 * @param start Position to snap.
2670 * @param event Event to get current key modifier information from, or 0.
2673 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2675 if (!_session || !event) {
2679 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2680 if (_snap_mode == SnapOff) {
2681 snap_to_internal (start, direction, for_mark);
2684 if (_snap_mode != SnapOff) {
2685 snap_to_internal (start, direction, for_mark);
2686 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2687 /* SnapOff, but we pressed the snap_delta modifier */
2688 snap_to_internal (start, direction, for_mark);
2694 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2696 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2700 snap_to_internal (start, direction, for_mark, ensure_snap);
2704 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2706 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2707 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2709 switch (_snap_type) {
2710 case SnapToTimecodeFrame:
2711 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2712 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2713 /* start is already on a whole timecode frame, do nothing */
2714 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2715 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2717 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2721 case SnapToTimecodeSeconds:
2722 if (_session->config.get_timecode_offset_negative()) {
2723 start += _session->config.get_timecode_offset ();
2725 start -= _session->config.get_timecode_offset ();
2727 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2728 (start % one_timecode_second == 0)) {
2729 /* start is already on a whole second, do nothing */
2730 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2731 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2733 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2736 if (_session->config.get_timecode_offset_negative()) {
2737 start -= _session->config.get_timecode_offset ();
2739 start += _session->config.get_timecode_offset ();
2743 case SnapToTimecodeMinutes:
2744 if (_session->config.get_timecode_offset_negative()) {
2745 start += _session->config.get_timecode_offset ();
2747 start -= _session->config.get_timecode_offset ();
2749 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2750 (start % one_timecode_minute == 0)) {
2751 /* start is already on a whole minute, do nothing */
2752 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2753 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2755 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2757 if (_session->config.get_timecode_offset_negative()) {
2758 start -= _session->config.get_timecode_offset ();
2760 start += _session->config.get_timecode_offset ();
2764 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2765 abort(); /*NOTREACHED*/
2770 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2772 const framepos_t one_second = _session->frame_rate();
2773 const framepos_t one_minute = _session->frame_rate() * 60;
2774 framepos_t presnap = start;
2778 switch (_snap_type) {
2779 case SnapToTimecodeFrame:
2780 case SnapToTimecodeSeconds:
2781 case SnapToTimecodeMinutes:
2782 return timecode_snap_to_internal (start, direction, for_mark);
2785 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2786 start % (one_second/75) == 0) {
2787 /* start is already on a whole CD frame, do nothing */
2788 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2789 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2791 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2796 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2797 start % one_second == 0) {
2798 /* start is already on a whole second, do nothing */
2799 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2800 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2802 start = (framepos_t) floor ((double) start / one_second) * one_second;
2807 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2808 start % one_minute == 0) {
2809 /* start is already on a whole minute, do nothing */
2810 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2811 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2813 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2818 start = _session->tempo_map().round_to_bar (start, direction);
2822 start = _session->tempo_map().round_to_beat (start, direction);
2825 case SnapToBeatDiv128:
2826 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2828 case SnapToBeatDiv64:
2829 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2831 case SnapToBeatDiv32:
2832 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2834 case SnapToBeatDiv28:
2835 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2837 case SnapToBeatDiv24:
2838 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2840 case SnapToBeatDiv20:
2841 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2843 case SnapToBeatDiv16:
2844 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2846 case SnapToBeatDiv14:
2847 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2849 case SnapToBeatDiv12:
2850 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2852 case SnapToBeatDiv10:
2853 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2855 case SnapToBeatDiv8:
2856 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2858 case SnapToBeatDiv7:
2859 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2861 case SnapToBeatDiv6:
2862 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2864 case SnapToBeatDiv5:
2865 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2867 case SnapToBeatDiv4:
2868 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2870 case SnapToBeatDiv3:
2871 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2873 case SnapToBeatDiv2:
2874 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2882 _session->locations()->marks_either_side (start, before, after);
2884 if (before == max_framepos && after == max_framepos) {
2885 /* No marks to snap to, so just don't snap */
2887 } else if (before == max_framepos) {
2889 } else if (after == max_framepos) {
2891 } else if (before != max_framepos && after != max_framepos) {
2892 /* have before and after */
2893 if ((start - before) < (after - start)) {
2902 case SnapToRegionStart:
2903 case SnapToRegionEnd:
2904 case SnapToRegionSync:
2905 case SnapToRegionBoundary:
2906 if (!region_boundary_cache.empty()) {
2908 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2909 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2911 if (direction > 0) {
2912 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2914 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2917 if (next != region_boundary_cache.begin ()) {
2922 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2923 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2925 if (start > (p + n) / 2) {
2934 switch (_snap_mode) {
2944 if (presnap > start) {
2945 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2949 } else if (presnap < start) {
2950 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2956 /* handled at entry */
2964 Editor::setup_toolbar ()
2966 HBox* mode_box = manage(new HBox);
2967 mode_box->set_border_width (2);
2968 mode_box->set_spacing(2);
2970 HBox* mouse_mode_box = manage (new HBox);
2971 HBox* mouse_mode_hbox = manage (new HBox);
2972 VBox* mouse_mode_vbox = manage (new VBox);
2973 Alignment* mouse_mode_align = manage (new Alignment);
2975 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2976 mouse_mode_size_group->add_widget (smart_mode_button);
2977 mouse_mode_size_group->add_widget (mouse_move_button);
2978 mouse_mode_size_group->add_widget (mouse_cut_button);
2979 mouse_mode_size_group->add_widget (mouse_select_button);
2980 mouse_mode_size_group->add_widget (mouse_timefx_button);
2981 mouse_mode_size_group->add_widget (mouse_audition_button);
2982 mouse_mode_size_group->add_widget (mouse_draw_button);
2983 mouse_mode_size_group->add_widget (mouse_content_button);
2985 mouse_mode_size_group->add_widget (zoom_in_button);
2986 mouse_mode_size_group->add_widget (zoom_out_button);
2987 mouse_mode_size_group->add_widget (zoom_preset_selector);
2988 mouse_mode_size_group->add_widget (zoom_out_full_button);
2989 mouse_mode_size_group->add_widget (zoom_focus_selector);
2991 mouse_mode_size_group->add_widget (tav_shrink_button);
2992 mouse_mode_size_group->add_widget (tav_expand_button);
2993 mouse_mode_size_group->add_widget (visible_tracks_selector);
2995 mouse_mode_size_group->add_widget (snap_type_selector);
2996 mouse_mode_size_group->add_widget (snap_mode_selector);
2998 mouse_mode_size_group->add_widget (edit_point_selector);
2999 mouse_mode_size_group->add_widget (edit_mode_selector);
3001 mouse_mode_size_group->add_widget (*nudge_clock);
3002 mouse_mode_size_group->add_widget (nudge_forward_button);
3003 mouse_mode_size_group->add_widget (nudge_backward_button);
3005 mouse_mode_hbox->set_spacing (2);
3007 if (!ARDOUR::Profile->get_trx()) {
3008 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
3011 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
3012 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
3014 if (!ARDOUR::Profile->get_mixbus()) {
3015 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
3018 if (!ARDOUR::Profile->get_trx()) {
3019 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
3020 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
3021 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
3022 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
3025 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
3027 mouse_mode_align->add (*mouse_mode_vbox);
3028 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
3030 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
3032 edit_mode_selector.set_name ("mouse mode button");
3034 if (!ARDOUR::Profile->get_trx()) {
3035 mode_box->pack_start (edit_mode_selector, false, false);
3038 mode_box->pack_start (*mouse_mode_box, false, false);
3042 _zoom_box.set_spacing (2);
3043 _zoom_box.set_border_width (2);
3047 zoom_preset_selector.set_name ("zoom button");
3048 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3049 zoom_preset_selector.set_size_request (42, -1);
3051 zoom_in_button.set_name ("zoom button");
3052 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3053 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3054 zoom_in_button.set_related_action (act);
3056 zoom_out_button.set_name ("zoom button");
3057 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3058 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3059 zoom_out_button.set_related_action (act);
3061 zoom_out_full_button.set_name ("zoom button");
3062 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3063 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3064 zoom_out_full_button.set_related_action (act);
3066 zoom_focus_selector.set_name ("zoom button");
3068 if (ARDOUR::Profile->get_mixbus()) {
3069 _zoom_box.pack_start (zoom_preset_selector, false, false);
3070 } else if (ARDOUR::Profile->get_trx()) {
3071 mode_box->pack_start (zoom_out_button, false, false);
3072 mode_box->pack_start (zoom_in_button, false, false);
3074 _zoom_box.pack_start (zoom_out_button, false, false);
3075 _zoom_box.pack_start (zoom_in_button, false, false);
3076 _zoom_box.pack_start (zoom_out_full_button, false, false);
3077 _zoom_box.pack_start (zoom_focus_selector, false, false);
3080 /* Track zoom buttons */
3081 visible_tracks_selector.set_name ("zoom button");
3082 if (Profile->get_mixbus()) {
3083 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3084 visible_tracks_selector.set_size_request (42, -1);
3086 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3089 tav_expand_button.set_name ("zoom button");
3090 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3091 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3092 tav_expand_button.set_related_action (act);
3094 tav_shrink_button.set_name ("zoom button");
3095 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3096 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3097 tav_shrink_button.set_related_action (act);
3099 if (ARDOUR::Profile->get_mixbus()) {
3100 _zoom_box.pack_start (visible_tracks_selector);
3101 } else if (ARDOUR::Profile->get_trx()) {
3102 _zoom_box.pack_start (tav_shrink_button);
3103 _zoom_box.pack_start (tav_expand_button);
3105 _zoom_box.pack_start (visible_tracks_selector);
3106 _zoom_box.pack_start (tav_shrink_button);
3107 _zoom_box.pack_start (tav_expand_button);
3110 snap_box.set_spacing (2);
3111 snap_box.set_border_width (2);
3113 snap_type_selector.set_name ("mouse mode button");
3115 snap_mode_selector.set_name ("mouse mode button");
3117 edit_point_selector.set_name ("mouse mode button");
3119 snap_box.pack_start (snap_mode_selector, false, false);
3120 snap_box.pack_start (snap_type_selector, false, false);
3121 snap_box.pack_start (edit_point_selector, false, false);
3125 HBox *nudge_box = manage (new HBox);
3126 nudge_box->set_spacing (2);
3127 nudge_box->set_border_width (2);
3129 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3130 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3132 nudge_box->pack_start (nudge_backward_button, false, false);
3133 nudge_box->pack_start (nudge_forward_button, false, false);
3134 nudge_box->pack_start (*nudge_clock, false, false);
3137 /* Pack everything in... */
3139 HBox* hbox = manage (new HBox);
3140 hbox->set_spacing(2);
3142 toolbar_hbox.set_spacing (2);
3143 toolbar_hbox.set_border_width (1);
3145 toolbar_hbox.pack_start (*mode_box, false, false);
3146 if (!ARDOUR::Profile->get_trx()) {
3147 toolbar_hbox.pack_start (_zoom_box, false, false);
3148 toolbar_hbox.pack_start (*hbox, false, false);
3151 if (!ARDOUR::Profile->get_trx()) {
3152 hbox->pack_start (snap_box, false, false);
3153 hbox->pack_start (*nudge_box, false, false);
3158 toolbar_base.set_name ("ToolBarBase");
3159 toolbar_base.add (toolbar_hbox);
3161 _toolbar_viewport.add (toolbar_base);
3162 /* stick to the required height but allow width to vary if there's not enough room */
3163 _toolbar_viewport.set_size_request (1, -1);
3165 toolbar_frame.set_shadow_type (SHADOW_OUT);
3166 toolbar_frame.set_name ("BaseFrame");
3167 toolbar_frame.add (_toolbar_viewport);
3171 Editor::build_edit_point_menu ()
3173 using namespace Menu_Helpers;
3175 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3176 if(!Profile->get_mixbus())
3177 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3178 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3180 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3184 Editor::build_edit_mode_menu ()
3186 using namespace Menu_Helpers;
3188 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3189 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3190 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3191 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3193 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3197 Editor::build_snap_mode_menu ()
3199 using namespace Menu_Helpers;
3201 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3202 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3203 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3205 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3209 Editor::build_snap_type_menu ()
3211 using namespace Menu_Helpers;
3213 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3214 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3215 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3216 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3217 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3218 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3219 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3220 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3221 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3222 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3223 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3224 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3225 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3226 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3227 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3228 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3229 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3230 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3231 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3232 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3233 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3234 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3235 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3236 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3237 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3238 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3239 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3240 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3241 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3242 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3244 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3249 Editor::setup_tooltips ()
3251 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3252 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3253 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3254 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3255 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3256 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3257 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3258 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3259 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3260 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3261 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3262 set_tooltip (zoom_in_button, _("Zoom In"));
3263 set_tooltip (zoom_out_button, _("Zoom Out"));
3264 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3265 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3266 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3267 set_tooltip (tav_expand_button, _("Expand Tracks"));
3268 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3269 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3270 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3271 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3272 set_tooltip (edit_point_selector, _("Edit Point"));
3273 set_tooltip (edit_mode_selector, _("Edit Mode"));
3274 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3278 Editor::convert_drop_to_paths (
3279 vector<string>& paths,
3280 const RefPtr<Gdk::DragContext>& /*context*/,
3283 const SelectionData& data,
3287 if (_session == 0) {
3291 vector<string> uris = data.get_uris();
3295 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3296 are actually URI lists. So do it by hand.
3299 if (data.get_target() != "text/plain") {
3303 /* Parse the "uri-list" format that Nautilus provides,
3304 where each pathname is delimited by \r\n.
3306 THERE MAY BE NO NULL TERMINATING CHAR!!!
3309 string txt = data.get_text();
3313 p = (char *) malloc (txt.length() + 1);
3314 txt.copy (p, txt.length(), 0);
3315 p[txt.length()] = '\0';
3321 while (g_ascii_isspace (*p))
3325 while (*q && (*q != '\n') && (*q != '\r')) {
3332 while (q > p && g_ascii_isspace (*q))
3337 uris.push_back (string (p, q - p + 1));
3341 p = strchr (p, '\n');
3353 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3354 if ((*i).substr (0,7) == "file://") {
3355 paths.push_back (Glib::filename_from_uri (*i));
3363 Editor::new_tempo_section ()
3368 Editor::map_transport_state ()
3370 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3372 if (_session && _session->transport_stopped()) {
3373 have_pending_keyboard_selection = false;
3376 update_loop_range_view ();
3382 Editor::begin_selection_op_history ()
3384 selection_op_cmd_depth = 0;
3385 selection_op_history_it = 0;
3387 while(!selection_op_history.empty()) {
3388 delete selection_op_history.front();
3389 selection_op_history.pop_front();
3392 selection_undo_action->set_sensitive (false);
3393 selection_redo_action->set_sensitive (false);
3394 selection_op_history.push_front (&_selection_memento->get_state ());
3398 Editor::begin_reversible_selection_op (string name)
3401 //cerr << name << endl;
3402 /* begin/commit pairs can be nested */
3403 selection_op_cmd_depth++;
3408 Editor::commit_reversible_selection_op ()
3411 if (selection_op_cmd_depth == 1) {
3413 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3415 The user has undone some selection ops and then made a new one,
3416 making anything earlier in the list invalid.
3419 list<XMLNode *>::iterator it = selection_op_history.begin();
3420 list<XMLNode *>::iterator e_it = it;
3421 advance (e_it, selection_op_history_it);
3423 for ( ; it != e_it; ++it) {
3426 selection_op_history.erase (selection_op_history.begin(), e_it);
3429 selection_op_history.push_front (&_selection_memento->get_state ());
3430 selection_op_history_it = 0;
3432 selection_undo_action->set_sensitive (true);
3433 selection_redo_action->set_sensitive (false);
3436 if (selection_op_cmd_depth > 0) {
3437 selection_op_cmd_depth--;
3443 Editor::undo_selection_op ()
3446 selection_op_history_it++;
3448 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3449 if (n == selection_op_history_it) {
3450 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3451 selection_redo_action->set_sensitive (true);
3455 /* is there an earlier entry? */
3456 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3457 selection_undo_action->set_sensitive (false);
3463 Editor::redo_selection_op ()
3466 if (selection_op_history_it > 0) {
3467 selection_op_history_it--;
3470 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3471 if (n == selection_op_history_it) {
3472 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3473 selection_undo_action->set_sensitive (true);
3478 if (selection_op_history_it == 0) {
3479 selection_redo_action->set_sensitive (false);
3485 Editor::begin_reversible_command (string name)
3488 before.push_back (&_selection_memento->get_state ());
3489 _session->begin_reversible_command (name);
3494 Editor::begin_reversible_command (GQuark q)
3497 before.push_back (&_selection_memento->get_state ());
3498 _session->begin_reversible_command (q);
3503 Editor::abort_reversible_command ()
3506 while(!before.empty()) {
3507 delete before.front();
3510 _session->abort_reversible_command ();
3515 Editor::commit_reversible_command ()
3518 if (before.size() == 1) {
3519 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3520 redo_action->set_sensitive(false);
3521 undo_action->set_sensitive(true);
3522 begin_selection_op_history ();
3525 if (before.empty()) {
3526 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3531 _session->commit_reversible_command ();
3536 Editor::history_changed ()
3540 if (undo_action && _session) {
3541 if (_session->undo_depth() == 0) {
3542 label = S_("Command|Undo");
3544 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3546 undo_action->property_label() = label;
3549 if (redo_action && _session) {
3550 if (_session->redo_depth() == 0) {
3552 redo_action->set_sensitive (false);
3554 label = string_compose(_("Redo (%1)"), _session->next_redo());
3555 redo_action->set_sensitive (true);
3557 redo_action->property_label() = label;
3562 Editor::duplicate_range (bool with_dialog)
3566 RegionSelection rs = get_regions_from_selection_and_entered ();
3568 if ( selection->time.length() == 0 && rs.empty()) {
3574 ArdourDialog win (_("Duplicate"));
3575 Label label (_("Number of duplications:"));
3576 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3577 SpinButton spinner (adjustment, 0.0, 1);
3580 win.get_vbox()->set_spacing (12);
3581 win.get_vbox()->pack_start (hbox);
3582 hbox.set_border_width (6);
3583 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3585 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3586 place, visually. so do this by hand.
3589 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3590 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3591 spinner.grab_focus();
3597 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3598 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3599 win.set_default_response (RESPONSE_ACCEPT);
3601 spinner.grab_focus ();
3603 switch (win.run ()) {
3604 case RESPONSE_ACCEPT:
3610 times = adjustment.get_value();
3613 if ((current_mouse_mode() == Editing::MouseRange)) {
3614 if (selection->time.length()) {
3615 duplicate_selection (times);
3617 } else if (get_smart_mode()) {
3618 if (selection->time.length()) {
3619 duplicate_selection (times);
3621 duplicate_some_regions (rs, times);
3623 duplicate_some_regions (rs, times);
3628 Editor::set_edit_mode (EditMode m)
3630 Config->set_edit_mode (m);
3634 Editor::cycle_edit_mode ()
3636 switch (Config->get_edit_mode()) {
3638 Config->set_edit_mode (Ripple);
3642 Config->set_edit_mode (Lock);
3645 Config->set_edit_mode (Slide);
3651 Editor::edit_mode_selection_done ( EditMode m )
3653 Config->set_edit_mode ( m );
3657 Editor::snap_type_selection_done (SnapType snaptype)
3659 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3661 ract->set_active ();
3666 Editor::snap_mode_selection_done (SnapMode mode)
3668 RefPtr<RadioAction> ract = snap_mode_action (mode);
3671 ract->set_active (true);
3676 Editor::cycle_edit_point (bool with_marker)
3678 if(Profile->get_mixbus())
3679 with_marker = false;
3681 switch (_edit_point) {
3683 set_edit_point_preference (EditAtPlayhead);
3685 case EditAtPlayhead:
3687 set_edit_point_preference (EditAtSelectedMarker);
3689 set_edit_point_preference (EditAtMouse);
3692 case EditAtSelectedMarker:
3693 set_edit_point_preference (EditAtMouse);
3699 Editor::edit_point_selection_done (EditPoint ep)
3701 set_edit_point_preference ( ep );
3705 Editor::build_zoom_focus_menu ()
3707 using namespace Menu_Helpers;
3709 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3710 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3711 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3712 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3713 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3714 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3716 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3720 Editor::zoom_focus_selection_done ( ZoomFocus f )
3722 RefPtr<RadioAction> ract = zoom_focus_action (f);
3724 ract->set_active ();
3729 Editor::build_track_count_menu ()
3731 using namespace Menu_Helpers;
3733 if (!Profile->get_mixbus()) {
3734 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3735 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3736 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3737 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3738 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3739 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3740 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3741 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3742 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3743 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3744 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3745 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3746 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3748 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3749 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3750 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3751 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3752 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3753 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3754 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3755 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3756 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3757 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3759 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3760 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3761 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3762 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3763 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3764 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3765 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3766 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3767 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3768 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3769 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3774 Editor::set_zoom_preset (int64_t ms)
3777 temporal_zoom_session();
3781 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3782 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3786 Editor::set_visible_track_count (int32_t n)
3788 _visible_track_count = n;
3790 /* if the canvas hasn't really been allocated any size yet, just
3791 record the desired number of visible tracks and return. when canvas
3792 allocation happens, we will get called again and then we can do the
3796 if (_visible_canvas_height <= 1) {
3802 DisplaySuspender ds;
3804 if (_visible_track_count > 0) {
3805 h = trackviews_height() / _visible_track_count;
3806 std::ostringstream s;
3807 s << _visible_track_count;
3809 } else if (_visible_track_count == 0) {
3811 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3812 if ((*i)->marked_for_display()) {
3816 h = trackviews_height() / n;
3819 /* negative value means that the visible track count has
3820 been overridden by explicit track height changes.
3822 visible_tracks_selector.set_text (X_("*"));
3826 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3827 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3830 if (str != visible_tracks_selector.get_text()) {
3831 visible_tracks_selector.set_text (str);
3836 Editor::override_visible_track_count ()
3838 _visible_track_count = -1;
3839 visible_tracks_selector.set_text ( _("*") );
3843 Editor::edit_controls_button_release (GdkEventButton* ev)
3845 if (Keyboard::is_context_menu_event (ev)) {
3846 ARDOUR_UI::instance()->add_route ();
3847 } else if (ev->button == 1) {
3848 selection->clear_tracks ();
3855 Editor::mouse_select_button_release (GdkEventButton* ev)
3857 /* this handles just right-clicks */
3859 if (ev->button != 3) {
3867 Editor::set_zoom_focus (ZoomFocus f)
3869 string str = zoom_focus_strings[(int)f];
3871 if (str != zoom_focus_selector.get_text()) {
3872 zoom_focus_selector.set_text (str);
3875 if (zoom_focus != f) {
3882 Editor::cycle_zoom_focus ()
3884 switch (zoom_focus) {
3886 set_zoom_focus (ZoomFocusRight);
3888 case ZoomFocusRight:
3889 set_zoom_focus (ZoomFocusCenter);
3891 case ZoomFocusCenter:
3892 set_zoom_focus (ZoomFocusPlayhead);
3894 case ZoomFocusPlayhead:
3895 set_zoom_focus (ZoomFocusMouse);
3897 case ZoomFocusMouse:
3898 set_zoom_focus (ZoomFocusEdit);
3901 set_zoom_focus (ZoomFocusLeft);
3907 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3909 /* recover or initialize pane positions. do this here rather than earlier because
3910 we don't want the positions to change the child allocations, which they seem to do.
3914 XMLProperty const * prop;
3916 XMLNode* geometry = ARDOUR_UI::instance()->editor_settings();
3925 if (which == static_cast<Paned*> (&edit_pane)) {
3927 if (done & Horizontal) {
3931 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3932 _notebook_shrunk = string_is_affirmative (prop->value ());
3935 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3936 /* initial allocation is 90% to canvas, 10% to notebook */
3937 pos = (int) floor (alloc.get_width() * 0.90f);
3938 snprintf (buf, sizeof(buf), "%d", pos);
3940 pos = atoi (prop->value());
3943 if (edit_pane.get_allocation().get_width() > pos) {
3944 edit_pane.set_position (pos);
3947 done = (Pane) (done | Horizontal);
3949 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3951 if (done & Vertical) {
3955 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3956 /* initial allocation is 90% to canvas, 10% to summary */
3957 pos = (int) floor (alloc.get_height() * 0.90f);
3958 snprintf (buf, sizeof(buf), "%d", pos);
3961 pos = atoi (prop->value());
3964 if (editor_summary_pane.get_allocation().get_height() > pos) {
3965 editor_summary_pane.set_position (pos);
3968 done = (Pane) (done | Vertical);
3973 Editor::set_show_measures (bool yn)
3975 if (_show_measures != yn) {
3978 if ((_show_measures = yn) == true) {
3980 tempo_lines->show();
3983 std::vector<TempoMap::BBTPoint> grid;
3984 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
3985 draw_measures (grid);
3993 Editor::toggle_follow_playhead ()
3995 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3997 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3998 set_follow_playhead (tact->get_active());
4002 /** @param yn true to follow playhead, otherwise false.
4003 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
4006 Editor::set_follow_playhead (bool yn, bool catch_up)
4008 if (_follow_playhead != yn) {
4009 if ((_follow_playhead = yn) == true && catch_up) {
4011 reset_x_origin_to_follow_playhead ();
4018 Editor::toggle_stationary_playhead ()
4020 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
4022 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
4023 set_stationary_playhead (tact->get_active());
4028 Editor::set_stationary_playhead (bool yn)
4030 if (_stationary_playhead != yn) {
4031 if ((_stationary_playhead = yn) == true) {
4033 // FIXME need a 3.0 equivalent of this 2.X call
4034 // update_current_screen ();
4041 Editor::playlist_selector () const
4043 return *_playlist_selector;
4047 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4049 if (paste_count == 0) {
4050 /* don't bother calculating an offset that will be zero anyway */
4054 /* calculate basic unsnapped multi-paste offset */
4055 framecnt_t offset = paste_count * duration;
4057 /* snap offset so pos + offset is aligned to the grid */
4058 framepos_t offset_pos = pos + offset;
4059 snap_to(offset_pos, RoundUpMaybe);
4060 offset = offset_pos - pos;
4066 Editor::get_grid_beat_divisions(framepos_t position)
4068 switch (_snap_type) {
4069 case SnapToBeatDiv128: return 128;
4070 case SnapToBeatDiv64: return 64;
4071 case SnapToBeatDiv32: return 32;
4072 case SnapToBeatDiv28: return 28;
4073 case SnapToBeatDiv24: return 24;
4074 case SnapToBeatDiv20: return 20;
4075 case SnapToBeatDiv16: return 16;
4076 case SnapToBeatDiv14: return 14;
4077 case SnapToBeatDiv12: return 12;
4078 case SnapToBeatDiv10: return 10;
4079 case SnapToBeatDiv8: return 8;
4080 case SnapToBeatDiv7: return 7;
4081 case SnapToBeatDiv6: return 6;
4082 case SnapToBeatDiv5: return 5;
4083 case SnapToBeatDiv4: return 4;
4084 case SnapToBeatDiv3: return 3;
4085 case SnapToBeatDiv2: return 2;
4092 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4096 const unsigned divisions = get_grid_beat_divisions(position);
4098 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4101 switch (_snap_type) {
4103 return Evoral::Beats(1.0);
4106 return Evoral::Beats(_session->tempo_map().meter_at_frame (position).divisions_per_bar());
4114 return Evoral::Beats();
4118 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4122 ret = nudge_clock->current_duration (pos);
4123 next = ret + 1; /* XXXX fix me */
4129 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4131 ArdourDialog dialog (_("Playlist Deletion"));
4132 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4133 "If it is kept, its audio files will not be cleaned.\n"
4134 "If it is deleted, audio files used by it alone will be cleaned."),
4137 dialog.set_position (WIN_POS_CENTER);
4138 dialog.get_vbox()->pack_start (label);
4142 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4143 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4144 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4145 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4146 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4148 // by default gtk uses the left most button
4149 keep->grab_focus ();
4151 switch (dialog.run ()) {
4153 /* keep this and all remaining ones */
4158 /* delete this and all others */
4162 case RESPONSE_ACCEPT:
4163 /* delete the playlist */
4167 case RESPONSE_REJECT:
4168 /* keep the playlist */
4180 Editor::audio_region_selection_covers (framepos_t where)
4182 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4183 if ((*a)->region()->covers (where)) {
4192 Editor::prepare_for_cleanup ()
4194 cut_buffer->clear_regions ();
4195 cut_buffer->clear_playlists ();
4197 selection->clear_regions ();
4198 selection->clear_playlists ();
4200 _regions->suspend_redisplay ();
4204 Editor::finish_cleanup ()
4206 _regions->resume_redisplay ();
4210 Editor::transport_loop_location()
4213 return _session->locations()->auto_loop_location();
4220 Editor::transport_punch_location()
4223 return _session->locations()->auto_punch_location();
4230 Editor::control_layout_scroll (GdkEventScroll* ev)
4232 /* Just forward to the normal canvas scroll method. The coordinate
4233 systems are different but since the canvas is always larger than the
4234 track headers, and aligned with the trackview area, this will work.
4236 In the not too distant future this layout is going away anyway and
4237 headers will be on the canvas.
4239 return canvas_scroll_event (ev, false);
4243 Editor::session_state_saved (string)
4246 _snapshots->redisplay ();
4250 Editor::maximise_editing_space ()
4256 Gtk::Window* toplevel = current_toplevel();
4259 toplevel->fullscreen ();
4265 Editor::restore_editing_space ()
4271 Gtk::Window* toplevel = current_toplevel();
4274 toplevel->unfullscreen();
4280 * Make new playlists for a given track and also any others that belong
4281 * to the same active route group with the `select' property.
4286 Editor::new_playlists (TimeAxisView* v)
4288 begin_reversible_command (_("new playlists"));
4289 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4290 _session->playlists->get (playlists);
4291 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4292 commit_reversible_command ();
4296 * Use a copy of the current playlist for a given track and also any others that belong
4297 * to the same active route group with the `select' property.
4302 Editor::copy_playlists (TimeAxisView* v)
4304 begin_reversible_command (_("copy playlists"));
4305 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4306 _session->playlists->get (playlists);
4307 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4308 commit_reversible_command ();
4311 /** Clear the current playlist for a given track and also any others that belong
4312 * to the same active route group with the `select' property.
4317 Editor::clear_playlists (TimeAxisView* v)
4319 begin_reversible_command (_("clear playlists"));
4320 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4321 _session->playlists->get (playlists);
4322 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4323 commit_reversible_command ();
4327 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4329 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4333 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4335 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4339 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4341 atv.clear_playlist ();
4345 Editor::get_y_origin () const
4347 return vertical_adjustment.get_value ();
4350 /** Queue up a change to the viewport x origin.
4351 * @param frame New x origin.
4354 Editor::reset_x_origin (framepos_t frame)
4356 pending_visual_change.add (VisualChange::TimeOrigin);
4357 pending_visual_change.time_origin = frame;
4358 ensure_visual_change_idle_handler ();
4362 Editor::reset_y_origin (double y)
4364 pending_visual_change.add (VisualChange::YOrigin);
4365 pending_visual_change.y_origin = y;
4366 ensure_visual_change_idle_handler ();
4370 Editor::reset_zoom (framecnt_t spp)
4372 if (spp == samples_per_pixel) {
4376 pending_visual_change.add (VisualChange::ZoomLevel);
4377 pending_visual_change.samples_per_pixel = spp;
4378 ensure_visual_change_idle_handler ();
4382 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4384 reset_x_origin (frame);
4387 if (!no_save_visual) {
4388 undo_visual_stack.push_back (current_visual_state(false));
4392 Editor::VisualState::VisualState (bool with_tracks)
4393 : gui_state (with_tracks ? new GUIObjectState : 0)
4397 Editor::VisualState::~VisualState ()
4402 Editor::VisualState*
4403 Editor::current_visual_state (bool with_tracks)
4405 VisualState* vs = new VisualState (with_tracks);
4406 vs->y_position = vertical_adjustment.get_value();
4407 vs->samples_per_pixel = samples_per_pixel;
4408 vs->leftmost_frame = leftmost_frame;
4409 vs->zoom_focus = zoom_focus;
4412 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4419 Editor::undo_visual_state ()
4421 if (undo_visual_stack.empty()) {
4425 VisualState* vs = undo_visual_stack.back();
4426 undo_visual_stack.pop_back();
4429 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4432 use_visual_state (*vs);
4437 Editor::redo_visual_state ()
4439 if (redo_visual_stack.empty()) {
4443 VisualState* vs = redo_visual_stack.back();
4444 redo_visual_stack.pop_back();
4446 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4447 // why do we check here?
4448 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4451 use_visual_state (*vs);
4456 Editor::swap_visual_state ()
4458 if (undo_visual_stack.empty()) {
4459 redo_visual_state ();
4461 undo_visual_state ();
4466 Editor::use_visual_state (VisualState& vs)
4468 PBD::Unwinder<bool> nsv (no_save_visual, true);
4469 DisplaySuspender ds;
4471 vertical_adjustment.set_value (vs.y_position);
4473 set_zoom_focus (vs.zoom_focus);
4474 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4477 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4479 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4480 (*i)->clear_property_cache();
4481 (*i)->reset_visual_state ();
4485 _routes->update_visibility ();
4488 /** This is the core function that controls the zoom level of the canvas. It is called
4489 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4490 * @param spp new number of samples per pixel
4493 Editor::set_samples_per_pixel (framecnt_t spp)
4499 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4500 const framecnt_t lots_of_pixels = 4000;
4502 /* if the zoom level is greater than what you'd get trying to display 3
4503 * days of audio on a really big screen, then it's too big.
4506 if (spp * lots_of_pixels > three_days) {
4510 samples_per_pixel = spp;
4513 tempo_lines->tempo_map_changed();
4516 bool const showing_time_selection = selection->time.length() > 0;
4518 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4519 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4520 (*i)->reshow_selection (selection->time);
4524 ZoomChanged (); /* EMIT_SIGNAL */
4526 ArdourCanvas::GtkCanvasViewport* c;
4528 c = get_track_canvas();
4530 c->canvas()->zoomed ();
4533 if (playhead_cursor) {
4534 playhead_cursor->set_position (playhead_cursor->current_frame ());
4537 refresh_location_display();
4538 _summary->set_overlays_dirty ();
4540 update_marker_labels ();
4546 Editor::queue_visual_videotimeline_update ()
4549 * pending_visual_change.add (VisualChange::VideoTimeline);
4550 * or maybe even more specific: which videotimeline-image
4551 * currently it calls update_video_timeline() to update
4552 * _all outdated_ images on the video-timeline.
4553 * see 'exposeimg()' in video_image_frame.cc
4555 ensure_visual_change_idle_handler ();
4559 Editor::ensure_visual_change_idle_handler ()
4561 if (pending_visual_change.idle_handler_id < 0) {
4562 // see comment in add_to_idle_resize above.
4563 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4564 pending_visual_change.being_handled = false;
4569 Editor::_idle_visual_changer (void* arg)
4571 return static_cast<Editor*>(arg)->idle_visual_changer ();
4575 Editor::idle_visual_changer ()
4577 /* set_horizontal_position() below (and maybe other calls) call
4578 gtk_main_iteration(), so it's possible that a signal will be handled
4579 half-way through this method. If this signal wants an
4580 idle_visual_changer we must schedule another one after this one, so
4581 mark the idle_handler_id as -1 here to allow that. Also make a note
4582 that we are doing the visual change, so that changes in response to
4583 super-rapid-screen-update can be dropped if we are still processing
4587 pending_visual_change.idle_handler_id = -1;
4588 pending_visual_change.being_handled = true;
4590 VisualChange vc = pending_visual_change;
4592 pending_visual_change.pending = (VisualChange::Type) 0;
4594 visual_changer (vc);
4596 pending_visual_change.being_handled = false;
4598 return 0; /* this is always a one-shot call */
4602 Editor::visual_changer (const VisualChange& vc)
4604 double const last_time_origin = horizontal_position ();
4606 if (vc.pending & VisualChange::ZoomLevel) {
4607 set_samples_per_pixel (vc.samples_per_pixel);
4609 compute_fixed_ruler_scale ();
4611 std::vector<TempoMap::BBTPoint> grid;
4612 compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4613 compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4614 update_tempo_based_rulers (grid);
4616 update_video_timeline();
4619 if (vc.pending & VisualChange::TimeOrigin) {
4620 set_horizontal_position (vc.time_origin / samples_per_pixel);
4623 if (vc.pending & VisualChange::YOrigin) {
4624 vertical_adjustment.set_value (vc.y_origin);
4627 if (last_time_origin == horizontal_position ()) {
4628 /* changed signal not emitted */
4629 update_fixed_rulers ();
4630 redisplay_tempo (true);
4633 if (!(vc.pending & VisualChange::ZoomLevel)) {
4634 update_video_timeline();
4637 _summary->set_overlays_dirty ();
4640 struct EditorOrderTimeAxisSorter {
4641 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4642 return a->order () < b->order ();
4647 Editor::sort_track_selection (TrackViewList& sel)
4649 EditorOrderTimeAxisSorter cmp;
4654 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4657 framepos_t where = 0;
4658 EditPoint ep = _edit_point;
4660 if (Profile->get_mixbus())
4661 if (ep == EditAtSelectedMarker)
4662 ep = EditAtPlayhead;
4664 if (from_outside_canvas && (ep == EditAtMouse)) {
4665 ep = EditAtPlayhead;
4666 } else if (from_context_menu && (ep == EditAtMouse)) {
4667 return canvas_event_sample (&context_click_event, 0, 0);
4670 if (entered_marker) {
4671 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4672 return entered_marker->position();
4675 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4676 ep = EditAtSelectedMarker;
4679 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4680 ep = EditAtPlayhead;
4684 case EditAtPlayhead:
4685 if (_dragging_playhead) {
4686 where = *_control_scroll_target;
4688 where = _session->audible_frame();
4690 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4693 case EditAtSelectedMarker:
4694 if (!selection->markers.empty()) {
4696 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4699 where = loc->start();
4703 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4711 if (!mouse_frame (where, ignored)) {
4712 /* XXX not right but what can we do ? */
4716 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4724 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4726 if (!_session) return;
4728 begin_reversible_command (cmd);
4732 if ((tll = transport_loop_location()) == 0) {
4733 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4734 XMLNode &before = _session->locations()->get_state();
4735 _session->locations()->add (loc, true);
4736 _session->set_auto_loop_location (loc);
4737 XMLNode &after = _session->locations()->get_state();
4738 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4740 XMLNode &before = tll->get_state();
4741 tll->set_hidden (false, this);
4742 tll->set (start, end);
4743 XMLNode &after = tll->get_state();
4744 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4747 commit_reversible_command ();
4751 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4753 if (!_session) return;
4755 begin_reversible_command (cmd);
4759 if ((tpl = transport_punch_location()) == 0) {
4760 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4761 XMLNode &before = _session->locations()->get_state();
4762 _session->locations()->add (loc, true);
4763 _session->set_auto_punch_location (loc);
4764 XMLNode &after = _session->locations()->get_state();
4765 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4767 XMLNode &before = tpl->get_state();
4768 tpl->set_hidden (false, this);
4769 tpl->set (start, end);
4770 XMLNode &after = tpl->get_state();
4771 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4774 commit_reversible_command ();
4777 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4778 * @param rs List to which found regions are added.
4779 * @param where Time to look at.
4780 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4783 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4785 const TrackViewList* tracks;
4788 tracks = &track_views;
4793 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4795 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4798 boost::shared_ptr<Track> tr;
4799 boost::shared_ptr<Playlist> pl;
4801 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4803 boost::shared_ptr<RegionList> regions = pl->regions_at (
4804 (framepos_t) floor ( (double) where * tr->speed()));
4806 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4807 RegionView* rv = rtv->view()->find_view (*i);
4818 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4820 const TrackViewList* tracks;
4823 tracks = &track_views;
4828 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4829 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4831 boost::shared_ptr<Track> tr;
4832 boost::shared_ptr<Playlist> pl;
4834 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4836 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4837 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4839 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4841 RegionView* rv = rtv->view()->find_view (*i);
4852 /** Get regions using the following method:
4854 * Make a region list using:
4855 * (a) any selected regions
4856 * (b) the intersection of any selected tracks and the edit point(*)
4857 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4859 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4861 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4865 Editor::get_regions_from_selection_and_edit_point ()
4867 RegionSelection regions;
4869 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4870 regions.add (entered_regionview);
4872 regions = selection->regions;
4875 if ( regions.empty() ) {
4876 TrackViewList tracks = selection->tracks;
4878 if (!tracks.empty()) {
4879 /* no region selected or entered, but some selected tracks:
4880 * act on all regions on the selected tracks at the edit point
4882 framepos_t const where = get_preferred_edit_position ();
4883 get_regions_at(regions, where, tracks);
4890 /** Get regions using the following method:
4892 * Make a region list using:
4893 * (a) any selected regions
4894 * (b) the intersection of any selected tracks and the edit point(*)
4895 * (c) if neither exists, then whatever region is under the mouse
4897 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4899 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4902 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4904 RegionSelection regions;
4906 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4907 regions.add (entered_regionview);
4909 regions = selection->regions;
4912 if ( regions.empty() ) {
4913 TrackViewList tracks = selection->tracks;
4915 if (!tracks.empty()) {
4916 /* no region selected or entered, but some selected tracks:
4917 * act on all regions on the selected tracks at the edit point
4919 get_regions_at(regions, pos, tracks);
4926 /** Start with regions that are selected, or the entered regionview if none are selected.
4927 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4928 * of the regions that we started with.
4932 Editor::get_regions_from_selection_and_entered () const
4934 RegionSelection regions = selection->regions;
4936 if (regions.empty() && entered_regionview) {
4937 regions.add (entered_regionview);
4944 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4946 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4947 RouteTimeAxisView* rtav;
4949 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4950 boost::shared_ptr<Playlist> pl;
4951 std::vector<boost::shared_ptr<Region> > results;
4952 boost::shared_ptr<Track> tr;
4954 if ((tr = rtav->track()) == 0) {
4959 if ((pl = (tr->playlist())) != 0) {
4960 boost::shared_ptr<Region> r = pl->region_by_id (id);
4962 RegionView* rv = rtav->view()->find_view (r);
4964 regions.push_back (rv);
4973 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4976 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4977 MidiTimeAxisView* mtav;
4979 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4981 mtav->get_per_region_note_selection (selection);
4988 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4990 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4992 RouteTimeAxisView* tatv;
4994 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4996 boost::shared_ptr<Playlist> pl;
4997 vector<boost::shared_ptr<Region> > results;
4999 boost::shared_ptr<Track> tr;
5001 if ((tr = tatv->track()) == 0) {
5006 if ((pl = (tr->playlist())) != 0) {
5007 if (src_comparison) {
5008 pl->get_source_equivalent_regions (region, results);
5010 pl->get_region_list_equivalent_regions (region, results);
5014 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
5015 if ((marv = tatv->view()->find_view (*ir)) != 0) {
5016 regions.push_back (marv);
5025 Editor::show_rhythm_ferret ()
5027 if (rhythm_ferret == 0) {
5028 rhythm_ferret = new RhythmFerret(*this);
5031 rhythm_ferret->set_session (_session);
5032 rhythm_ferret->show ();
5033 rhythm_ferret->present ();
5037 Editor::first_idle ()
5039 MessageDialog* dialog = 0;
5041 if (track_views.size() > 1) {
5042 Timers::TimerSuspender t;
5043 dialog = new MessageDialog (
5044 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5048 ARDOUR_UI::instance()->flush_pending ();
5051 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5055 // first idle adds route children (automation tracks), so we need to redisplay here
5056 _routes->redisplay ();
5060 if (_session->undo_depth() == 0) {
5061 undo_action->set_sensitive(false);
5063 redo_action->set_sensitive(false);
5064 begin_selection_op_history ();
5070 Editor::_idle_resize (gpointer arg)
5072 return ((Editor*)arg)->idle_resize ();
5076 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5078 if (resize_idle_id < 0) {
5079 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5080 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5081 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5083 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5084 _pending_resize_amount = 0;
5087 /* make a note of the smallest resulting height, so that we can clamp the
5088 lower limit at TimeAxisView::hSmall */
5090 int32_t min_resulting = INT32_MAX;
5092 _pending_resize_amount += h;
5093 _pending_resize_view = view;
5095 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5097 if (selection->tracks.contains (_pending_resize_view)) {
5098 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5099 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5103 if (min_resulting < 0) {
5108 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5109 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5113 /** Handle pending resizing of tracks */
5115 Editor::idle_resize ()
5117 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5119 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5120 selection->tracks.contains (_pending_resize_view)) {
5122 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5123 if (*i != _pending_resize_view) {
5124 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5129 _pending_resize_amount = 0;
5130 _group_tabs->set_dirty ();
5131 resize_idle_id = -1;
5139 ENSURE_GUI_THREAD (*this, &Editor::located);
5142 playhead_cursor->set_position (_session->audible_frame ());
5143 if (_follow_playhead && !_pending_initial_locate) {
5144 reset_x_origin_to_follow_playhead ();
5148 _pending_locate_request = false;
5149 _pending_initial_locate = false;
5153 Editor::region_view_added (RegionView * rv)
5155 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5156 if (rv->region ()->id () == (*pr)) {
5157 selection->add (rv);
5158 selection->regions.pending.erase (pr);
5163 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5165 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5166 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5167 if (rv->region()->id () == (*rnote).first) {
5168 mrv->select_notes ((*rnote).second);
5169 selection->pending_midi_note_selection.erase(rnote);
5175 _summary->set_background_dirty ();
5179 Editor::region_view_removed ()
5181 _summary->set_background_dirty ();
5185 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5187 TrackViewList::const_iterator j = track_views.begin ();
5188 while (j != track_views.end()) {
5189 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5190 if (rtv && rtv->route() == r) {
5201 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5205 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5206 TimeAxisView* tv = axis_view_from_route (*i);
5216 Editor::suspend_route_redisplay ()
5219 _routes->suspend_redisplay();
5224 Editor::resume_route_redisplay ()
5227 _routes->redisplay(); // queue redisplay
5228 _routes->resume_redisplay();
5233 Editor::add_routes (RouteList& routes)
5235 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5237 RouteTimeAxisView *rtv;
5238 list<RouteTimeAxisView*> new_views;
5239 TrackViewList new_selection;
5240 bool from_scratch = (track_views.size() == 0);
5242 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5243 boost::shared_ptr<Route> route = (*x);
5245 if (route->is_auditioner() || route->is_monitor()) {
5249 DataType dt = route->input()->default_type();
5251 if (dt == ARDOUR::DataType::AUDIO) {
5252 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5253 rtv->set_route (route);
5254 } else if (dt == ARDOUR::DataType::MIDI) {
5255 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5256 rtv->set_route (route);
5258 throw unknown_type();
5261 new_views.push_back (rtv);
5262 track_views.push_back (rtv);
5263 new_selection.push_back (rtv);
5265 rtv->effective_gain_display ();
5267 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5268 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5271 if (new_views.size() > 0) {
5272 _routes->routes_added (new_views);
5273 _summary->routes_added (new_views);
5276 if (!from_scratch) {
5277 selection->tracks.clear();
5278 selection->add (new_selection);
5279 begin_selection_op_history();
5282 if (show_editor_mixer_when_tracks_arrive) {
5283 show_editor_mixer (true);
5286 editor_list_button.set_sensitive (true);
5290 Editor::timeaxisview_deleted (TimeAxisView *tv)
5292 if (tv == entered_track) {
5296 if (_session && _session->deletion_in_progress()) {
5297 /* the situation is under control */
5301 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5303 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5305 _routes->route_removed (tv);
5307 TimeAxisView::Children c = tv->get_child_list ();
5308 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5309 if (entered_track == i->get()) {
5314 /* remove it from the list of track views */
5316 TrackViewList::iterator i;
5318 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5319 i = track_views.erase (i);
5322 /* update whatever the current mixer strip is displaying, if revelant */
5324 boost::shared_ptr<Route> route;
5327 route = rtav->route ();
5330 if (current_mixer_strip && current_mixer_strip->route() == route) {
5332 TimeAxisView* next_tv;
5334 if (track_views.empty()) {
5336 } else if (i == track_views.end()) {
5337 next_tv = track_views.front();
5344 set_selected_mixer_strip (*next_tv);
5346 /* make the editor mixer strip go away setting the
5347 * button to inactive (which also unticks the menu option)
5350 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5356 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5358 if (apply_to_selection) {
5359 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5361 TrackSelection::iterator j = i;
5364 hide_track_in_display (*i, false);
5369 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5371 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5372 // this will hide the mixer strip
5373 set_selected_mixer_strip (*tv);
5376 _routes->hide_track_in_display (*tv);
5381 Editor::sync_track_view_list_and_routes ()
5383 track_views = TrackViewList (_routes->views ());
5385 _summary->set_background_dirty();
5386 _group_tabs->set_dirty ();
5388 return false; // do not call again (until needed)
5392 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5394 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5399 /** Find a RouteTimeAxisView by the ID of its route */
5401 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5403 RouteTimeAxisView* v;
5405 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5406 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5407 if(v->route()->id() == id) {
5417 Editor::fit_route_group (RouteGroup *g)
5419 TrackViewList ts = axis_views_from_routes (g->route_list ());
5424 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5426 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5429 _session->cancel_audition ();
5433 if (_session->is_auditioning()) {
5434 _session->cancel_audition ();
5435 if (r == last_audition_region) {
5440 _session->audition_region (r);
5441 last_audition_region = r;
5446 Editor::hide_a_region (boost::shared_ptr<Region> r)
5448 r->set_hidden (true);
5452 Editor::show_a_region (boost::shared_ptr<Region> r)
5454 r->set_hidden (false);
5458 Editor::audition_region_from_region_list ()
5460 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5464 Editor::hide_region_from_region_list ()
5466 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5470 Editor::show_region_in_region_list ()
5472 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5476 Editor::step_edit_status_change (bool yn)
5479 start_step_editing ();
5481 stop_step_editing ();
5486 Editor::start_step_editing ()
5488 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5492 Editor::stop_step_editing ()
5494 step_edit_connection.disconnect ();
5498 Editor::check_step_edit ()
5500 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5501 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5503 mtv->check_step_edit ();
5507 return true; // do it again, till we stop
5511 Editor::scroll_press (Direction dir)
5513 ++_scroll_callbacks;
5515 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5516 /* delay the first auto-repeat */
5522 scroll_backward (1);
5530 scroll_up_one_track ();
5534 scroll_down_one_track ();
5538 /* do hacky auto-repeat */
5539 if (!_scroll_connection.connected ()) {
5541 _scroll_connection = Glib::signal_timeout().connect (
5542 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5545 _scroll_callbacks = 0;
5552 Editor::scroll_release ()
5554 _scroll_connection.disconnect ();
5557 /** Queue a change for the Editor viewport x origin to follow the playhead */
5559 Editor::reset_x_origin_to_follow_playhead ()
5561 framepos_t const frame = playhead_cursor->current_frame ();
5563 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5565 if (_session->transport_speed() < 0) {
5567 if (frame > (current_page_samples() / 2)) {
5568 center_screen (frame-(current_page_samples()/2));
5570 center_screen (current_page_samples()/2);
5577 if (frame < leftmost_frame) {
5579 if (_session->transport_rolling()) {
5580 /* rolling; end up with the playhead at the right of the page */
5581 l = frame - current_page_samples ();
5583 /* not rolling: end up with the playhead 1/4 of the way along the page */
5584 l = frame - current_page_samples() / 4;
5588 if (_session->transport_rolling()) {
5589 /* rolling: end up with the playhead on the left of the page */
5592 /* not rolling: end up with the playhead 3/4 of the way along the page */
5593 l = frame - 3 * current_page_samples() / 4;
5601 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5607 Editor::super_rapid_screen_update ()
5609 if (!_session || !_session->engine().running()) {
5613 /* METERING / MIXER STRIPS */
5615 /* update track meters, if required */
5616 if (contents().is_mapped() && meters_running) {
5617 RouteTimeAxisView* rtv;
5618 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5619 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5620 rtv->fast_update ();
5625 /* and any current mixer strip */
5626 if (current_mixer_strip) {
5627 current_mixer_strip->fast_update ();
5630 /* PLAYHEAD AND VIEWPORT */
5632 framepos_t const frame = _session->audible_frame();
5634 /* There are a few reasons why we might not update the playhead / viewport stuff:
5636 * 1. we don't update things when there's a pending locate request, otherwise
5637 * when the editor requests a locate there is a chance that this method
5638 * will move the playhead before the locate request is processed, causing
5640 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5641 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5644 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5646 last_update_frame = frame;
5648 if (!_dragging_playhead) {
5649 playhead_cursor->set_position (frame);
5652 if (!_stationary_playhead) {
5654 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5655 /* We only do this if we aren't already
5656 handling a visual change (ie if
5657 pending_visual_change.being_handled is
5658 false) so that these requests don't stack
5659 up there are too many of them to handle in
5662 reset_x_origin_to_follow_playhead ();
5667 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5668 framepos_t const frame = playhead_cursor->current_frame ();
5669 double target = ((double)frame - (double)current_page_samples()/2.0);
5670 if (target <= 0.0) {
5673 // compare to EditorCursor::set_position()
5674 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5675 double const new_pos = sample_to_pixel_unrounded (target);
5676 if (rint (new_pos) != rint (old_pos)) {
5677 reset_x_origin (pixel_to_sample (floor (new_pos)));
5688 Editor::session_going_away ()
5690 _have_idled = false;
5692 _session_connections.drop_connections ();
5694 super_rapid_screen_update_connection.disconnect ();
5696 selection->clear ();
5697 cut_buffer->clear ();
5699 clicked_regionview = 0;
5700 clicked_axisview = 0;
5701 clicked_routeview = 0;
5702 entered_regionview = 0;
5704 last_update_frame = 0;
5707 playhead_cursor->hide ();
5709 /* rip everything out of the list displays */
5713 _route_groups->clear ();
5715 /* do this first so that deleting a track doesn't reset cms to null
5716 and thus cause a leak.
5719 if (current_mixer_strip) {
5720 if (current_mixer_strip->get_parent() != 0) {
5721 global_hpacker.remove (*current_mixer_strip);
5723 delete current_mixer_strip;
5724 current_mixer_strip = 0;
5727 /* delete all trackviews */
5729 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5732 track_views.clear ();
5734 nudge_clock->set_session (0);
5736 editor_list_button.set_active(false);
5737 editor_list_button.set_sensitive(false);
5739 /* clear tempo/meter rulers */
5740 remove_metric_marks ();
5742 clear_marker_display ();
5744 stop_step_editing ();
5748 /* get rid of any existing editor mixer strip */
5750 WindowTitle title(Glib::get_application_name());
5751 title += _("Editor");
5753 own_window()->set_title (title.get_string());
5756 SessionHandlePtr::session_going_away ();
5760 Editor::trigger_script (int i)
5762 LuaInstance::instance()-> call_action (i);
5766 Editor::set_script_action_name (int i, const std::string& n)
5768 string const a = string_compose (X_("script-action-%1"), i + 1);
5769 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5772 act->set_label (string_compose (_("Unset #%1"), i + 1));
5773 act->set_tooltip (_("no action bound"));
5774 act->set_sensitive (false);
5777 act->set_tooltip (n);
5778 act->set_sensitive (true);
5780 KeyEditor::UpdateBindings ();
5784 Editor::show_editor_list (bool yn)
5787 _the_notebook.show ();
5789 _the_notebook.hide ();
5794 Editor::change_region_layering_order (bool from_context_menu)
5796 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5798 if (!clicked_routeview) {
5799 if (layering_order_editor) {
5800 layering_order_editor->hide ();
5805 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5811 boost::shared_ptr<Playlist> pl = track->playlist();
5817 if (layering_order_editor == 0) {
5818 layering_order_editor = new RegionLayeringOrderEditor (*this);
5821 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5822 layering_order_editor->maybe_present ();
5826 Editor::update_region_layering_order_editor ()
5828 if (layering_order_editor && layering_order_editor->is_visible ()) {
5829 change_region_layering_order (true);
5834 Editor::setup_fade_images ()
5836 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5837 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5838 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5839 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5840 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5842 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5843 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5844 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5845 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5846 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5848 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5849 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5850 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5851 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5852 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5854 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5855 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5856 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5857 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5858 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5862 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5864 Editor::action_menu_item (std::string const & name)
5866 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5869 return *manage (a->create_menu_item ());
5873 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5875 EventBox* b = manage (new EventBox);
5876 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5877 Label* l = manage (new Label (name));
5881 _the_notebook.append_page (widget, *b);
5885 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5887 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5888 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5891 if (ev->type == GDK_2BUTTON_PRESS) {
5893 /* double-click on a notebook tab shrinks or expands the notebook */
5895 if (_notebook_shrunk) {
5896 if (pre_notebook_shrink_pane_width) {
5897 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5899 _notebook_shrunk = false;
5901 pre_notebook_shrink_pane_width = edit_pane.get_position();
5903 /* this expands the LHS of the edit pane to cover the notebook
5904 PAGE but leaves the tabs visible.
5906 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5907 _notebook_shrunk = true;
5915 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5917 using namespace Menu_Helpers;
5919 MenuList& items = _control_point_context_menu.items ();
5922 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5923 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5924 if (!can_remove_control_point (item)) {
5925 items.back().set_sensitive (false);
5928 _control_point_context_menu.popup (event->button.button, event->button.time);
5932 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5934 using namespace Menu_Helpers;
5936 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5941 /* We need to get the selection here and pass it to the operations, since
5942 popping up the menu will cause a region leave event which clears
5943 entered_regionview. */
5945 MidiRegionView& mrv = note->region_view();
5946 const RegionSelection rs = get_regions_from_selection_and_entered ();
5947 const uint32_t sel_size = mrv.selection_size ();
5949 MenuList& items = _note_context_menu.items();
5953 items.push_back(MenuElem(_("Delete"),
5954 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5957 items.push_back(MenuElem(_("Edit..."),
5958 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5959 if (sel_size != 1) {
5960 items.back().set_sensitive (false);
5963 items.push_back(MenuElem(_("Transpose..."),
5964 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5967 items.push_back(MenuElem(_("Legatize"),
5968 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5970 items.back().set_sensitive (false);
5973 items.push_back(MenuElem(_("Quantize..."),
5974 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5976 items.push_back(MenuElem(_("Remove Overlap"),
5977 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5979 items.back().set_sensitive (false);
5982 items.push_back(MenuElem(_("Transform..."),
5983 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5985 _note_context_menu.popup (event->button.button, event->button.time);
5989 Editor::zoom_vertical_modifier_released()
5991 _stepping_axis_view = 0;
5995 Editor::ui_parameter_changed (string parameter)
5997 if (parameter == "icon-set") {
5998 while (!_cursor_stack.empty()) {
5999 _cursor_stack.pop_back();
6001 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
6002 _cursor_stack.push_back(_cursors->grabber);
6003 } else if (parameter == "draggable-playhead") {
6004 if (_verbose_cursor) {
6005 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
6011 Editor::use_own_window (bool and_fill_it)
6013 bool new_window = !own_window();
6015 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
6017 if (win && new_window) {
6018 win->set_name ("EditorWindow");
6020 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
6022 // win->signal_realize().connect (*this, &Editor::on_realize);
6023 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
6024 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
6025 win->set_data ("ardour-bindings", bindings);
6030 DisplaySuspender ds;
6031 contents().show_all ();
6033 /* XXX: this is a bit unfortunate; it would probably
6034 be nicer if we could just call show () above rather
6035 than needing the show_all ()
6038 /* re-hide stuff if necessary */
6039 editor_list_button_toggled ();
6040 parameter_changed ("show-summary");
6041 parameter_changed ("show-group-tabs");
6042 parameter_changed ("show-zoom-tools");
6044 /* now reset all audio_time_axis heights, because widgets might need
6050 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6051 tv = (static_cast<TimeAxisView*>(*i));
6052 tv->reset_height ();
6055 if (current_mixer_strip) {
6056 current_mixer_strip->hide_things ();
6057 current_mixer_strip->parameter_changed ("mixer-element-visibility");