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.h"
76 #include "ardour/route_group.h"
77 #include "ardour/session_playlists.h"
78 #include "ardour/tempo.h"
79 #include "ardour/utils.h"
80 #include "ardour/vca_manager.h"
81 #include "ardour/vca.h"
83 #include "canvas/debug.h"
84 #include "canvas/text.h"
86 #include "control_protocol/control_protocol.h"
89 #include "analysis_window.h"
90 #include "audio_clock.h"
91 #include "audio_region_view.h"
92 #include "audio_streamview.h"
93 #include "audio_time_axis.h"
94 #include "automation_time_axis.h"
95 #include "bundle_manager.h"
96 #include "crossfade_edit.h"
100 #include "editor_cursors.h"
101 #include "editor_drag.h"
102 #include "editor_group_tabs.h"
103 #include "editor_locations.h"
104 #include "editor_regions.h"
105 #include "editor_route_groups.h"
106 #include "editor_routes.h"
107 #include "editor_snapshots.h"
108 #include "editor_summary.h"
109 #include "export_report.h"
110 #include "global_port_matrix.h"
111 #include "gui_object.h"
112 #include "gui_thread.h"
113 #include "keyboard.h"
114 #include "keyeditor.h"
115 #include "luainstance.h"
117 #include "midi_region_view.h"
118 #include "midi_time_axis.h"
119 #include "mixer_strip.h"
120 #include "mixer_ui.h"
121 #include "mouse_cursors.h"
122 #include "note_base.h"
123 #include "playlist_selector.h"
124 #include "public_editor.h"
125 #include "quantize_dialog.h"
126 #include "region_layering_order_editor.h"
127 #include "rgb_macros.h"
128 #include "rhythm_ferret.h"
129 #include "route_sorter.h"
130 #include "selection.h"
131 #include "simple_progress_dialog.h"
133 #include "tempo_lines.h"
134 #include "time_axis_view.h"
136 #include "tooltips.h"
137 #include "ui_config.h"
139 #include "vca_time_axis.h"
140 #include "verbose_cursor.h"
142 #include "pbd/i18n.h"
145 using namespace ARDOUR;
146 using namespace ARDOUR_UI_UTILS;
149 using namespace Glib;
150 using namespace Gtkmm2ext;
151 using namespace Editing;
153 using PBD::internationalize;
155 using Gtkmm2ext::Keyboard;
157 double Editor::timebar_height = 15.0;
159 static const gchar *_snap_type_strings[] = {
193 static const gchar *_snap_mode_strings[] = {
200 static const gchar *_edit_point_strings[] = {
207 static const gchar *_edit_mode_strings[] = {
215 static const gchar *_zoom_focus_strings[] = {
225 #ifdef USE_RUBBERBAND
226 static const gchar *_rb_opt_strings[] = {
229 N_("Balanced multitimbral mixture"),
230 N_("Unpitched percussion with stable notes"),
231 N_("Crisp monophonic instrumental"),
232 N_("Unpitched solo percussion"),
233 N_("Resample without preserving pitch"),
238 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
241 : PublicEditor (global_hpacker)
242 , editor_mixer_strip_width (Wide)
243 , constructed (false)
244 , _playlist_selector (0)
245 , no_save_visual (false)
247 , samples_per_pixel (2048)
248 , zoom_focus (ZoomFocusPlayhead)
249 , mouse_mode (MouseObject)
250 , pre_internal_snap_type (SnapToBeat)
251 , pre_internal_snap_mode (SnapOff)
252 , internal_snap_type (SnapToBeat)
253 , internal_snap_mode (SnapOff)
254 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
255 , _notebook_shrunk (false)
256 , location_marker_color (0)
257 , location_range_color (0)
258 , location_loop_color (0)
259 , location_punch_color (0)
260 , location_cd_marker_color (0)
262 , _show_marker_lines (false)
263 , clicked_axisview (0)
264 , clicked_routeview (0)
265 , clicked_regionview (0)
266 , clicked_selection (0)
267 , clicked_control_point (0)
268 , button_release_can_deselect (true)
269 , _mouse_changed_selection (false)
270 , region_edit_menu_split_item (0)
271 , region_edit_menu_split_multichannel_item (0)
272 , track_region_edit_playlist_menu (0)
273 , track_edit_playlist_submenu (0)
274 , track_selection_edit_playlist_submenu (0)
275 , _popup_region_menu_item (0)
277 , _track_canvas_viewport (0)
278 , within_track_canvas (false)
279 , _verbose_cursor (0)
283 , range_marker_group (0)
284 , transport_marker_group (0)
285 , cd_marker_group (0)
286 , _time_markers_group (0)
287 , hv_scroll_group (0)
289 , cursor_scroll_group (0)
290 , no_scroll_group (0)
291 , _trackview_group (0)
292 , _drag_motion_group (0)
293 , _canvas_drop_zone (0)
294 , no_ruler_shown_update (false)
295 , ruler_grabbed_widget (0)
297 , minsec_mark_interval (0)
298 , minsec_mark_modulo (0)
300 , timecode_mark_modulo (0)
301 , timecode_nmarks (0)
302 , _samples_ruler_interval (0)
305 , bbt_bar_helper_on (0)
306 , bbt_accent_modulo (0)
311 , visible_timebars (0)
312 , editor_ruler_menu (0)
316 , range_marker_bar (0)
317 , transport_marker_bar (0)
319 , minsec_label (_("Mins:Secs"))
320 , bbt_label (_("Bars:Beats"))
321 , timecode_label (_("Timecode"))
322 , samples_label (_("Samples"))
323 , tempo_label (_("Tempo"))
324 , meter_label (_("Meter"))
325 , mark_label (_("Location Markers"))
326 , range_mark_label (_("Range Markers"))
327 , transport_mark_label (_("Loop/Punch Ranges"))
328 , cd_mark_label (_("CD Markers"))
329 , videotl_label (_("Video Timeline"))
331 , playhead_cursor (0)
332 , edit_packer (4, 4, true)
333 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
334 , horizontal_adjustment (0.0, 0.0, 1e16)
335 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
336 , controls_layout (unused_adjustment, vertical_adjustment)
337 , _scroll_callbacks (0)
338 , _visible_canvas_width (0)
339 , _visible_canvas_height (0)
340 , _full_canvas_height (0)
341 , edit_controls_left_menu (0)
342 , edit_controls_right_menu (0)
343 , last_update_frame (0)
344 , cut_buffer_start (0)
345 , cut_buffer_length (0)
346 , button_bindings (0)
350 , current_interthread_info (0)
351 , analysis_window (0)
352 , select_new_marker (false)
354 , scrubbing_direction (0)
355 , scrub_reversals (0)
356 , scrub_reverse_distance (0)
357 , have_pending_keyboard_selection (false)
358 , pending_keyboard_selection_start (0)
359 , _snap_type (SnapToBeat)
360 , _snap_mode (SnapOff)
361 , snap_threshold (5.0)
362 , ignore_gui_changes (false)
363 , _drags (new DragManager (this))
365 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
366 , _dragging_playhead (false)
367 , _dragging_edit_point (false)
368 , _show_measures (true)
369 , _follow_playhead (true)
370 , _stationary_playhead (false)
373 , global_rect_group (0)
374 , time_line_group (0)
375 , tempo_marker_menu (0)
376 , meter_marker_menu (0)
378 , range_marker_menu (0)
379 , transport_marker_menu (0)
380 , new_transport_marker_menu (0)
382 , marker_menu_item (0)
383 , bbt_beat_subdivision (4)
384 , _visible_track_count (-1)
385 , toolbar_selection_clock_table (2,3)
386 , automation_mode_button (_("mode"))
387 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
388 , selection (new Selection (this))
389 , cut_buffer (new Selection (this))
390 , _selection_memento (new SelectionMemento())
391 , _all_region_actions_sensitized (false)
392 , _ignore_region_action (false)
393 , _last_region_menu_was_main (false)
394 , _ignore_follow_edits (false)
395 , cd_marker_bar_drag_rect (0)
396 , range_bar_drag_rect (0)
397 , transport_bar_drag_rect (0)
398 , transport_bar_range_rect (0)
399 , transport_bar_preroll_rect (0)
400 , transport_bar_postroll_rect (0)
401 , transport_loop_range_rect (0)
402 , transport_punch_range_rect (0)
403 , transport_punchin_line (0)
404 , transport_punchout_line (0)
405 , transport_preroll_rect (0)
406 , transport_postroll_rect (0)
408 , rubberband_rect (0)
414 , autoscroll_horizontal_allowed (false)
415 , autoscroll_vertical_allowed (false)
417 , autoscroll_widget (0)
418 , show_gain_after_trim (false)
419 , selection_op_cmd_depth (0)
420 , selection_op_history_it (0)
421 , no_save_instant (false)
423 , current_mixer_strip (0)
424 , show_editor_mixer_when_tracks_arrive (false)
425 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
426 , current_stepping_trackview (0)
427 , last_track_height_step_timestamp (0)
429 , entered_regionview (0)
430 , clear_entered_track (false)
431 , _edit_point (EditAtMouse)
432 , meters_running (false)
434 , _have_idled (false)
435 , resize_idle_id (-1)
436 , _pending_resize_amount (0)
437 , _pending_resize_view (0)
438 , _pending_locate_request (false)
439 , _pending_initial_locate (false)
443 , layering_order_editor (0)
444 , _last_cut_copy_source_track (0)
445 , _region_selection_change_updates_region_list (true)
447 , _following_mixer_selection (false)
448 , _control_point_toggled_on_press (false)
449 , _stepping_axis_view (0)
450 , quantize_dialog (0)
451 , _main_menu_disabler (0)
452 , myactions (X_("editor"))
454 /* we are a singleton */
456 PublicEditor::_instance = this;
460 last_event_time.tv_sec = 0;
461 last_event_time.tv_usec = 0;
463 selection_op_history.clear();
466 snap_type_strings = I18N (_snap_type_strings);
467 snap_mode_strings = I18N (_snap_mode_strings);
468 zoom_focus_strings = I18N (_zoom_focus_strings);
469 edit_mode_strings = I18N (_edit_mode_strings);
470 edit_point_strings = I18N (_edit_point_strings);
471 #ifdef USE_RUBBERBAND
472 rb_opt_strings = I18N (_rb_opt_strings);
476 build_edit_mode_menu();
477 build_zoom_focus_menu();
478 build_track_count_menu();
479 build_snap_mode_menu();
480 build_snap_type_menu();
481 build_edit_point_menu();
483 location_marker_color = UIConfiguration::instance().color ("location marker");
484 location_range_color = UIConfiguration::instance().color ("location range");
485 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
486 location_loop_color = UIConfiguration::instance().color ("location loop");
487 location_punch_color = UIConfiguration::instance().color ("location punch");
489 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
491 TimeAxisView::setup_sizes ();
492 ArdourMarker::setup_sizes (timebar_height);
493 TempoCurve::setup_sizes (timebar_height);
495 bbt_label.set_name ("EditorRulerLabel");
496 bbt_label.set_size_request (-1, (int)timebar_height);
497 bbt_label.set_alignment (1.0, 0.5);
498 bbt_label.set_padding (5,0);
500 bbt_label.set_no_show_all();
501 minsec_label.set_name ("EditorRulerLabel");
502 minsec_label.set_size_request (-1, (int)timebar_height);
503 minsec_label.set_alignment (1.0, 0.5);
504 minsec_label.set_padding (5,0);
505 minsec_label.hide ();
506 minsec_label.set_no_show_all();
507 timecode_label.set_name ("EditorRulerLabel");
508 timecode_label.set_size_request (-1, (int)timebar_height);
509 timecode_label.set_alignment (1.0, 0.5);
510 timecode_label.set_padding (5,0);
511 timecode_label.hide ();
512 timecode_label.set_no_show_all();
513 samples_label.set_name ("EditorRulerLabel");
514 samples_label.set_size_request (-1, (int)timebar_height);
515 samples_label.set_alignment (1.0, 0.5);
516 samples_label.set_padding (5,0);
517 samples_label.hide ();
518 samples_label.set_no_show_all();
520 tempo_label.set_name ("EditorRulerLabel");
521 tempo_label.set_size_request (-1, (int)timebar_height);
522 tempo_label.set_alignment (1.0, 0.5);
523 tempo_label.set_padding (5,0);
525 tempo_label.set_no_show_all();
527 meter_label.set_name ("EditorRulerLabel");
528 meter_label.set_size_request (-1, (int)timebar_height);
529 meter_label.set_alignment (1.0, 0.5);
530 meter_label.set_padding (5,0);
532 meter_label.set_no_show_all();
534 if (Profile->get_trx()) {
535 mark_label.set_text (_("Markers"));
537 mark_label.set_name ("EditorRulerLabel");
538 mark_label.set_size_request (-1, (int)timebar_height);
539 mark_label.set_alignment (1.0, 0.5);
540 mark_label.set_padding (5,0);
542 mark_label.set_no_show_all();
544 cd_mark_label.set_name ("EditorRulerLabel");
545 cd_mark_label.set_size_request (-1, (int)timebar_height);
546 cd_mark_label.set_alignment (1.0, 0.5);
547 cd_mark_label.set_padding (5,0);
548 cd_mark_label.hide();
549 cd_mark_label.set_no_show_all();
551 videotl_bar_height = 4;
552 videotl_label.set_name ("EditorRulerLabel");
553 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
554 videotl_label.set_alignment (1.0, 0.5);
555 videotl_label.set_padding (5,0);
556 videotl_label.hide();
557 videotl_label.set_no_show_all();
559 range_mark_label.set_name ("EditorRulerLabel");
560 range_mark_label.set_size_request (-1, (int)timebar_height);
561 range_mark_label.set_alignment (1.0, 0.5);
562 range_mark_label.set_padding (5,0);
563 range_mark_label.hide();
564 range_mark_label.set_no_show_all();
566 transport_mark_label.set_name ("EditorRulerLabel");
567 transport_mark_label.set_size_request (-1, (int)timebar_height);
568 transport_mark_label.set_alignment (1.0, 0.5);
569 transport_mark_label.set_padding (5,0);
570 transport_mark_label.hide();
571 transport_mark_label.set_no_show_all();
573 initialize_canvas ();
575 CairoWidget::set_focus_handler (sigc::mem_fun (ARDOUR_UI::instance(), &ARDOUR_UI::reset_focus));
577 _summary = new EditorSummary (this);
579 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
580 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
582 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
584 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
585 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
587 edit_controls_vbox.set_spacing (0);
588 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
589 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
591 HBox* h = manage (new HBox);
592 _group_tabs = new EditorGroupTabs (this);
593 if (!ARDOUR::Profile->get_trx()) {
594 h->pack_start (*_group_tabs, PACK_SHRINK);
596 h->pack_start (edit_controls_vbox);
597 controls_layout.add (*h);
599 controls_layout.set_name ("EditControlsBase");
600 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
601 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
602 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
604 _cursors = new MouseCursors;
605 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
606 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
608 /* Push default cursor to ever-present bottom of cursor stack. */
609 push_canvas_cursor(_cursors->grabber);
611 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
613 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
614 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
615 pad_line_1->set_outline_color (0xFF0000FF);
621 edit_packer.set_col_spacings (0);
622 edit_packer.set_row_spacings (0);
623 edit_packer.set_homogeneous (false);
624 edit_packer.set_border_width (0);
625 edit_packer.set_name ("EditorWindow");
627 time_bars_event_box.add (time_bars_vbox);
628 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
629 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
631 /* labels for the time bars */
632 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
634 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
636 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
638 bottom_hbox.set_border_width (2);
639 bottom_hbox.set_spacing (3);
641 _route_groups = new EditorRouteGroups (this);
642 _routes = new EditorRoutes (this);
643 _regions = new EditorRegions (this);
644 _snapshots = new EditorSnapshots (this);
645 _locations = new EditorLocations (this);
647 /* these are static location signals */
649 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
650 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
651 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
653 add_notebook_page (_("Regions"), _regions->widget ());
654 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
655 add_notebook_page (_("Snapshots"), _snapshots->widget ());
656 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
657 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
659 _the_notebook.set_show_tabs (true);
660 _the_notebook.set_scrollable (true);
661 _the_notebook.popup_disable ();
662 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
663 _the_notebook.show_all ();
665 _notebook_shrunk = false;
668 /* Pick up some settings we need to cache, early */
670 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
673 if (settings && (prop = settings->property ("notebook-shrunk"))) {
674 _notebook_shrunk = string_is_affirmative (prop->value ());
677 editor_summary_pane.set_check_divider_position (true);
678 editor_summary_pane.add (edit_packer);
680 Button* summary_arrows_left_left = manage (new Button);
681 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
682 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
683 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
685 Button* summary_arrows_left_right = manage (new Button);
686 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
687 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
688 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
690 VBox* summary_arrows_left = manage (new VBox);
691 summary_arrows_left->pack_start (*summary_arrows_left_left);
692 summary_arrows_left->pack_start (*summary_arrows_left_right);
694 Button* summary_arrows_right_up = manage (new Button);
695 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
696 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
697 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
699 Button* summary_arrows_right_down = manage (new Button);
700 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
701 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
702 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
704 VBox* summary_arrows_right = manage (new VBox);
705 summary_arrows_right->pack_start (*summary_arrows_right_up);
706 summary_arrows_right->pack_start (*summary_arrows_right_down);
708 Frame* summary_frame = manage (new Frame);
709 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
711 summary_frame->add (*_summary);
712 summary_frame->show ();
714 _summary_hbox.pack_start (*summary_arrows_left, false, false);
715 _summary_hbox.pack_start (*summary_frame, true, true);
716 _summary_hbox.pack_start (*summary_arrows_right, false, false);
718 if (!ARDOUR::Profile->get_trx()) {
719 editor_summary_pane.add (_summary_hbox);
722 edit_pane.set_check_divider_position (true);
723 edit_pane.add (editor_summary_pane);
724 if (!ARDOUR::Profile->get_trx()) {
725 edit_pane.add (_the_notebook);
728 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
729 edit_pane.set_child_minsize (_the_notebook, 30); /* rough guess at width of notebook tabs */
730 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
737 if (!settings || ((prop = settings->property ("edit-horizontal-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) {
738 /* initial allocation is 90% to canvas, 10% to notebook */
739 edit_pane.set_divider (0, 0.90);
741 edit_pane.set_divider (0, fract);
744 if (!settings || ((prop = settings->property ("edit-vertical-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) {
745 /* initial allocation is 90% to canvas, 10% to summary */
746 editor_summary_pane.set_divider (0, 0.90);
749 editor_summary_pane.set_divider (0, fract);
753 top_hbox.pack_start (toolbar_frame);
755 HBox *hbox = manage (new HBox);
756 hbox->pack_start (edit_pane, true, true);
758 global_vpacker.pack_start (top_hbox, false, false);
759 global_vpacker.pack_start (*hbox, true, true);
760 global_hpacker.pack_start (global_vpacker, true, true);
762 /* need to show the "contents" widget so that notebook will show if tab is switched to
765 global_hpacker.show ();
767 /* register actions now so that set_state() can find them and set toggles/checks etc */
774 _playlist_selector = new PlaylistSelector();
775 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
777 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
781 nudge_forward_button.set_name ("nudge button");
782 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
784 nudge_backward_button.set_name ("nudge button");
785 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
787 fade_context_menu.set_name ("ArdourContextMenu");
789 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
791 /* allow external control surfaces/protocols to do various things */
793 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
794 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
795 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
796 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
797 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
798 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
799 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
800 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
801 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
802 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
803 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
804 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
805 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
806 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
808 ControlProtocol::AddStripableToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
809 ControlProtocol::RemoveStripableFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
810 ControlProtocol::SetStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
811 ControlProtocol::ToggleStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
812 ControlProtocol::ClearStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
814 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
818 ARDOUR_UI::instance()->Escape.connect (*this, invalidator (*this), boost::bind (&Editor::escape, this), gui_context());
820 /* problematic: has to return a value and thus cannot be x-thread */
822 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
824 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
825 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
827 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
829 _ignore_region_action = false;
830 _last_region_menu_was_main = false;
831 _popup_region_menu_item = 0;
833 _ignore_follow_edits = false;
835 _show_marker_lines = false;
837 /* Button bindings */
839 button_bindings = new Bindings ("editor-mouse");
841 XMLNode* node = button_settings();
843 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
844 button_bindings->load_operation (**i);
850 /* grab current parameter state */
851 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
852 UIConfiguration::instance().map_parameters (pc);
854 setup_fade_images ();
856 LuaInstance::instance(); // instantiate
857 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &Editor::set_script_action_name));
864 delete button_bindings;
866 delete _route_groups;
867 delete _track_canvas_viewport;
870 delete _verbose_cursor;
871 delete quantize_dialog;
877 delete _playlist_selector;
879 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
885 Editor::button_settings () const
887 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
888 XMLNode* node = find_named_node (*settings, X_("Buttons"));
891 node = new XMLNode (X_("Buttons"));
898 Editor::get_smart_mode () const
900 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
904 Editor::catch_vanishing_regionview (RegionView *rv)
906 /* note: the selection will take care of the vanishing
907 audioregionview by itself.
910 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
914 if (clicked_regionview == rv) {
915 clicked_regionview = 0;
918 if (entered_regionview == rv) {
919 set_entered_regionview (0);
922 if (!_all_region_actions_sensitized) {
923 sensitize_all_region_actions (true);
928 Editor::set_entered_regionview (RegionView* rv)
930 if (rv == entered_regionview) {
934 if (entered_regionview) {
935 entered_regionview->exited ();
938 entered_regionview = rv;
940 if (entered_regionview != 0) {
941 entered_regionview->entered ();
944 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
945 /* This RegionView entry might have changed what region actions
946 are allowed, so sensitize them all in case a key is pressed.
948 sensitize_all_region_actions (true);
953 Editor::set_entered_track (TimeAxisView* tav)
956 entered_track->exited ();
962 entered_track->entered ();
967 Editor::instant_save ()
969 if (!constructed || !ARDOUR_UI::instance()->session_loaded || no_save_instant) {
974 _session->add_instant_xml(get_state());
976 Config->add_instant_xml(get_state());
981 Editor::control_vertical_zoom_in_all ()
983 tav_zoom_smooth (false, true);
987 Editor::control_vertical_zoom_out_all ()
989 tav_zoom_smooth (true, true);
993 Editor::control_vertical_zoom_in_selected ()
995 tav_zoom_smooth (false, false);
999 Editor::control_vertical_zoom_out_selected ()
1001 tav_zoom_smooth (true, false);
1005 Editor::control_view (uint32_t view)
1007 goto_visual_state (view);
1011 Editor::control_unselect ()
1013 selection->clear_tracks ();
1017 Editor::control_select (boost::shared_ptr<Stripable> s, Selection::Operation op)
1019 TimeAxisView* tav = axis_view_from_stripable (s);
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 ARDOUR_UI::instance()->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->vca_manager().VCAAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_vcas, this, _1), gui_context());
1368 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1369 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1370 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1371 _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::marker_position_changed, this), gui_context());
1372 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1373 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1374 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1375 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1376 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1377 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1378 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1380 playhead_cursor->show ();
1382 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1383 Config->map_parameters (pc);
1384 _session->config.map_parameters (pc);
1386 restore_ruler_visibility ();
1387 //tempo_map_changed (PropertyChange (0));
1388 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1390 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1391 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1394 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1395 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1398 switch (_snap_type) {
1399 case SnapToRegionStart:
1400 case SnapToRegionEnd:
1401 case SnapToRegionSync:
1402 case SnapToRegionBoundary:
1403 build_region_boundary_cache ();
1410 /* register for undo history */
1411 _session->register_with_memento_command_factory(id(), this);
1412 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1414 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1416 LuaInstance::instance()->set_session(_session);
1418 start_updating_meters ();
1422 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1424 if (a->get_name() == "RegionMenu") {
1425 /* When the main menu's region menu is opened, we setup the actions so that they look right
1426 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1427 so we resensitize all region actions when the entered regionview or the region selection
1428 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1429 happens after the region context menu is opened. So we set a flag here, too.
1433 sensitize_the_right_region_actions ();
1434 _last_region_menu_was_main = true;
1439 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1441 using namespace Menu_Helpers;
1443 void (Editor::*emf)(FadeShape);
1444 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1447 images = &_xfade_in_images;
1448 emf = &Editor::set_fade_in_shape;
1450 images = &_xfade_out_images;
1451 emf = &Editor::set_fade_out_shape;
1456 _("Linear (for highly correlated material)"),
1457 *(*images)[FadeLinear],
1458 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1462 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1466 _("Constant power"),
1467 *(*images)[FadeConstantPower],
1468 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1471 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1476 *(*images)[FadeSymmetric],
1477 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1481 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1486 *(*images)[FadeSlow],
1487 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1490 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1495 *(*images)[FadeFast],
1496 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1499 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1502 /** Pop up a context menu for when the user clicks on a start crossfade */
1504 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1506 using namespace Menu_Helpers;
1507 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1512 MenuList& items (xfade_in_context_menu.items());
1515 if (arv->audio_region()->fade_in_active()) {
1516 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1518 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1521 items.push_back (SeparatorElem());
1522 fill_xfade_menu (items, true);
1524 xfade_in_context_menu.popup (button, time);
1527 /** Pop up a context menu for when the user clicks on an end crossfade */
1529 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1531 using namespace Menu_Helpers;
1532 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1537 MenuList& items (xfade_out_context_menu.items());
1540 if (arv->audio_region()->fade_out_active()) {
1541 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1543 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1546 items.push_back (SeparatorElem());
1547 fill_xfade_menu (items, false);
1549 xfade_out_context_menu.popup (button, time);
1553 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1555 using namespace Menu_Helpers;
1556 Menu* (Editor::*build_menu_function)();
1559 switch (item_type) {
1561 case RegionViewName:
1562 case RegionViewNameHighlight:
1563 case LeftFrameHandle:
1564 case RightFrameHandle:
1565 if (with_selection) {
1566 build_menu_function = &Editor::build_track_selection_context_menu;
1568 build_menu_function = &Editor::build_track_region_context_menu;
1573 if (with_selection) {
1574 build_menu_function = &Editor::build_track_selection_context_menu;
1576 build_menu_function = &Editor::build_track_context_menu;
1581 if (clicked_routeview->track()) {
1582 build_menu_function = &Editor::build_track_context_menu;
1584 build_menu_function = &Editor::build_track_bus_context_menu;
1589 /* probably shouldn't happen but if it does, we don't care */
1593 menu = (this->*build_menu_function)();
1594 menu->set_name ("ArdourContextMenu");
1596 /* now handle specific situations */
1598 switch (item_type) {
1600 case RegionViewName:
1601 case RegionViewNameHighlight:
1602 case LeftFrameHandle:
1603 case RightFrameHandle:
1604 if (!with_selection) {
1605 if (region_edit_menu_split_item) {
1606 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1607 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1609 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1612 if (region_edit_menu_split_multichannel_item) {
1613 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1614 region_edit_menu_split_multichannel_item->set_sensitive (true);
1616 region_edit_menu_split_multichannel_item->set_sensitive (false);
1629 /* probably shouldn't happen but if it does, we don't care */
1633 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1635 /* Bounce to disk */
1637 using namespace Menu_Helpers;
1638 MenuList& edit_items = menu->items();
1640 edit_items.push_back (SeparatorElem());
1642 switch (clicked_routeview->audio_track()->freeze_state()) {
1643 case AudioTrack::NoFreeze:
1644 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1647 case AudioTrack::Frozen:
1648 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1651 case AudioTrack::UnFrozen:
1652 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1658 if (item_type == StreamItem && clicked_routeview) {
1659 clicked_routeview->build_underlay_menu(menu);
1662 /* When the region menu is opened, we setup the actions so that they look right
1665 sensitize_the_right_region_actions ();
1666 _last_region_menu_was_main = false;
1668 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1669 menu->popup (button, time);
1673 Editor::build_track_context_menu ()
1675 using namespace Menu_Helpers;
1677 MenuList& edit_items = track_context_menu.items();
1680 add_dstream_context_items (edit_items);
1681 return &track_context_menu;
1685 Editor::build_track_bus_context_menu ()
1687 using namespace Menu_Helpers;
1689 MenuList& edit_items = track_context_menu.items();
1692 add_bus_context_items (edit_items);
1693 return &track_context_menu;
1697 Editor::build_track_region_context_menu ()
1699 using namespace Menu_Helpers;
1700 MenuList& edit_items = track_region_context_menu.items();
1703 /* we've just cleared the track region context menu, so the menu that these
1704 two items were on will have disappeared; stop them dangling.
1706 region_edit_menu_split_item = 0;
1707 region_edit_menu_split_multichannel_item = 0;
1709 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1712 boost::shared_ptr<Track> tr;
1713 boost::shared_ptr<Playlist> pl;
1715 if ((tr = rtv->track())) {
1716 add_region_context_items (edit_items, tr);
1720 add_dstream_context_items (edit_items);
1722 return &track_region_context_menu;
1726 Editor::loudness_analyze_region_selection ()
1731 Selection& s (PublicEditor::instance ().get_selection ());
1732 RegionSelection ars = s.regions;
1733 ARDOUR::AnalysisGraph ag (_session);
1734 framecnt_t total_work = 0;
1736 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1737 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1741 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1744 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1745 total_work += arv->region ()->length ();
1748 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1750 ag.set_total_frames (total_work);
1751 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1754 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1755 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1759 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1763 ag.analyze_region (ar);
1766 if (!ag.canceled ()) {
1767 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1773 Editor::loudness_analyze_range_selection ()
1778 Selection& s (PublicEditor::instance ().get_selection ());
1779 TimeSelection ts = s.time;
1780 ARDOUR::AnalysisGraph ag (_session);
1781 framecnt_t total_work = 0;
1783 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1784 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1788 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1792 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1793 total_work += j->length ();
1797 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1799 ag.set_total_frames (total_work);
1800 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1803 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1804 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1808 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1812 ag.analyze_range (rui->route (), pl, ts);
1815 if (!ag.canceled ()) {
1816 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1822 Editor::spectral_analyze_region_selection ()
1824 if (analysis_window == 0) {
1825 analysis_window = new AnalysisWindow();
1828 analysis_window->set_session(_session);
1830 analysis_window->show_all();
1833 analysis_window->set_regionmode();
1834 analysis_window->analyze();
1836 analysis_window->present();
1840 Editor::spectral_analyze_range_selection()
1842 if (analysis_window == 0) {
1843 analysis_window = new AnalysisWindow();
1846 analysis_window->set_session(_session);
1848 analysis_window->show_all();
1851 analysis_window->set_rangemode();
1852 analysis_window->analyze();
1854 analysis_window->present();
1858 Editor::build_track_selection_context_menu ()
1860 using namespace Menu_Helpers;
1861 MenuList& edit_items = track_selection_context_menu.items();
1862 edit_items.clear ();
1864 add_selection_context_items (edit_items);
1865 // edit_items.push_back (SeparatorElem());
1866 // add_dstream_context_items (edit_items);
1868 return &track_selection_context_menu;
1872 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1874 using namespace Menu_Helpers;
1876 /* OK, stick the region submenu at the top of the list, and then add
1880 RegionSelection rs = get_regions_from_selection_and_entered ();
1882 string::size_type pos = 0;
1883 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1885 /* we have to hack up the region name because "_" has a special
1886 meaning for menu titles.
1889 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1890 menu_item_name.replace (pos, 1, "__");
1894 if (_popup_region_menu_item == 0) {
1895 _popup_region_menu_item = new MenuItem (menu_item_name);
1896 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1897 _popup_region_menu_item->show ();
1899 _popup_region_menu_item->set_label (menu_item_name);
1902 /* No latering allowed in later is higher layering model */
1903 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1904 if (act && Config->get_layer_model() == LaterHigher) {
1905 act->set_sensitive (false);
1907 act->set_sensitive (true);
1910 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1912 edit_items.push_back (*_popup_region_menu_item);
1913 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1914 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1916 edit_items.push_back (SeparatorElem());
1919 /** Add context menu items relevant to selection ranges.
1920 * @param edit_items List to add the items to.
1923 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1925 using namespace Menu_Helpers;
1927 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1928 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1930 edit_items.push_back (SeparatorElem());
1931 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1933 edit_items.push_back (SeparatorElem());
1934 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1935 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1937 edit_items.push_back (SeparatorElem());
1939 edit_items.push_back (
1941 _("Move Range Start to Previous Region Boundary"),
1942 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1946 edit_items.push_back (
1948 _("Move Range Start to Next Region Boundary"),
1949 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1953 edit_items.push_back (
1955 _("Move Range End to Previous Region Boundary"),
1956 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1960 edit_items.push_back (
1962 _("Move Range End to Next Region Boundary"),
1963 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1967 edit_items.push_back (SeparatorElem());
1968 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1969 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1971 edit_items.push_back (SeparatorElem());
1972 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1974 edit_items.push_back (SeparatorElem());
1975 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1976 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1977 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1979 edit_items.push_back (SeparatorElem());
1980 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1982 edit_items.push_back (SeparatorElem());
1983 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1984 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1986 edit_items.push_back (SeparatorElem());
1987 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1988 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1989 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1990 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1991 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1992 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1993 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1999 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2001 using namespace Menu_Helpers;
2005 Menu *play_menu = manage (new Menu);
2006 MenuList& play_items = play_menu->items();
2007 play_menu->set_name ("ArdourContextMenu");
2009 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2010 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2011 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2012 play_items.push_back (SeparatorElem());
2013 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2015 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2019 Menu *select_menu = manage (new Menu);
2020 MenuList& select_items = select_menu->items();
2021 select_menu->set_name ("ArdourContextMenu");
2023 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2024 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2025 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2026 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2027 select_items.push_back (SeparatorElem());
2028 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2029 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2030 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2031 select_items.push_back (SeparatorElem());
2032 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2033 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2034 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2035 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2036 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2037 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2038 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2040 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2044 Menu *cutnpaste_menu = manage (new Menu);
2045 MenuList& cutnpaste_items = cutnpaste_menu->items();
2046 cutnpaste_menu->set_name ("ArdourContextMenu");
2048 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2049 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2050 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2052 cutnpaste_items.push_back (SeparatorElem());
2054 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2055 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2057 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2059 /* Adding new material */
2061 edit_items.push_back (SeparatorElem());
2062 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2063 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2067 Menu *nudge_menu = manage (new Menu());
2068 MenuList& nudge_items = nudge_menu->items();
2069 nudge_menu->set_name ("ArdourContextMenu");
2071 edit_items.push_back (SeparatorElem());
2072 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2073 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2074 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2075 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2077 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2081 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2083 using namespace Menu_Helpers;
2087 Menu *play_menu = manage (new Menu);
2088 MenuList& play_items = play_menu->items();
2089 play_menu->set_name ("ArdourContextMenu");
2091 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2092 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2093 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2097 Menu *select_menu = manage (new Menu);
2098 MenuList& select_items = select_menu->items();
2099 select_menu->set_name ("ArdourContextMenu");
2101 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2102 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2103 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2104 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2105 select_items.push_back (SeparatorElem());
2106 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2107 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2108 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2109 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2111 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2115 Menu *cutnpaste_menu = manage (new Menu);
2116 MenuList& cutnpaste_items = cutnpaste_menu->items();
2117 cutnpaste_menu->set_name ("ArdourContextMenu");
2119 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2120 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2121 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2123 Menu *nudge_menu = manage (new Menu());
2124 MenuList& nudge_items = nudge_menu->items();
2125 nudge_menu->set_name ("ArdourContextMenu");
2127 edit_items.push_back (SeparatorElem());
2128 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2129 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2130 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2131 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2133 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2137 Editor::snap_type() const
2143 Editor::snap_musical() const
2145 switch (_snap_type) {
2146 case SnapToBeatDiv128:
2147 case SnapToBeatDiv64:
2148 case SnapToBeatDiv32:
2149 case SnapToBeatDiv28:
2150 case SnapToBeatDiv24:
2151 case SnapToBeatDiv20:
2152 case SnapToBeatDiv16:
2153 case SnapToBeatDiv14:
2154 case SnapToBeatDiv12:
2155 case SnapToBeatDiv10:
2156 case SnapToBeatDiv8:
2157 case SnapToBeatDiv7:
2158 case SnapToBeatDiv6:
2159 case SnapToBeatDiv5:
2160 case SnapToBeatDiv4:
2161 case SnapToBeatDiv3:
2162 case SnapToBeatDiv2:
2174 Editor::snap_mode() const
2180 Editor::set_snap_to (SnapType st)
2182 unsigned int snap_ind = (unsigned int)st;
2184 if (internal_editing()) {
2185 internal_snap_type = st;
2187 pre_internal_snap_type = st;
2192 if (snap_ind > snap_type_strings.size() - 1) {
2194 _snap_type = (SnapType)snap_ind;
2197 string str = snap_type_strings[snap_ind];
2199 if (str != snap_type_selector.get_text()) {
2200 snap_type_selector.set_text (str);
2205 switch (_snap_type) {
2206 case SnapToBeatDiv128:
2207 case SnapToBeatDiv64:
2208 case SnapToBeatDiv32:
2209 case SnapToBeatDiv28:
2210 case SnapToBeatDiv24:
2211 case SnapToBeatDiv20:
2212 case SnapToBeatDiv16:
2213 case SnapToBeatDiv14:
2214 case SnapToBeatDiv12:
2215 case SnapToBeatDiv10:
2216 case SnapToBeatDiv8:
2217 case SnapToBeatDiv7:
2218 case SnapToBeatDiv6:
2219 case SnapToBeatDiv5:
2220 case SnapToBeatDiv4:
2221 case SnapToBeatDiv3:
2222 case SnapToBeatDiv2: {
2223 std::vector<TempoMap::BBTPoint> grid;
2224 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
2225 compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples());
2226 update_tempo_based_rulers (grid);
2230 case SnapToRegionStart:
2231 case SnapToRegionEnd:
2232 case SnapToRegionSync:
2233 case SnapToRegionBoundary:
2234 build_region_boundary_cache ();
2242 redisplay_tempo (false);
2244 SnapChanged (); /* EMIT SIGNAL */
2248 Editor::set_snap_mode (SnapMode mode)
2250 string str = snap_mode_strings[(int)mode];
2252 if (internal_editing()) {
2253 internal_snap_mode = mode;
2255 pre_internal_snap_mode = mode;
2260 if (str != snap_mode_selector.get_text ()) {
2261 snap_mode_selector.set_text (str);
2268 Editor::set_edit_point_preference (EditPoint ep, bool force)
2270 bool changed = (_edit_point != ep);
2273 if (Profile->get_mixbus())
2274 if (ep == EditAtSelectedMarker)
2275 ep = EditAtPlayhead;
2277 string str = edit_point_strings[(int)ep];
2278 if (str != edit_point_selector.get_text ()) {
2279 edit_point_selector.set_text (str);
2282 update_all_enter_cursors();
2284 if (!force && !changed) {
2288 const char* action=NULL;
2290 switch (_edit_point) {
2291 case EditAtPlayhead:
2292 action = "edit-at-playhead";
2294 case EditAtSelectedMarker:
2295 action = "edit-at-marker";
2298 action = "edit-at-mouse";
2302 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2304 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2308 bool in_track_canvas;
2310 if (!mouse_frame (foo, in_track_canvas)) {
2311 in_track_canvas = false;
2314 reset_canvas_action_sensitivity (in_track_canvas);
2320 Editor::set_state (const XMLNode& node, int version)
2322 XMLProperty const * prop;
2324 PBD::Unwinder<bool> nsi (no_save_instant, true);
2327 Tabbable::set_state (node, version);
2329 if (_session && (prop = node.property ("playhead"))) {
2331 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2333 playhead_cursor->set_position (pos);
2335 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2336 playhead_cursor->set_position (0);
2339 playhead_cursor->set_position (0);
2342 if ((prop = node.property ("mixer-width"))) {
2343 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2346 if ((prop = node.property ("zoom-focus"))) {
2347 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2349 zoom_focus_selection_done (zoom_focus);
2352 if ((prop = node.property ("zoom"))) {
2353 /* older versions of ardour used floating point samples_per_pixel */
2354 double f = PBD::atof (prop->value());
2355 reset_zoom (llrintf (f));
2357 reset_zoom (samples_per_pixel);
2360 if ((prop = node.property ("visible-track-count"))) {
2361 set_visible_track_count (PBD::atoi (prop->value()));
2364 if ((prop = node.property ("snap-to"))) {
2365 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2366 set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
2368 set_snap_to (_snap_type);
2371 if ((prop = node.property ("snap-mode"))) {
2372 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2373 /* set text of Dropdown. in case _snap_mode == SnapOff (default)
2374 * snap_mode_selection_done() will only mark an already active item as active
2375 * which does not trigger set_text().
2377 set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode));
2379 set_snap_mode (_snap_mode);
2382 if ((prop = node.property ("internal-snap-to"))) {
2383 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2386 if ((prop = node.property ("internal-snap-mode"))) {
2387 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2390 if ((prop = node.property ("pre-internal-snap-to"))) {
2391 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2394 if ((prop = node.property ("pre-internal-snap-mode"))) {
2395 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2398 if ((prop = node.property ("mouse-mode"))) {
2399 MouseMode m = str2mousemode(prop->value());
2400 set_mouse_mode (m, true);
2402 set_mouse_mode (MouseObject, true);
2405 if ((prop = node.property ("left-frame")) != 0) {
2407 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2411 reset_x_origin (pos);
2415 if ((prop = node.property ("y-origin")) != 0) {
2416 reset_y_origin (atof (prop->value ()));
2419 if ((prop = node.property ("join-object-range"))) {
2420 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2421 bool yn = string_is_affirmative (prop->value());
2423 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2424 tact->set_active (!yn);
2425 tact->set_active (yn);
2427 set_mouse_mode(mouse_mode, true);
2430 if ((prop = node.property ("edit-point"))) {
2431 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2433 set_edit_point_preference (_edit_point);
2436 if ((prop = node.property ("show-measures"))) {
2437 bool yn = string_is_affirmative (prop->value());
2438 _show_measures = yn;
2441 if ((prop = node.property ("follow-playhead"))) {
2442 bool yn = string_is_affirmative (prop->value());
2443 set_follow_playhead (yn);
2446 if ((prop = node.property ("stationary-playhead"))) {
2447 bool yn = string_is_affirmative (prop->value());
2448 set_stationary_playhead (yn);
2451 if ((prop = node.property ("region-list-sort-type"))) {
2452 RegionListSortType st;
2453 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2456 if ((prop = node.property ("show-editor-mixer"))) {
2458 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2461 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2462 bool yn = string_is_affirmative (prop->value());
2464 /* do it twice to force the change */
2466 tact->set_active (!yn);
2467 tact->set_active (yn);
2470 if ((prop = node.property ("show-editor-list"))) {
2472 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2475 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2476 bool yn = string_is_affirmative (prop->value());
2478 /* do it twice to force the change */
2480 tact->set_active (!yn);
2481 tact->set_active (yn);
2484 if ((prop = node.property (X_("editor-list-page")))) {
2485 _the_notebook.set_current_page (atoi (prop->value ()));
2488 if ((prop = node.property (X_("show-marker-lines")))) {
2489 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2491 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2492 bool yn = string_is_affirmative (prop->value ());
2494 tact->set_active (!yn);
2495 tact->set_active (yn);
2498 XMLNodeList children = node.children ();
2499 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2500 selection->set_state (**i, Stateful::current_state_version);
2501 _regions->set_state (**i);
2504 if ((prop = node.property ("maximised"))) {
2505 bool yn = string_is_affirmative (prop->value());
2506 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2508 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2509 bool fs = tact && tact->get_active();
2511 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2515 if ((prop = node.property ("nudge-clock-value"))) {
2517 sscanf (prop->value().c_str(), "%" PRId64, &f);
2518 nudge_clock->set (f);
2520 nudge_clock->set_mode (AudioClock::Timecode);
2521 nudge_clock->set (_session->frame_rate() * 5, true);
2526 * Not all properties may have been in XML, but
2527 * those that are linked to a private variable may need changing
2532 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2534 yn = _show_measures;
2535 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2536 /* do it twice to force the change */
2537 tact->set_active (!yn);
2538 tact->set_active (yn);
2541 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2542 yn = _follow_playhead;
2544 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2545 if (tact->get_active() != yn) {
2546 tact->set_active (yn);
2550 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2551 yn = _stationary_playhead;
2553 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2554 if (tact->get_active() != yn) {
2555 tact->set_active (yn);
2560 return LuaInstance::instance()->set_state(node);
2564 Editor::get_state ()
2566 XMLNode* node = new XMLNode (X_("Editor"));
2570 id().print (buf, sizeof (buf));
2571 node->add_property ("id", buf);
2573 node->add_child_nocopy (Tabbable::get_state());
2575 snprintf(buf,sizeof(buf), "%f", edit_pane.get_divider ());
2576 node->add_property("edit-horizontal-pane-pos", string(buf));
2577 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2578 snprintf(buf,sizeof(buf), "%f", editor_summary_pane.get_divider());
2579 node->add_property("edit-vertical-pane-pos", string(buf));
2581 maybe_add_mixer_strip_width (*node);
2583 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2585 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2586 node->add_property ("zoom", buf);
2587 node->add_property ("snap-to", enum_2_string (_snap_type));
2588 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2589 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2590 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2591 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2592 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2593 node->add_property ("edit-point", enum_2_string (_edit_point));
2594 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2595 node->add_property ("visible-track-count", buf);
2597 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2598 node->add_property ("playhead", buf);
2599 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2600 node->add_property ("left-frame", buf);
2601 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2602 node->add_property ("y-origin", buf);
2604 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2605 node->add_property ("maximised", _maximised ? "yes" : "no");
2606 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2607 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2608 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2609 node->add_property ("mouse-mode", enum2str(mouse_mode));
2610 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2612 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2614 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2615 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2618 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2620 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2621 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2624 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2625 node->add_property (X_("editor-list-page"), buf);
2627 if (button_bindings) {
2628 XMLNode* bb = new XMLNode (X_("Buttons"));
2629 button_bindings->save (*bb);
2630 node->add_child_nocopy (*bb);
2633 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2635 node->add_child_nocopy (selection->get_state ());
2636 node->add_child_nocopy (_regions->get_state ());
2638 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2639 node->add_property ("nudge-clock-value", buf);
2641 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2642 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2647 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2648 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2650 * @return pair: TimeAxisView that y is over, layer index.
2652 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2653 * in stacked or expanded region display mode, otherwise 0.
2655 std::pair<TimeAxisView *, double>
2656 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2658 if (!trackview_relative_offset) {
2659 y -= _trackview_group->canvas_origin().y;
2663 return std::make_pair ( (TimeAxisView *) 0, 0);
2666 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2668 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2675 return std::make_pair ( (TimeAxisView *) 0, 0);
2678 /** Snap a position to the grid, if appropriate, taking into account current
2679 * grid settings and also the state of any snap modifier keys that may be pressed.
2680 * @param start Position to snap.
2681 * @param event Event to get current key modifier information from, or 0.
2684 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2686 if (!_session || !event) {
2690 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2691 if (_snap_mode == SnapOff) {
2692 snap_to_internal (start, direction, for_mark);
2695 if (_snap_mode != SnapOff) {
2696 snap_to_internal (start, direction, for_mark);
2697 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2698 /* SnapOff, but we pressed the snap_delta modifier */
2699 snap_to_internal (start, direction, for_mark);
2705 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2707 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2711 snap_to_internal (start, direction, for_mark, ensure_snap);
2715 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2717 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2718 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2720 switch (_snap_type) {
2721 case SnapToTimecodeFrame:
2722 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2723 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2724 /* start is already on a whole timecode frame, do nothing */
2725 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2726 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2728 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2732 case SnapToTimecodeSeconds:
2733 if (_session->config.get_timecode_offset_negative()) {
2734 start += _session->config.get_timecode_offset ();
2736 start -= _session->config.get_timecode_offset ();
2738 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2739 (start % one_timecode_second == 0)) {
2740 /* start is already on a whole second, do nothing */
2741 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2742 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2744 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2747 if (_session->config.get_timecode_offset_negative()) {
2748 start -= _session->config.get_timecode_offset ();
2750 start += _session->config.get_timecode_offset ();
2754 case SnapToTimecodeMinutes:
2755 if (_session->config.get_timecode_offset_negative()) {
2756 start += _session->config.get_timecode_offset ();
2758 start -= _session->config.get_timecode_offset ();
2760 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2761 (start % one_timecode_minute == 0)) {
2762 /* start is already on a whole minute, do nothing */
2763 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2764 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2766 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2768 if (_session->config.get_timecode_offset_negative()) {
2769 start -= _session->config.get_timecode_offset ();
2771 start += _session->config.get_timecode_offset ();
2775 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2776 abort(); /*NOTREACHED*/
2781 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2783 const framepos_t one_second = _session->frame_rate();
2784 const framepos_t one_minute = _session->frame_rate() * 60;
2785 framepos_t presnap = start;
2789 switch (_snap_type) {
2790 case SnapToTimecodeFrame:
2791 case SnapToTimecodeSeconds:
2792 case SnapToTimecodeMinutes:
2793 return timecode_snap_to_internal (start, direction, for_mark);
2796 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2797 start % (one_second/75) == 0) {
2798 /* start is already on a whole CD frame, do nothing */
2799 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2800 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2802 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2807 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2808 start % one_second == 0) {
2809 /* start is already on a whole second, do nothing */
2810 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2811 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2813 start = (framepos_t) floor ((double) start / one_second) * one_second;
2818 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2819 start % one_minute == 0) {
2820 /* start is already on a whole minute, do nothing */
2821 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2822 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2824 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2829 start = _session->tempo_map().round_to_bar (start, direction);
2833 start = _session->tempo_map().round_to_beat (start, direction);
2836 case SnapToBeatDiv128:
2837 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 128, direction);
2839 case SnapToBeatDiv64:
2840 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 64, direction);
2842 case SnapToBeatDiv32:
2843 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 32, direction);
2845 case SnapToBeatDiv28:
2846 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 28, direction);
2848 case SnapToBeatDiv24:
2849 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 24, direction);
2851 case SnapToBeatDiv20:
2852 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 20, direction);
2854 case SnapToBeatDiv16:
2855 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 16, direction);
2857 case SnapToBeatDiv14:
2858 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 14, direction);
2860 case SnapToBeatDiv12:
2861 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 12, direction);
2863 case SnapToBeatDiv10:
2864 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 10, direction);
2866 case SnapToBeatDiv8:
2867 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 8, direction);
2869 case SnapToBeatDiv7:
2870 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 7, direction);
2872 case SnapToBeatDiv6:
2873 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 6, direction);
2875 case SnapToBeatDiv5:
2876 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 5, direction);
2878 case SnapToBeatDiv4:
2879 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 4, direction);
2881 case SnapToBeatDiv3:
2882 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 3, direction);
2884 case SnapToBeatDiv2:
2885 start = _session->tempo_map().round_to_quarter_note_subdivision (start, 2, direction);
2893 _session->locations()->marks_either_side (start, before, after);
2895 if (before == max_framepos && after == max_framepos) {
2896 /* No marks to snap to, so just don't snap */
2898 } else if (before == max_framepos) {
2900 } else if (after == max_framepos) {
2902 } else if (before != max_framepos && after != max_framepos) {
2903 /* have before and after */
2904 if ((start - before) < (after - start)) {
2913 case SnapToRegionStart:
2914 case SnapToRegionEnd:
2915 case SnapToRegionSync:
2916 case SnapToRegionBoundary:
2917 if (!region_boundary_cache.empty()) {
2919 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2920 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2922 if (direction > 0) {
2923 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2925 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2928 if (next != region_boundary_cache.begin ()) {
2933 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2934 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2936 if (start > (p + n) / 2) {
2945 switch (_snap_mode) {
2955 if (presnap > start) {
2956 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2960 } else if (presnap < start) {
2961 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2967 /* handled at entry */
2975 Editor::setup_toolbar ()
2977 HBox* mode_box = manage(new HBox);
2978 mode_box->set_border_width (2);
2979 mode_box->set_spacing(2);
2981 HBox* mouse_mode_box = manage (new HBox);
2982 HBox* mouse_mode_hbox = manage (new HBox);
2983 VBox* mouse_mode_vbox = manage (new VBox);
2984 Alignment* mouse_mode_align = manage (new Alignment);
2986 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2987 mouse_mode_size_group->add_widget (smart_mode_button);
2988 mouse_mode_size_group->add_widget (mouse_move_button);
2989 mouse_mode_size_group->add_widget (mouse_cut_button);
2990 mouse_mode_size_group->add_widget (mouse_select_button);
2991 mouse_mode_size_group->add_widget (mouse_timefx_button);
2992 mouse_mode_size_group->add_widget (mouse_audition_button);
2993 mouse_mode_size_group->add_widget (mouse_draw_button);
2994 mouse_mode_size_group->add_widget (mouse_content_button);
2996 mouse_mode_size_group->add_widget (zoom_in_button);
2997 mouse_mode_size_group->add_widget (zoom_out_button);
2998 mouse_mode_size_group->add_widget (zoom_preset_selector);
2999 mouse_mode_size_group->add_widget (zoom_out_full_button);
3000 mouse_mode_size_group->add_widget (zoom_focus_selector);
3002 mouse_mode_size_group->add_widget (tav_shrink_button);
3003 mouse_mode_size_group->add_widget (tav_expand_button);
3004 mouse_mode_size_group->add_widget (visible_tracks_selector);
3006 mouse_mode_size_group->add_widget (snap_type_selector);
3007 mouse_mode_size_group->add_widget (snap_mode_selector);
3009 mouse_mode_size_group->add_widget (edit_point_selector);
3010 mouse_mode_size_group->add_widget (edit_mode_selector);
3012 mouse_mode_size_group->add_widget (*nudge_clock);
3013 mouse_mode_size_group->add_widget (nudge_forward_button);
3014 mouse_mode_size_group->add_widget (nudge_backward_button);
3016 mouse_mode_hbox->set_spacing (2);
3018 if (!ARDOUR::Profile->get_trx()) {
3019 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
3022 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
3023 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
3025 if (!ARDOUR::Profile->get_mixbus()) {
3026 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
3029 if (!ARDOUR::Profile->get_trx()) {
3030 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
3031 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
3032 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
3033 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
3036 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
3038 mouse_mode_align->add (*mouse_mode_vbox);
3039 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
3041 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
3043 edit_mode_selector.set_name ("mouse mode button");
3045 if (!ARDOUR::Profile->get_trx()) {
3046 mode_box->pack_start (edit_mode_selector, false, false);
3049 mode_box->pack_start (*mouse_mode_box, false, false);
3053 _zoom_box.set_spacing (2);
3054 _zoom_box.set_border_width (2);
3058 zoom_preset_selector.set_name ("zoom button");
3059 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3060 zoom_preset_selector.set_size_request (42, -1);
3062 zoom_in_button.set_name ("zoom button");
3063 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3064 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3065 zoom_in_button.set_related_action (act);
3067 zoom_out_button.set_name ("zoom button");
3068 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3069 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3070 zoom_out_button.set_related_action (act);
3072 zoom_out_full_button.set_name ("zoom button");
3073 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3074 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3075 zoom_out_full_button.set_related_action (act);
3077 zoom_focus_selector.set_name ("zoom button");
3079 if (ARDOUR::Profile->get_mixbus()) {
3080 _zoom_box.pack_start (zoom_preset_selector, false, false);
3081 } else if (ARDOUR::Profile->get_trx()) {
3082 mode_box->pack_start (zoom_out_button, false, false);
3083 mode_box->pack_start (zoom_in_button, false, false);
3085 _zoom_box.pack_start (zoom_out_button, false, false);
3086 _zoom_box.pack_start (zoom_in_button, false, false);
3087 _zoom_box.pack_start (zoom_out_full_button, false, false);
3088 _zoom_box.pack_start (zoom_focus_selector, false, false);
3091 /* Track zoom buttons */
3092 visible_tracks_selector.set_name ("zoom button");
3093 if (Profile->get_mixbus()) {
3094 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3095 visible_tracks_selector.set_size_request (42, -1);
3097 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3100 tav_expand_button.set_name ("zoom button");
3101 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3102 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3103 tav_expand_button.set_related_action (act);
3105 tav_shrink_button.set_name ("zoom button");
3106 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3107 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3108 tav_shrink_button.set_related_action (act);
3110 if (ARDOUR::Profile->get_mixbus()) {
3111 _zoom_box.pack_start (visible_tracks_selector);
3112 } else if (ARDOUR::Profile->get_trx()) {
3113 _zoom_box.pack_start (tav_shrink_button);
3114 _zoom_box.pack_start (tav_expand_button);
3116 _zoom_box.pack_start (visible_tracks_selector);
3117 _zoom_box.pack_start (tav_shrink_button);
3118 _zoom_box.pack_start (tav_expand_button);
3121 snap_box.set_spacing (2);
3122 snap_box.set_border_width (2);
3124 snap_type_selector.set_name ("mouse mode button");
3126 snap_mode_selector.set_name ("mouse mode button");
3128 edit_point_selector.set_name ("mouse mode button");
3130 snap_box.pack_start (snap_mode_selector, false, false);
3131 snap_box.pack_start (snap_type_selector, false, false);
3132 snap_box.pack_start (edit_point_selector, false, false);
3136 HBox *nudge_box = manage (new HBox);
3137 nudge_box->set_spacing (2);
3138 nudge_box->set_border_width (2);
3140 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3141 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3143 nudge_box->pack_start (nudge_backward_button, false, false);
3144 nudge_box->pack_start (nudge_forward_button, false, false);
3145 nudge_box->pack_start (*nudge_clock, false, false);
3148 /* Pack everything in... */
3150 HBox* hbox = manage (new HBox);
3151 hbox->set_spacing(2);
3153 toolbar_hbox.set_spacing (2);
3154 toolbar_hbox.set_border_width (1);
3156 toolbar_hbox.pack_start (*mode_box, false, false);
3157 if (!ARDOUR::Profile->get_trx()) {
3158 toolbar_hbox.pack_start (_zoom_box, false, false);
3159 toolbar_hbox.pack_start (*hbox, false, false);
3162 if (!ARDOUR::Profile->get_trx()) {
3163 hbox->pack_start (snap_box, false, false);
3164 hbox->pack_start (*nudge_box, false, false);
3169 toolbar_base.set_name ("ToolBarBase");
3170 toolbar_base.add (toolbar_hbox);
3172 _toolbar_viewport.add (toolbar_base);
3173 /* stick to the required height but allow width to vary if there's not enough room */
3174 _toolbar_viewport.set_size_request (1, -1);
3176 toolbar_frame.set_shadow_type (SHADOW_OUT);
3177 toolbar_frame.set_name ("BaseFrame");
3178 toolbar_frame.add (_toolbar_viewport);
3182 Editor::build_edit_point_menu ()
3184 using namespace Menu_Helpers;
3186 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3187 if(!Profile->get_mixbus())
3188 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3189 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3191 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3195 Editor::build_edit_mode_menu ()
3197 using namespace Menu_Helpers;
3199 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3200 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3201 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3202 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3204 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3208 Editor::build_snap_mode_menu ()
3210 using namespace Menu_Helpers;
3212 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3213 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3214 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3216 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3220 Editor::build_snap_type_menu ()
3222 using namespace Menu_Helpers;
3224 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3225 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3226 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3227 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3228 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3229 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3230 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3231 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3232 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3233 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3234 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3235 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3236 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3237 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3238 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3239 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3240 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3241 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3242 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3243 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3244 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3245 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3246 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3247 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3248 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3249 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3250 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3251 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3252 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3253 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3255 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3260 Editor::setup_tooltips ()
3262 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3263 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3264 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3265 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3266 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3267 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3268 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3269 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3270 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3271 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3272 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3273 set_tooltip (zoom_in_button, _("Zoom In"));
3274 set_tooltip (zoom_out_button, _("Zoom Out"));
3275 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3276 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3277 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3278 set_tooltip (tav_expand_button, _("Expand Tracks"));
3279 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3280 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3281 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3282 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3283 set_tooltip (edit_point_selector, _("Edit Point"));
3284 set_tooltip (edit_mode_selector, _("Edit Mode"));
3285 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3289 Editor::convert_drop_to_paths (
3290 vector<string>& paths,
3291 const RefPtr<Gdk::DragContext>& /*context*/,
3294 const SelectionData& data,
3298 if (_session == 0) {
3302 vector<string> uris = data.get_uris();
3306 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3307 are actually URI lists. So do it by hand.
3310 if (data.get_target() != "text/plain") {
3314 /* Parse the "uri-list" format that Nautilus provides,
3315 where each pathname is delimited by \r\n.
3317 THERE MAY BE NO NULL TERMINATING CHAR!!!
3320 string txt = data.get_text();
3324 p = (char *) malloc (txt.length() + 1);
3325 txt.copy (p, txt.length(), 0);
3326 p[txt.length()] = '\0';
3332 while (g_ascii_isspace (*p))
3336 while (*q && (*q != '\n') && (*q != '\r')) {
3343 while (q > p && g_ascii_isspace (*q))
3348 uris.push_back (string (p, q - p + 1));
3352 p = strchr (p, '\n');
3364 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3365 if ((*i).substr (0,7) == "file://") {
3366 paths.push_back (Glib::filename_from_uri (*i));
3374 Editor::new_tempo_section ()
3379 Editor::map_transport_state ()
3381 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3383 if (_session && _session->transport_stopped()) {
3384 have_pending_keyboard_selection = false;
3387 update_loop_range_view ();
3393 Editor::begin_selection_op_history ()
3395 selection_op_cmd_depth = 0;
3396 selection_op_history_it = 0;
3398 while(!selection_op_history.empty()) {
3399 delete selection_op_history.front();
3400 selection_op_history.pop_front();
3403 selection_undo_action->set_sensitive (false);
3404 selection_redo_action->set_sensitive (false);
3405 selection_op_history.push_front (&_selection_memento->get_state ());
3409 Editor::begin_reversible_selection_op (string name)
3412 //cerr << name << endl;
3413 /* begin/commit pairs can be nested */
3414 selection_op_cmd_depth++;
3419 Editor::commit_reversible_selection_op ()
3422 if (selection_op_cmd_depth == 1) {
3424 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3426 The user has undone some selection ops and then made a new one,
3427 making anything earlier in the list invalid.
3430 list<XMLNode *>::iterator it = selection_op_history.begin();
3431 list<XMLNode *>::iterator e_it = it;
3432 advance (e_it, selection_op_history_it);
3434 for ( ; it != e_it; ++it) {
3437 selection_op_history.erase (selection_op_history.begin(), e_it);
3440 selection_op_history.push_front (&_selection_memento->get_state ());
3441 selection_op_history_it = 0;
3443 selection_undo_action->set_sensitive (true);
3444 selection_redo_action->set_sensitive (false);
3447 if (selection_op_cmd_depth > 0) {
3448 selection_op_cmd_depth--;
3454 Editor::undo_selection_op ()
3457 selection_op_history_it++;
3459 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3460 if (n == selection_op_history_it) {
3461 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3462 selection_redo_action->set_sensitive (true);
3466 /* is there an earlier entry? */
3467 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3468 selection_undo_action->set_sensitive (false);
3474 Editor::redo_selection_op ()
3477 if (selection_op_history_it > 0) {
3478 selection_op_history_it--;
3481 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3482 if (n == selection_op_history_it) {
3483 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3484 selection_undo_action->set_sensitive (true);
3489 if (selection_op_history_it == 0) {
3490 selection_redo_action->set_sensitive (false);
3496 Editor::begin_reversible_command (string name)
3499 before.push_back (&_selection_memento->get_state ());
3500 _session->begin_reversible_command (name);
3505 Editor::begin_reversible_command (GQuark q)
3508 before.push_back (&_selection_memento->get_state ());
3509 _session->begin_reversible_command (q);
3514 Editor::abort_reversible_command ()
3517 while(!before.empty()) {
3518 delete before.front();
3521 _session->abort_reversible_command ();
3526 Editor::commit_reversible_command ()
3529 if (before.size() == 1) {
3530 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3531 redo_action->set_sensitive(false);
3532 undo_action->set_sensitive(true);
3533 begin_selection_op_history ();
3536 if (before.empty()) {
3537 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3542 _session->commit_reversible_command ();
3547 Editor::history_changed ()
3551 if (undo_action && _session) {
3552 if (_session->undo_depth() == 0) {
3553 label = S_("Command|Undo");
3555 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3557 undo_action->property_label() = label;
3560 if (redo_action && _session) {
3561 if (_session->redo_depth() == 0) {
3563 redo_action->set_sensitive (false);
3565 label = string_compose(_("Redo (%1)"), _session->next_redo());
3566 redo_action->set_sensitive (true);
3568 redo_action->property_label() = label;
3573 Editor::duplicate_range (bool with_dialog)
3577 RegionSelection rs = get_regions_from_selection_and_entered ();
3579 if ( selection->time.length() == 0 && rs.empty()) {
3585 ArdourDialog win (_("Duplicate"));
3586 Label label (_("Number of duplications:"));
3587 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3588 SpinButton spinner (adjustment, 0.0, 1);
3591 win.get_vbox()->set_spacing (12);
3592 win.get_vbox()->pack_start (hbox);
3593 hbox.set_border_width (6);
3594 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3596 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3597 place, visually. so do this by hand.
3600 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3601 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3602 spinner.grab_focus();
3608 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3609 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3610 win.set_default_response (RESPONSE_ACCEPT);
3612 spinner.grab_focus ();
3614 switch (win.run ()) {
3615 case RESPONSE_ACCEPT:
3621 times = adjustment.get_value();
3624 if ((current_mouse_mode() == Editing::MouseRange)) {
3625 if (selection->time.length()) {
3626 duplicate_selection (times);
3628 } else if (get_smart_mode()) {
3629 if (selection->time.length()) {
3630 duplicate_selection (times);
3632 duplicate_some_regions (rs, times);
3634 duplicate_some_regions (rs, times);
3639 Editor::set_edit_mode (EditMode m)
3641 Config->set_edit_mode (m);
3645 Editor::cycle_edit_mode ()
3647 switch (Config->get_edit_mode()) {
3649 Config->set_edit_mode (Ripple);
3653 Config->set_edit_mode (Lock);
3656 Config->set_edit_mode (Slide);
3662 Editor::edit_mode_selection_done ( EditMode m )
3664 Config->set_edit_mode ( m );
3668 Editor::snap_type_selection_done (SnapType snaptype)
3670 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3672 ract->set_active ();
3677 Editor::snap_mode_selection_done (SnapMode mode)
3679 RefPtr<RadioAction> ract = snap_mode_action (mode);
3682 ract->set_active (true);
3687 Editor::cycle_edit_point (bool with_marker)
3689 if(Profile->get_mixbus())
3690 with_marker = false;
3692 switch (_edit_point) {
3694 set_edit_point_preference (EditAtPlayhead);
3696 case EditAtPlayhead:
3698 set_edit_point_preference (EditAtSelectedMarker);
3700 set_edit_point_preference (EditAtMouse);
3703 case EditAtSelectedMarker:
3704 set_edit_point_preference (EditAtMouse);
3710 Editor::edit_point_selection_done (EditPoint ep)
3712 set_edit_point_preference ( ep );
3716 Editor::build_zoom_focus_menu ()
3718 using namespace Menu_Helpers;
3720 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3721 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3722 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3723 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3724 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3725 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3727 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3731 Editor::zoom_focus_selection_done ( ZoomFocus f )
3733 RefPtr<RadioAction> ract = zoom_focus_action (f);
3735 ract->set_active ();
3740 Editor::build_track_count_menu ()
3742 using namespace Menu_Helpers;
3744 if (!Profile->get_mixbus()) {
3745 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3746 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3747 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3748 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3749 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3750 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3751 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3752 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3753 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3754 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3755 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3756 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3757 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3759 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3760 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3761 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3762 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3763 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3764 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3765 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3766 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3767 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3768 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3770 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3771 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3772 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3773 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3774 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3775 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3776 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3777 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3778 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3779 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3780 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3785 Editor::set_zoom_preset (int64_t ms)
3788 temporal_zoom_session();
3792 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3793 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3797 Editor::set_visible_track_count (int32_t n)
3799 _visible_track_count = n;
3801 /* if the canvas hasn't really been allocated any size yet, just
3802 record the desired number of visible tracks and return. when canvas
3803 allocation happens, we will get called again and then we can do the
3807 if (_visible_canvas_height <= 1) {
3813 DisplaySuspender ds;
3815 if (_visible_track_count > 0) {
3816 h = trackviews_height() / _visible_track_count;
3817 std::ostringstream s;
3818 s << _visible_track_count;
3820 } else if (_visible_track_count == 0) {
3822 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3823 if ((*i)->marked_for_display()) {
3827 h = trackviews_height() / n;
3830 /* negative value means that the visible track count has
3831 been overridden by explicit track height changes.
3833 visible_tracks_selector.set_text (X_("*"));
3837 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3838 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3841 if (str != visible_tracks_selector.get_text()) {
3842 visible_tracks_selector.set_text (str);
3847 Editor::override_visible_track_count ()
3849 _visible_track_count = -1;
3850 visible_tracks_selector.set_text ( _("*") );
3854 Editor::edit_controls_button_release (GdkEventButton* ev)
3856 if (Keyboard::is_context_menu_event (ev)) {
3857 ARDOUR_UI::instance()->add_route ();
3858 } else if (ev->button == 1) {
3859 selection->clear_tracks ();
3866 Editor::mouse_select_button_release (GdkEventButton* ev)
3868 /* this handles just right-clicks */
3870 if (ev->button != 3) {
3878 Editor::set_zoom_focus (ZoomFocus f)
3880 string str = zoom_focus_strings[(int)f];
3882 if (str != zoom_focus_selector.get_text()) {
3883 zoom_focus_selector.set_text (str);
3886 if (zoom_focus != f) {
3893 Editor::cycle_zoom_focus ()
3895 switch (zoom_focus) {
3897 set_zoom_focus (ZoomFocusRight);
3899 case ZoomFocusRight:
3900 set_zoom_focus (ZoomFocusCenter);
3902 case ZoomFocusCenter:
3903 set_zoom_focus (ZoomFocusPlayhead);
3905 case ZoomFocusPlayhead:
3906 set_zoom_focus (ZoomFocusMouse);
3908 case ZoomFocusMouse:
3909 set_zoom_focus (ZoomFocusEdit);
3912 set_zoom_focus (ZoomFocusLeft);
3918 Editor::set_show_measures (bool yn)
3920 if (_show_measures != yn) {
3923 if ((_show_measures = yn) == true) {
3925 tempo_lines->show();
3928 std::vector<TempoMap::BBTPoint> grid;
3929 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
3930 draw_measures (grid);
3938 Editor::toggle_follow_playhead ()
3940 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3942 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3943 set_follow_playhead (tact->get_active());
3947 /** @param yn true to follow playhead, otherwise false.
3948 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3951 Editor::set_follow_playhead (bool yn, bool catch_up)
3953 if (_follow_playhead != yn) {
3954 if ((_follow_playhead = yn) == true && catch_up) {
3956 reset_x_origin_to_follow_playhead ();
3963 Editor::toggle_stationary_playhead ()
3965 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3967 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3968 set_stationary_playhead (tact->get_active());
3973 Editor::set_stationary_playhead (bool yn)
3975 if (_stationary_playhead != yn) {
3976 if ((_stationary_playhead = yn) == true) {
3978 // FIXME need a 3.0 equivalent of this 2.X call
3979 // update_current_screen ();
3986 Editor::playlist_selector () const
3988 return *_playlist_selector;
3992 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
3994 if (paste_count == 0) {
3995 /* don't bother calculating an offset that will be zero anyway */
3999 /* calculate basic unsnapped multi-paste offset */
4000 framecnt_t offset = paste_count * duration;
4002 /* snap offset so pos + offset is aligned to the grid */
4003 framepos_t offset_pos = pos + offset;
4004 snap_to(offset_pos, RoundUpMaybe);
4005 offset = offset_pos - pos;
4011 Editor::get_grid_beat_divisions(framepos_t position)
4013 switch (_snap_type) {
4014 case SnapToBeatDiv128: return 128;
4015 case SnapToBeatDiv64: return 64;
4016 case SnapToBeatDiv32: return 32;
4017 case SnapToBeatDiv28: return 28;
4018 case SnapToBeatDiv24: return 24;
4019 case SnapToBeatDiv20: return 20;
4020 case SnapToBeatDiv16: return 16;
4021 case SnapToBeatDiv14: return 14;
4022 case SnapToBeatDiv12: return 12;
4023 case SnapToBeatDiv10: return 10;
4024 case SnapToBeatDiv8: return 8;
4025 case SnapToBeatDiv7: return 7;
4026 case SnapToBeatDiv6: return 6;
4027 case SnapToBeatDiv5: return 5;
4028 case SnapToBeatDiv4: return 4;
4029 case SnapToBeatDiv3: return 3;
4030 case SnapToBeatDiv2: return 2;
4036 /** returns the current musical grid divisiions using the supplied modifier mask from a GtkEvent.
4037 if the grid is non-musical, returns 0.
4038 if the grid is snapped to bars, returns -1.
4039 @param event_state the current keyboard modifier mask.
4042 Editor::get_grid_music_divisions (uint32_t event_state)
4044 if (snap_mode() == Editing::SnapOff && !ArdourKeyboard::indicates_snap (event_state)) {
4048 if (snap_mode() != Editing::SnapOff && ArdourKeyboard::indicates_snap (event_state)) {
4052 switch (_snap_type) {
4053 case SnapToBeatDiv128: return 128;
4054 case SnapToBeatDiv64: return 64;
4055 case SnapToBeatDiv32: return 32;
4056 case SnapToBeatDiv28: return 28;
4057 case SnapToBeatDiv24: return 24;
4058 case SnapToBeatDiv20: return 20;
4059 case SnapToBeatDiv16: return 16;
4060 case SnapToBeatDiv14: return 14;
4061 case SnapToBeatDiv12: return 12;
4062 case SnapToBeatDiv10: return 10;
4063 case SnapToBeatDiv8: return 8;
4064 case SnapToBeatDiv7: return 7;
4065 case SnapToBeatDiv6: return 6;
4066 case SnapToBeatDiv5: return 5;
4067 case SnapToBeatDiv4: return 4;
4068 case SnapToBeatDiv3: return 3;
4069 case SnapToBeatDiv2: return 2;
4070 case SnapToBeat: return 1;
4071 case SnapToBar : return -1;
4078 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4082 const unsigned divisions = get_grid_beat_divisions(position);
4084 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4087 switch (_snap_type) {
4089 return Evoral::Beats(4.0 / _session->tempo_map().meter_at_frame (position).note_divisor());
4092 const Meter& m = _session->tempo_map().meter_at_frame (position);
4093 return Evoral::Beats((4.0 * m.divisions_per_bar()) / m.note_divisor());
4101 return Evoral::Beats();
4105 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4109 ret = nudge_clock->current_duration (pos);
4110 next = ret + 1; /* XXXX fix me */
4116 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4118 ArdourDialog dialog (_("Playlist Deletion"));
4119 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4120 "If it is kept, its audio files will not be cleaned.\n"
4121 "If it is deleted, audio files used by it alone will be cleaned."),
4124 dialog.set_position (WIN_POS_CENTER);
4125 dialog.get_vbox()->pack_start (label);
4129 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4130 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4131 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4132 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4133 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4135 // by default gtk uses the left most button
4136 keep->grab_focus ();
4138 switch (dialog.run ()) {
4140 /* keep this and all remaining ones */
4145 /* delete this and all others */
4149 case RESPONSE_ACCEPT:
4150 /* delete the playlist */
4154 case RESPONSE_REJECT:
4155 /* keep the playlist */
4167 Editor::audio_region_selection_covers (framepos_t where)
4169 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4170 if ((*a)->region()->covers (where)) {
4179 Editor::prepare_for_cleanup ()
4181 cut_buffer->clear_regions ();
4182 cut_buffer->clear_playlists ();
4184 selection->clear_regions ();
4185 selection->clear_playlists ();
4187 _regions->suspend_redisplay ();
4191 Editor::finish_cleanup ()
4193 _regions->resume_redisplay ();
4197 Editor::transport_loop_location()
4200 return _session->locations()->auto_loop_location();
4207 Editor::transport_punch_location()
4210 return _session->locations()->auto_punch_location();
4217 Editor::control_layout_scroll (GdkEventScroll* ev)
4219 /* Just forward to the normal canvas scroll method. The coordinate
4220 systems are different but since the canvas is always larger than the
4221 track headers, and aligned with the trackview area, this will work.
4223 In the not too distant future this layout is going away anyway and
4224 headers will be on the canvas.
4226 return canvas_scroll_event (ev, false);
4230 Editor::session_state_saved (string)
4233 _snapshots->redisplay ();
4237 Editor::maximise_editing_space ()
4243 Gtk::Window* toplevel = current_toplevel();
4246 toplevel->fullscreen ();
4252 Editor::restore_editing_space ()
4258 Gtk::Window* toplevel = current_toplevel();
4261 toplevel->unfullscreen();
4267 * Make new playlists for a given track and also any others that belong
4268 * to the same active route group with the `select' property.
4273 Editor::new_playlists (TimeAxisView* v)
4275 begin_reversible_command (_("new playlists"));
4276 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4277 _session->playlists->get (playlists);
4278 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
4279 commit_reversible_command ();
4283 * Use a copy of the current playlist for a given track and also any others that belong
4284 * to the same active route group with the `select' property.
4289 Editor::copy_playlists (TimeAxisView* v)
4291 begin_reversible_command (_("copy playlists"));
4292 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4293 _session->playlists->get (playlists);
4294 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
4295 commit_reversible_command ();
4298 /** Clear the current playlist for a given track and also any others that belong
4299 * to the same active route group with the `select' property.
4304 Editor::clear_playlists (TimeAxisView* v)
4306 begin_reversible_command (_("clear playlists"));
4307 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4308 _session->playlists->get (playlists);
4309 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::group_select.property_id);
4310 commit_reversible_command ();
4314 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4316 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4320 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4322 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4326 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4328 atv.clear_playlist ();
4332 Editor::get_y_origin () const
4334 return vertical_adjustment.get_value ();
4337 /** Queue up a change to the viewport x origin.
4338 * @param frame New x origin.
4341 Editor::reset_x_origin (framepos_t frame)
4343 pending_visual_change.add (VisualChange::TimeOrigin);
4344 pending_visual_change.time_origin = frame;
4345 ensure_visual_change_idle_handler ();
4349 Editor::reset_y_origin (double y)
4351 pending_visual_change.add (VisualChange::YOrigin);
4352 pending_visual_change.y_origin = y;
4353 ensure_visual_change_idle_handler ();
4357 Editor::reset_zoom (framecnt_t spp)
4359 if (spp == samples_per_pixel) {
4363 pending_visual_change.add (VisualChange::ZoomLevel);
4364 pending_visual_change.samples_per_pixel = spp;
4365 ensure_visual_change_idle_handler ();
4369 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4371 reset_x_origin (frame);
4374 if (!no_save_visual) {
4375 undo_visual_stack.push_back (current_visual_state(false));
4379 Editor::VisualState::VisualState (bool with_tracks)
4380 : gui_state (with_tracks ? new GUIObjectState : 0)
4384 Editor::VisualState::~VisualState ()
4389 Editor::VisualState*
4390 Editor::current_visual_state (bool with_tracks)
4392 VisualState* vs = new VisualState (with_tracks);
4393 vs->y_position = vertical_adjustment.get_value();
4394 vs->samples_per_pixel = samples_per_pixel;
4395 vs->leftmost_frame = leftmost_frame;
4396 vs->zoom_focus = zoom_focus;
4399 vs->gui_state->set_state (ARDOUR_UI::instance()->gui_object_state->get_state());
4406 Editor::undo_visual_state ()
4408 if (undo_visual_stack.empty()) {
4412 VisualState* vs = undo_visual_stack.back();
4413 undo_visual_stack.pop_back();
4416 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4419 use_visual_state (*vs);
4424 Editor::redo_visual_state ()
4426 if (redo_visual_stack.empty()) {
4430 VisualState* vs = redo_visual_stack.back();
4431 redo_visual_stack.pop_back();
4433 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4434 // why do we check here?
4435 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4438 use_visual_state (*vs);
4443 Editor::swap_visual_state ()
4445 if (undo_visual_stack.empty()) {
4446 redo_visual_state ();
4448 undo_visual_state ();
4453 Editor::use_visual_state (VisualState& vs)
4455 PBD::Unwinder<bool> nsv (no_save_visual, true);
4456 DisplaySuspender ds;
4458 vertical_adjustment.set_value (vs.y_position);
4460 set_zoom_focus (vs.zoom_focus);
4461 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4464 ARDOUR_UI::instance()->gui_object_state->set_state (vs.gui_state->get_state());
4466 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4467 (*i)->clear_property_cache();
4468 (*i)->reset_visual_state ();
4472 _routes->update_visibility ();
4475 /** This is the core function that controls the zoom level of the canvas. It is called
4476 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4477 * @param spp new number of samples per pixel
4480 Editor::set_samples_per_pixel (framecnt_t spp)
4486 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4487 const framecnt_t lots_of_pixels = 4000;
4489 /* if the zoom level is greater than what you'd get trying to display 3
4490 * days of audio on a really big screen, then it's too big.
4493 if (spp * lots_of_pixels > three_days) {
4497 samples_per_pixel = spp;
4500 tempo_lines->tempo_map_changed();
4503 bool const showing_time_selection = selection->time.length() > 0;
4505 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4506 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4507 (*i)->reshow_selection (selection->time);
4511 ZoomChanged (); /* EMIT_SIGNAL */
4513 ArdourCanvas::GtkCanvasViewport* c;
4515 c = get_track_canvas();
4517 c->canvas()->zoomed ();
4520 if (playhead_cursor) {
4521 playhead_cursor->set_position (playhead_cursor->current_frame ());
4524 refresh_location_display();
4525 _summary->set_overlays_dirty ();
4527 update_marker_labels ();
4533 Editor::queue_visual_videotimeline_update ()
4536 * pending_visual_change.add (VisualChange::VideoTimeline);
4537 * or maybe even more specific: which videotimeline-image
4538 * currently it calls update_video_timeline() to update
4539 * _all outdated_ images on the video-timeline.
4540 * see 'exposeimg()' in video_image_frame.cc
4542 ensure_visual_change_idle_handler ();
4546 Editor::ensure_visual_change_idle_handler ()
4548 if (pending_visual_change.idle_handler_id < 0) {
4549 // see comment in add_to_idle_resize above.
4550 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4551 pending_visual_change.being_handled = false;
4556 Editor::_idle_visual_changer (void* arg)
4558 return static_cast<Editor*>(arg)->idle_visual_changer ();
4562 Editor::idle_visual_changer ()
4564 /* set_horizontal_position() below (and maybe other calls) call
4565 gtk_main_iteration(), so it's possible that a signal will be handled
4566 half-way through this method. If this signal wants an
4567 idle_visual_changer we must schedule another one after this one, so
4568 mark the idle_handler_id as -1 here to allow that. Also make a note
4569 that we are doing the visual change, so that changes in response to
4570 super-rapid-screen-update can be dropped if we are still processing
4574 pending_visual_change.idle_handler_id = -1;
4575 pending_visual_change.being_handled = true;
4577 VisualChange vc = pending_visual_change;
4579 pending_visual_change.pending = (VisualChange::Type) 0;
4581 visual_changer (vc);
4583 pending_visual_change.being_handled = false;
4585 return 0; /* this is always a one-shot call */
4589 Editor::visual_changer (const VisualChange& vc)
4591 double const last_time_origin = horizontal_position ();
4593 if (vc.pending & VisualChange::ZoomLevel) {
4594 set_samples_per_pixel (vc.samples_per_pixel);
4596 compute_fixed_ruler_scale ();
4598 std::vector<TempoMap::BBTPoint> grid;
4599 compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4600 compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4601 update_tempo_based_rulers (grid);
4603 update_video_timeline();
4606 if (vc.pending & VisualChange::TimeOrigin) {
4607 set_horizontal_position (vc.time_origin / samples_per_pixel);
4610 if (vc.pending & VisualChange::YOrigin) {
4611 vertical_adjustment.set_value (vc.y_origin);
4614 if (last_time_origin == horizontal_position ()) {
4615 /* changed signal not emitted */
4616 update_fixed_rulers ();
4617 redisplay_tempo (true);
4620 if (!(vc.pending & VisualChange::ZoomLevel)) {
4621 update_video_timeline();
4624 _summary->set_overlays_dirty ();
4627 struct EditorOrderTimeAxisSorter {
4628 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4629 return a->order () < b->order ();
4634 Editor::sort_track_selection (TrackViewList& sel)
4636 EditorOrderTimeAxisSorter cmp;
4641 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4644 framepos_t where = 0;
4645 EditPoint ep = _edit_point;
4647 if (Profile->get_mixbus())
4648 if (ep == EditAtSelectedMarker)
4649 ep = EditAtPlayhead;
4651 if (from_outside_canvas && (ep == EditAtMouse)) {
4652 ep = EditAtPlayhead;
4653 } else if (from_context_menu && (ep == EditAtMouse)) {
4654 return canvas_event_sample (&context_click_event, 0, 0);
4657 if (entered_marker) {
4658 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4659 return entered_marker->position();
4662 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4663 ep = EditAtSelectedMarker;
4666 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4667 ep = EditAtPlayhead;
4671 case EditAtPlayhead:
4672 if (_dragging_playhead) {
4673 where = *_control_scroll_target;
4675 where = _session->audible_frame();
4677 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4680 case EditAtSelectedMarker:
4681 if (!selection->markers.empty()) {
4683 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4686 where = loc->start();
4690 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4698 if (!mouse_frame (where, ignored)) {
4699 /* XXX not right but what can we do ? */
4703 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4711 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4713 if (!_session) return;
4715 begin_reversible_command (cmd);
4719 if ((tll = transport_loop_location()) == 0) {
4720 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4721 XMLNode &before = _session->locations()->get_state();
4722 _session->locations()->add (loc, true);
4723 _session->set_auto_loop_location (loc);
4724 XMLNode &after = _session->locations()->get_state();
4725 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4727 XMLNode &before = tll->get_state();
4728 tll->set_hidden (false, this);
4729 tll->set (start, end);
4730 XMLNode &after = tll->get_state();
4731 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4734 commit_reversible_command ();
4738 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4740 if (!_session) return;
4742 begin_reversible_command (cmd);
4746 if ((tpl = transport_punch_location()) == 0) {
4747 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4748 XMLNode &before = _session->locations()->get_state();
4749 _session->locations()->add (loc, true);
4750 _session->set_auto_punch_location (loc);
4751 XMLNode &after = _session->locations()->get_state();
4752 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4754 XMLNode &before = tpl->get_state();
4755 tpl->set_hidden (false, this);
4756 tpl->set (start, end);
4757 XMLNode &after = tpl->get_state();
4758 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4761 commit_reversible_command ();
4764 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4765 * @param rs List to which found regions are added.
4766 * @param where Time to look at.
4767 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4770 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4772 const TrackViewList* tracks;
4775 tracks = &track_views;
4780 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4782 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4785 boost::shared_ptr<Track> tr;
4786 boost::shared_ptr<Playlist> pl;
4788 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4790 boost::shared_ptr<RegionList> regions = pl->regions_at (
4791 (framepos_t) floor ( (double) where * tr->speed()));
4793 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4794 RegionView* rv = rtv->view()->find_view (*i);
4805 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4807 const TrackViewList* tracks;
4810 tracks = &track_views;
4815 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4816 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4818 boost::shared_ptr<Track> tr;
4819 boost::shared_ptr<Playlist> pl;
4821 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4823 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4824 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4826 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4828 RegionView* rv = rtv->view()->find_view (*i);
4839 /** Get regions using the following method:
4841 * Make a region list using:
4842 * (a) any selected regions
4843 * (b) the intersection of any selected tracks and the edit point(*)
4844 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4846 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4848 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4852 Editor::get_regions_from_selection_and_edit_point ()
4854 RegionSelection regions;
4856 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4857 regions.add (entered_regionview);
4859 regions = selection->regions;
4862 if ( regions.empty() ) {
4863 TrackViewList tracks = selection->tracks;
4865 if (!tracks.empty()) {
4866 /* no region selected or entered, but some selected tracks:
4867 * act on all regions on the selected tracks at the edit point
4869 framepos_t const where = get_preferred_edit_position ();
4870 get_regions_at(regions, where, tracks);
4877 /** Get regions using the following method:
4879 * Make a region list using:
4880 * (a) any selected regions
4881 * (b) the intersection of any selected tracks and the edit point(*)
4882 * (c) if neither exists, then whatever region is under the mouse
4884 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4886 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4889 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4891 RegionSelection regions;
4893 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4894 regions.add (entered_regionview);
4896 regions = selection->regions;
4899 if ( regions.empty() ) {
4900 TrackViewList tracks = selection->tracks;
4902 if (!tracks.empty()) {
4903 /* no region selected or entered, but some selected tracks:
4904 * act on all regions on the selected tracks at the edit point
4906 get_regions_at(regions, pos, tracks);
4913 /** Start with regions that are selected, or the entered regionview if none are selected.
4914 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4915 * of the regions that we started with.
4919 Editor::get_regions_from_selection_and_entered () const
4921 RegionSelection regions = selection->regions;
4923 if (regions.empty() && entered_regionview) {
4924 regions.add (entered_regionview);
4931 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4933 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4934 RouteTimeAxisView* rtav;
4936 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4937 boost::shared_ptr<Playlist> pl;
4938 std::vector<boost::shared_ptr<Region> > results;
4939 boost::shared_ptr<Track> tr;
4941 if ((tr = rtav->track()) == 0) {
4946 if ((pl = (tr->playlist())) != 0) {
4947 boost::shared_ptr<Region> r = pl->region_by_id (id);
4949 RegionView* rv = rtav->view()->find_view (r);
4951 regions.push_back (rv);
4960 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4963 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4964 MidiTimeAxisView* mtav;
4966 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4968 mtav->get_per_region_note_selection (selection);
4975 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4977 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4979 RouteTimeAxisView* tatv;
4981 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4983 boost::shared_ptr<Playlist> pl;
4984 vector<boost::shared_ptr<Region> > results;
4986 boost::shared_ptr<Track> tr;
4988 if ((tr = tatv->track()) == 0) {
4993 if ((pl = (tr->playlist())) != 0) {
4994 if (src_comparison) {
4995 pl->get_source_equivalent_regions (region, results);
4997 pl->get_region_list_equivalent_regions (region, results);
5001 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
5002 if ((marv = tatv->view()->find_view (*ir)) != 0) {
5003 regions.push_back (marv);
5012 Editor::show_rhythm_ferret ()
5014 if (rhythm_ferret == 0) {
5015 rhythm_ferret = new RhythmFerret(*this);
5018 rhythm_ferret->set_session (_session);
5019 rhythm_ferret->show ();
5020 rhythm_ferret->present ();
5024 Editor::first_idle ()
5026 MessageDialog* dialog = 0;
5028 if (track_views.size() > 1) {
5029 Timers::TimerSuspender t;
5030 dialog = new MessageDialog (
5031 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5035 ARDOUR_UI::instance()->flush_pending (60);
5038 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5042 // first idle adds route children (automation tracks), so we need to redisplay here
5043 _routes->redisplay ();
5047 if (_session->undo_depth() == 0) {
5048 undo_action->set_sensitive(false);
5050 redo_action->set_sensitive(false);
5051 begin_selection_op_history ();
5057 Editor::_idle_resize (gpointer arg)
5059 return ((Editor*)arg)->idle_resize ();
5063 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5065 if (resize_idle_id < 0) {
5066 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5067 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5068 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5070 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5071 _pending_resize_amount = 0;
5074 /* make a note of the smallest resulting height, so that we can clamp the
5075 lower limit at TimeAxisView::hSmall */
5077 int32_t min_resulting = INT32_MAX;
5079 _pending_resize_amount += h;
5080 _pending_resize_view = view;
5082 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5084 if (selection->tracks.contains (_pending_resize_view)) {
5085 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5086 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5090 if (min_resulting < 0) {
5095 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5096 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5100 /** Handle pending resizing of tracks */
5102 Editor::idle_resize ()
5104 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5106 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5107 selection->tracks.contains (_pending_resize_view)) {
5109 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5110 if (*i != _pending_resize_view) {
5111 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5116 _pending_resize_amount = 0;
5117 _group_tabs->set_dirty ();
5118 resize_idle_id = -1;
5126 ENSURE_GUI_THREAD (*this, &Editor::located);
5129 playhead_cursor->set_position (_session->audible_frame ());
5130 if (_follow_playhead && !_pending_initial_locate) {
5131 reset_x_origin_to_follow_playhead ();
5135 _pending_locate_request = false;
5136 _pending_initial_locate = false;
5140 Editor::region_view_added (RegionView * rv)
5142 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5143 if (rv->region ()->id () == (*pr)) {
5144 selection->add (rv);
5145 selection->regions.pending.erase (pr);
5150 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5152 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5153 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5154 if (rv->region()->id () == (*rnote).first) {
5155 mrv->select_notes ((*rnote).second);
5156 selection->pending_midi_note_selection.erase(rnote);
5162 _summary->set_background_dirty ();
5166 Editor::region_view_removed ()
5168 _summary->set_background_dirty ();
5172 Editor::axis_view_from_stripable (boost::shared_ptr<Stripable> s) const
5174 for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
5175 if ((*j)->stripable() == s) {
5185 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5189 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5190 TimeAxisView* tv = axis_view_from_stripable (*i);
5200 Editor::suspend_route_redisplay ()
5203 _routes->suspend_redisplay();
5208 Editor::resume_route_redisplay ()
5211 _routes->redisplay(); // queue redisplay
5212 _routes->resume_redisplay();
5217 Editor::add_vcas (VCAList& vlist)
5221 for (VCAList::iterator v = vlist.begin(); v != vlist.end(); ++v) {
5222 sl.push_back (boost::dynamic_pointer_cast<Stripable> (*v));
5225 add_stripables (sl);
5229 Editor::add_routes (RouteList& rlist)
5233 for (RouteList::iterator r = rlist.begin(); r != rlist.end(); ++r) {
5237 add_stripables (sl);
5241 Editor::add_stripables (StripableList& sl)
5243 list<TimeAxisView*> new_views;
5244 boost::shared_ptr<VCA> v;
5245 boost::shared_ptr<Route> r;
5246 TrackViewList new_selection;
5247 bool from_scratch = (track_views.size() == 0);
5249 sl.sort (StripablePresentationInfoSorter());
5251 for (StripableList::iterator s = sl.begin(); s != sl.end(); ++s) {
5253 if ((v = boost::dynamic_pointer_cast<VCA> (*s)) != 0) {
5255 VCATimeAxisView* vtv = new VCATimeAxisView (*this, _session, *_track_canvas);
5257 new_views.push_back (vtv);
5259 } else if ((r = boost::dynamic_pointer_cast<Route> (*s)) != 0) {
5261 if (r->is_auditioner() || r->is_monitor()) {
5265 RouteTimeAxisView* rtv;
5266 DataType dt = r->input()->default_type();
5268 if (dt == ARDOUR::DataType::AUDIO) {
5269 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5271 } else if (dt == ARDOUR::DataType::MIDI) {
5272 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5275 throw unknown_type();
5278 new_views.push_back (rtv);
5279 track_views.push_back (rtv);
5280 new_selection.push_back (rtv);
5282 rtv->effective_gain_display ();
5284 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5285 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5289 if (new_views.size() > 0) {
5290 _routes->time_axis_views_added (new_views);
5291 //_summary->routes_added (new_selection); /* XXX requires RouteTimeAxisViewList */
5294 /* note: !new_selection.empty() means that we got some routes rather
5298 if (!from_scratch && !new_selection.empty()) {
5299 selection->tracks.clear();
5300 selection->add (new_selection);
5301 begin_selection_op_history();
5304 if (show_editor_mixer_when_tracks_arrive && !new_selection.empty()) {
5305 show_editor_mixer (true);
5308 editor_list_button.set_sensitive (true);
5312 Editor::timeaxisview_deleted (TimeAxisView *tv)
5314 if (tv == entered_track) {
5318 if (_session && _session->deletion_in_progress()) {
5319 /* the situation is under control */
5323 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5325 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5327 _routes->route_removed (tv);
5329 TimeAxisView::Children c = tv->get_child_list ();
5330 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5331 if (entered_track == i->get()) {
5336 /* remove it from the list of track views */
5338 TrackViewList::iterator i;
5340 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5341 i = track_views.erase (i);
5344 /* update whatever the current mixer strip is displaying, if revelant */
5346 boost::shared_ptr<Route> route;
5349 route = rtav->route ();
5352 if (current_mixer_strip && current_mixer_strip->route() == route) {
5354 TimeAxisView* next_tv;
5356 if (track_views.empty()) {
5358 } else if (i == track_views.end()) {
5359 next_tv = track_views.front();
5366 set_selected_mixer_strip (*next_tv);
5368 /* make the editor mixer strip go away setting the
5369 * button to inactive (which also unticks the menu option)
5372 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5378 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5380 if (apply_to_selection) {
5381 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5383 TrackSelection::iterator j = i;
5386 hide_track_in_display (*i, false);
5391 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5393 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5394 // this will hide the mixer strip
5395 set_selected_mixer_strip (*tv);
5398 _routes->hide_track_in_display (*tv);
5403 Editor::sync_track_view_list_and_routes ()
5405 track_views = TrackViewList (_routes->views ());
5407 _summary->set_background_dirty();
5408 _group_tabs->set_dirty ();
5410 return false; // do not call again (until needed)
5414 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5416 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5421 /** Find a RouteTimeAxisView by the ID of its route */
5423 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5425 RouteTimeAxisView* v;
5427 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5428 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5429 if(v->route()->id() == id) {
5439 Editor::fit_route_group (RouteGroup *g)
5441 TrackViewList ts = axis_views_from_routes (g->route_list ());
5446 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5448 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5451 _session->cancel_audition ();
5455 if (_session->is_auditioning()) {
5456 _session->cancel_audition ();
5457 if (r == last_audition_region) {
5462 _session->audition_region (r);
5463 last_audition_region = r;
5468 Editor::hide_a_region (boost::shared_ptr<Region> r)
5470 r->set_hidden (true);
5474 Editor::show_a_region (boost::shared_ptr<Region> r)
5476 r->set_hidden (false);
5480 Editor::audition_region_from_region_list ()
5482 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5486 Editor::hide_region_from_region_list ()
5488 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5492 Editor::show_region_in_region_list ()
5494 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5498 Editor::step_edit_status_change (bool yn)
5501 start_step_editing ();
5503 stop_step_editing ();
5508 Editor::start_step_editing ()
5510 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5514 Editor::stop_step_editing ()
5516 step_edit_connection.disconnect ();
5520 Editor::check_step_edit ()
5522 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5523 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5525 mtv->check_step_edit ();
5529 return true; // do it again, till we stop
5533 Editor::scroll_press (Direction dir)
5535 ++_scroll_callbacks;
5537 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5538 /* delay the first auto-repeat */
5544 scroll_backward (1);
5552 scroll_up_one_track ();
5556 scroll_down_one_track ();
5560 /* do hacky auto-repeat */
5561 if (!_scroll_connection.connected ()) {
5563 _scroll_connection = Glib::signal_timeout().connect (
5564 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5567 _scroll_callbacks = 0;
5574 Editor::scroll_release ()
5576 _scroll_connection.disconnect ();
5579 /** Queue a change for the Editor viewport x origin to follow the playhead */
5581 Editor::reset_x_origin_to_follow_playhead ()
5583 framepos_t const frame = playhead_cursor->current_frame ();
5585 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5587 if (_session->transport_speed() < 0) {
5589 if (frame > (current_page_samples() / 2)) {
5590 center_screen (frame-(current_page_samples()/2));
5592 center_screen (current_page_samples()/2);
5599 if (frame < leftmost_frame) {
5601 if (_session->transport_rolling()) {
5602 /* rolling; end up with the playhead at the right of the page */
5603 l = frame - current_page_samples ();
5605 /* not rolling: end up with the playhead 1/4 of the way along the page */
5606 l = frame - current_page_samples() / 4;
5610 if (_session->transport_rolling()) {
5611 /* rolling: end up with the playhead on the left of the page */
5614 /* not rolling: end up with the playhead 3/4 of the way along the page */
5615 l = frame - 3 * current_page_samples() / 4;
5623 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5629 Editor::super_rapid_screen_update ()
5631 if (!_session || !_session->engine().running()) {
5635 /* METERING / MIXER STRIPS */
5637 /* update track meters, if required */
5638 if (contents().is_mapped() && meters_running) {
5639 RouteTimeAxisView* rtv;
5640 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5641 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5642 rtv->fast_update ();
5647 /* and any current mixer strip */
5648 if (current_mixer_strip) {
5649 current_mixer_strip->fast_update ();
5652 /* PLAYHEAD AND VIEWPORT */
5654 framepos_t const frame = _session->audible_frame();
5656 /* There are a few reasons why we might not update the playhead / viewport stuff:
5658 * 1. we don't update things when there's a pending locate request, otherwise
5659 * when the editor requests a locate there is a chance that this method
5660 * will move the playhead before the locate request is processed, causing
5662 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5663 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5666 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5668 last_update_frame = frame;
5670 if (!_dragging_playhead) {
5671 playhead_cursor->set_position (frame);
5674 if (!_stationary_playhead) {
5676 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5677 /* We only do this if we aren't already
5678 handling a visual change (ie if
5679 pending_visual_change.being_handled is
5680 false) so that these requests don't stack
5681 up there are too many of them to handle in
5684 reset_x_origin_to_follow_playhead ();
5689 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5690 framepos_t const frame = playhead_cursor->current_frame ();
5691 double target = ((double)frame - (double)current_page_samples()/2.0);
5692 if (target <= 0.0) {
5695 // compare to EditorCursor::set_position()
5696 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5697 double const new_pos = sample_to_pixel_unrounded (target);
5698 if (rint (new_pos) != rint (old_pos)) {
5699 reset_x_origin (pixel_to_sample (floor (new_pos)));
5710 Editor::session_going_away ()
5712 _have_idled = false;
5714 _session_connections.drop_connections ();
5716 super_rapid_screen_update_connection.disconnect ();
5718 selection->clear ();
5719 cut_buffer->clear ();
5721 clicked_regionview = 0;
5722 clicked_axisview = 0;
5723 clicked_routeview = 0;
5724 entered_regionview = 0;
5726 last_update_frame = 0;
5729 playhead_cursor->hide ();
5731 /* rip everything out of the list displays */
5735 _route_groups->clear ();
5737 /* do this first so that deleting a track doesn't reset cms to null
5738 and thus cause a leak.
5741 if (current_mixer_strip) {
5742 if (current_mixer_strip->get_parent() != 0) {
5743 global_hpacker.remove (*current_mixer_strip);
5745 delete current_mixer_strip;
5746 current_mixer_strip = 0;
5749 /* delete all trackviews */
5751 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5754 track_views.clear ();
5756 nudge_clock->set_session (0);
5758 editor_list_button.set_active(false);
5759 editor_list_button.set_sensitive(false);
5761 /* clear tempo/meter rulers */
5762 remove_metric_marks ();
5764 clear_marker_display ();
5766 stop_step_editing ();
5770 /* get rid of any existing editor mixer strip */
5772 WindowTitle title(Glib::get_application_name());
5773 title += _("Editor");
5775 own_window()->set_title (title.get_string());
5778 SessionHandlePtr::session_going_away ();
5782 Editor::trigger_script (int i)
5784 LuaInstance::instance()-> call_action (i);
5788 Editor::set_script_action_name (int i, const std::string& n)
5790 string const a = string_compose (X_("script-action-%1"), i + 1);
5791 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5794 act->set_label (string_compose (_("Unset #%1"), i + 1));
5795 act->set_tooltip (_("no action bound"));
5796 act->set_sensitive (false);
5799 act->set_tooltip (n);
5800 act->set_sensitive (true);
5802 KeyEditor::UpdateBindings ();
5806 Editor::show_editor_list (bool yn)
5809 _the_notebook.show ();
5811 _the_notebook.hide ();
5816 Editor::change_region_layering_order (bool from_context_menu)
5818 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5820 if (!clicked_routeview) {
5821 if (layering_order_editor) {
5822 layering_order_editor->hide ();
5827 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5833 boost::shared_ptr<Playlist> pl = track->playlist();
5839 if (layering_order_editor == 0) {
5840 layering_order_editor = new RegionLayeringOrderEditor (*this);
5843 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5844 layering_order_editor->maybe_present ();
5848 Editor::update_region_layering_order_editor ()
5850 if (layering_order_editor && layering_order_editor->is_visible ()) {
5851 change_region_layering_order (true);
5856 Editor::setup_fade_images ()
5858 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5859 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5860 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5861 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5862 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5864 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5865 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5866 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5867 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5868 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5870 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5871 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5872 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5873 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5874 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5876 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5877 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5878 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5879 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5880 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5884 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5886 Editor::action_menu_item (std::string const & name)
5888 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5891 return *manage (a->create_menu_item ());
5895 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5897 EventBox* b = manage (new EventBox);
5898 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5899 Label* l = manage (new Label (name));
5903 _the_notebook.append_page (widget, *b);
5907 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5909 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5910 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5913 if (ev->type == GDK_2BUTTON_PRESS) {
5915 /* double-click on a notebook tab shrinks or expands the notebook */
5917 if (_notebook_shrunk) {
5918 if (pre_notebook_shrink_pane_width) {
5919 edit_pane.set_divider (0, *pre_notebook_shrink_pane_width);
5921 _notebook_shrunk = false;
5923 pre_notebook_shrink_pane_width = edit_pane.get_divider();
5925 /* this expands the LHS of the edit pane to cover the notebook
5926 PAGE but leaves the tabs visible.
5928 edit_pane.set_divider (0, edit_pane.get_divider() + page->get_width());
5929 _notebook_shrunk = true;
5937 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5939 using namespace Menu_Helpers;
5941 MenuList& items = _control_point_context_menu.items ();
5944 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5945 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5946 if (!can_remove_control_point (item)) {
5947 items.back().set_sensitive (false);
5950 _control_point_context_menu.popup (event->button.button, event->button.time);
5954 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5956 using namespace Menu_Helpers;
5958 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5963 /* We need to get the selection here and pass it to the operations, since
5964 popping up the menu will cause a region leave event which clears
5965 entered_regionview. */
5967 MidiRegionView& mrv = note->region_view();
5968 const RegionSelection rs = get_regions_from_selection_and_entered ();
5969 const uint32_t sel_size = mrv.selection_size ();
5971 MenuList& items = _note_context_menu.items();
5975 items.push_back(MenuElem(_("Delete"),
5976 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5979 items.push_back(MenuElem(_("Edit..."),
5980 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5981 if (sel_size != 1) {
5982 items.back().set_sensitive (false);
5985 items.push_back(MenuElem(_("Transpose..."),
5986 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5989 items.push_back(MenuElem(_("Legatize"),
5990 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5992 items.back().set_sensitive (false);
5995 items.push_back(MenuElem(_("Quantize..."),
5996 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5998 items.push_back(MenuElem(_("Remove Overlap"),
5999 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
6001 items.back().set_sensitive (false);
6004 items.push_back(MenuElem(_("Transform..."),
6005 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
6007 _note_context_menu.popup (event->button.button, event->button.time);
6011 Editor::zoom_vertical_modifier_released()
6013 _stepping_axis_view = 0;
6017 Editor::ui_parameter_changed (string parameter)
6019 if (parameter == "icon-set") {
6020 while (!_cursor_stack.empty()) {
6021 _cursor_stack.pop_back();
6023 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
6024 _cursor_stack.push_back(_cursors->grabber);
6025 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
6026 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
6028 } else if (parameter == "draggable-playhead") {
6029 if (_verbose_cursor) {
6030 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
6036 Editor::use_own_window (bool and_fill_it)
6038 bool new_window = !own_window();
6040 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
6042 if (win && new_window) {
6043 win->set_name ("EditorWindow");
6045 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
6047 // win->signal_realize().connect (*this, &Editor::on_realize);
6048 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
6049 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
6050 win->set_data ("ardour-bindings", bindings);
6055 DisplaySuspender ds;
6056 contents().show_all ();
6058 /* XXX: this is a bit unfortunate; it would probably
6059 be nicer if we could just call show () above rather
6060 than needing the show_all ()
6063 /* re-hide stuff if necessary */
6064 editor_list_button_toggled ();
6065 parameter_changed ("show-summary");
6066 parameter_changed ("show-group-tabs");
6067 parameter_changed ("show-zoom-tools");
6069 /* now reset all audio_time_axis heights, because widgets might need
6075 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6076 tv = (static_cast<TimeAxisView*>(*i));
6077 tv->reset_height ();
6080 if (current_mixer_strip) {
6081 current_mixer_strip->hide_things ();
6082 current_mixer_strip->parameter_changed ("mixer-element-visibility");