2 Copyright (C) 2000-2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* Note: public Editor methods are documented in public_editor.h */
30 #include "ardour_ui.h"
32 * ardour_ui.h include was moved to the top of the list
33 * due to a conflicting definition of 'Style' between
34 * Apple's MacTypes.h and BarController.
37 #include <boost/none.hpp>
39 #include <sigc++/bind.h>
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
48 #include "pbd/timersub.h"
50 #include <glibmm/miscutils.h>
51 #include <glibmm/uriutils.h>
52 #include <gtkmm/image.h>
53 #include <gdkmm/color.h>
54 #include <gdkmm/bitmap.h>
56 #include <gtkmm/menu.h>
57 #include <gtkmm/menuitem.h>
59 #include "gtkmm2ext/bindings.h"
60 #include "gtkmm2ext/grouped_buttons.h"
61 #include "gtkmm2ext/gtk_ui.h"
62 #include <gtkmm2ext/keyboard.h>
63 #include "gtkmm2ext/utils.h"
64 #include "gtkmm2ext/window_title.h"
65 #include "gtkmm2ext/choice.h"
66 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
68 #include "ardour/analysis_graph.h"
69 #include "ardour/audio_track.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/audioregion.h"
72 #include "ardour/lmath.h"
73 #include "ardour/location.h"
74 #include "ardour/profile.h"
75 #include "ardour/route_group.h"
76 #include "ardour/session_playlists.h"
77 #include "ardour/tempo.h"
78 #include "ardour/utils.h"
79 #include "ardour/vca_manager.h"
81 #include "canvas/debug.h"
82 #include "canvas/text.h"
84 #include "control_protocol/control_protocol.h"
87 #include "analysis_window.h"
88 #include "audio_clock.h"
89 #include "audio_region_view.h"
90 #include "audio_streamview.h"
91 #include "audio_time_axis.h"
92 #include "automation_time_axis.h"
93 #include "bundle_manager.h"
94 #include "crossfade_edit.h"
98 #include "editor_cursors.h"
99 #include "editor_drag.h"
100 #include "editor_group_tabs.h"
101 #include "editor_locations.h"
102 #include "editor_regions.h"
103 #include "editor_route_groups.h"
104 #include "editor_routes.h"
105 #include "editor_snapshots.h"
106 #include "editor_summary.h"
107 #include "export_report.h"
108 #include "global_port_matrix.h"
109 #include "gui_object.h"
110 #include "gui_thread.h"
111 #include "keyboard.h"
112 #include "keyeditor.h"
113 #include "luainstance.h"
115 #include "midi_region_view.h"
116 #include "midi_time_axis.h"
117 #include "mixer_strip.h"
118 #include "mixer_ui.h"
119 #include "mouse_cursors.h"
120 #include "note_base.h"
121 #include "playlist_selector.h"
122 #include "public_editor.h"
123 #include "quantize_dialog.h"
124 #include "region_layering_order_editor.h"
125 #include "rgb_macros.h"
126 #include "rhythm_ferret.h"
127 #include "selection.h"
128 #include "simple_progress_dialog.h"
130 #include "tempo_lines.h"
131 #include "time_axis_view.h"
133 #include "tooltips.h"
134 #include "ui_config.h"
136 #include "vca_time_axis.h"
137 #include "verbose_cursor.h"
142 using namespace ARDOUR;
143 using namespace ARDOUR_UI_UTILS;
146 using namespace Glib;
147 using namespace Gtkmm2ext;
148 using namespace Editing;
150 using PBD::internationalize;
152 using Gtkmm2ext::Keyboard;
154 double Editor::timebar_height = 15.0;
156 static const gchar *_snap_type_strings[] = {
190 static const gchar *_snap_mode_strings[] = {
197 static const gchar *_edit_point_strings[] = {
204 static const gchar *_edit_mode_strings[] = {
212 static const gchar *_zoom_focus_strings[] = {
222 #ifdef USE_RUBBERBAND
223 static const gchar *_rb_opt_strings[] = {
226 N_("Balanced multitimbral mixture"),
227 N_("Unpitched percussion with stable notes"),
228 N_("Crisp monophonic instrumental"),
229 N_("Unpitched solo percussion"),
230 N_("Resample without preserving pitch"),
235 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
238 : PublicEditor (global_hpacker)
239 , editor_mixer_strip_width (Wide)
240 , constructed (false)
241 , _playlist_selector (0)
242 , no_save_visual (false)
244 , samples_per_pixel (2048)
245 , zoom_focus (ZoomFocusPlayhead)
246 , mouse_mode (MouseObject)
247 , pre_internal_snap_type (SnapToBeat)
248 , pre_internal_snap_mode (SnapOff)
249 , internal_snap_type (SnapToBeat)
250 , internal_snap_mode (SnapOff)
251 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
252 , _notebook_shrunk (false)
253 , location_marker_color (0)
254 , location_range_color (0)
255 , location_loop_color (0)
256 , location_punch_color (0)
257 , location_cd_marker_color (0)
259 , _show_marker_lines (false)
260 , clicked_axisview (0)
261 , clicked_routeview (0)
262 , clicked_regionview (0)
263 , clicked_selection (0)
264 , clicked_control_point (0)
265 , button_release_can_deselect (true)
266 , _mouse_changed_selection (false)
267 , region_edit_menu_split_item (0)
268 , region_edit_menu_split_multichannel_item (0)
269 , track_region_edit_playlist_menu (0)
270 , track_edit_playlist_submenu (0)
271 , track_selection_edit_playlist_submenu (0)
272 , _popup_region_menu_item (0)
274 , _track_canvas_viewport (0)
275 , within_track_canvas (false)
276 , _verbose_cursor (0)
280 , range_marker_group (0)
281 , transport_marker_group (0)
282 , cd_marker_group (0)
283 , _time_markers_group (0)
284 , hv_scroll_group (0)
286 , cursor_scroll_group (0)
287 , no_scroll_group (0)
288 , _trackview_group (0)
289 , _drag_motion_group (0)
290 , _canvas_drop_zone (0)
291 , no_ruler_shown_update (false)
292 , ruler_grabbed_widget (0)
294 , minsec_mark_interval (0)
295 , minsec_mark_modulo (0)
297 , timecode_mark_modulo (0)
298 , timecode_nmarks (0)
299 , _samples_ruler_interval (0)
302 , bbt_bar_helper_on (0)
303 , bbt_accent_modulo (0)
308 , visible_timebars (0)
309 , editor_ruler_menu (0)
313 , range_marker_bar (0)
314 , transport_marker_bar (0)
316 , minsec_label (_("Mins:Secs"))
317 , bbt_label (_("Bars:Beats"))
318 , timecode_label (_("Timecode"))
319 , samples_label (_("Samples"))
320 , tempo_label (_("Tempo"))
321 , meter_label (_("Meter"))
322 , mark_label (_("Location Markers"))
323 , range_mark_label (_("Range Markers"))
324 , transport_mark_label (_("Loop/Punch Ranges"))
325 , cd_mark_label (_("CD Markers"))
326 , videotl_label (_("Video Timeline"))
328 , playhead_cursor (0)
329 , edit_packer (4, 4, true)
330 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
331 , horizontal_adjustment (0.0, 0.0, 1e16)
332 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
333 , controls_layout (unused_adjustment, vertical_adjustment)
334 , _scroll_callbacks (0)
335 , _visible_canvas_width (0)
336 , _visible_canvas_height (0)
337 , _full_canvas_height (0)
338 , edit_controls_left_menu (0)
339 , edit_controls_right_menu (0)
340 , last_update_frame (0)
341 , cut_buffer_start (0)
342 , cut_buffer_length (0)
343 , button_bindings (0)
347 , current_interthread_info (0)
348 , analysis_window (0)
349 , select_new_marker (false)
351 , scrubbing_direction (0)
352 , scrub_reversals (0)
353 , scrub_reverse_distance (0)
354 , have_pending_keyboard_selection (false)
355 , pending_keyboard_selection_start (0)
356 , _snap_type (SnapToBeat)
357 , _snap_mode (SnapOff)
358 , snap_threshold (5.0)
359 , ignore_gui_changes (false)
360 , _drags (new DragManager (this))
362 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
363 , _dragging_playhead (false)
364 , _dragging_edit_point (false)
365 , _show_measures (true)
366 , _follow_playhead (true)
367 , _stationary_playhead (false)
370 , global_rect_group (0)
371 , time_line_group (0)
372 , tempo_marker_menu (0)
373 , meter_marker_menu (0)
375 , range_marker_menu (0)
376 , transport_marker_menu (0)
377 , new_transport_marker_menu (0)
379 , marker_menu_item (0)
380 , bbt_beat_subdivision (4)
381 , _visible_track_count (-1)
382 , toolbar_selection_clock_table (2,3)
383 , automation_mode_button (_("mode"))
384 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
385 , selection (new Selection (this))
386 , cut_buffer (new Selection (this))
387 , _selection_memento (new SelectionMemento())
388 , _all_region_actions_sensitized (false)
389 , _ignore_region_action (false)
390 , _last_region_menu_was_main (false)
391 , _ignore_follow_edits (false)
392 , cd_marker_bar_drag_rect (0)
393 , range_bar_drag_rect (0)
394 , transport_bar_drag_rect (0)
395 , transport_bar_range_rect (0)
396 , transport_bar_preroll_rect (0)
397 , transport_bar_postroll_rect (0)
398 , transport_loop_range_rect (0)
399 , transport_punch_range_rect (0)
400 , transport_punchin_line (0)
401 , transport_punchout_line (0)
402 , transport_preroll_rect (0)
403 , transport_postroll_rect (0)
405 , rubberband_rect (0)
411 , autoscroll_horizontal_allowed (false)
412 , autoscroll_vertical_allowed (false)
414 , autoscroll_widget (0)
415 , show_gain_after_trim (false)
416 , selection_op_cmd_depth (0)
417 , selection_op_history_it (0)
418 , no_save_instant (false)
420 , current_mixer_strip (0)
421 , show_editor_mixer_when_tracks_arrive (false)
422 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
423 , current_stepping_trackview (0)
424 , last_track_height_step_timestamp (0)
426 , entered_regionview (0)
427 , clear_entered_track (false)
428 , _edit_point (EditAtMouse)
429 , meters_running (false)
431 , _have_idled (false)
432 , resize_idle_id (-1)
433 , _pending_resize_amount (0)
434 , _pending_resize_view (0)
435 , _pending_locate_request (false)
436 , _pending_initial_locate (false)
440 , layering_order_editor (0)
441 , _last_cut_copy_source_track (0)
442 , _region_selection_change_updates_region_list (true)
444 , _following_mixer_selection (false)
445 , _control_point_toggled_on_press (false)
446 , _stepping_axis_view (0)
447 , quantize_dialog (0)
448 , _main_menu_disabler (0)
449 , myactions (X_("editor"))
451 /* we are a singleton */
453 PublicEditor::_instance = this;
457 last_event_time.tv_sec = 0;
458 last_event_time.tv_usec = 0;
460 selection_op_history.clear();
463 snap_type_strings = I18N (_snap_type_strings);
464 snap_mode_strings = I18N (_snap_mode_strings);
465 zoom_focus_strings = I18N (_zoom_focus_strings);
466 edit_mode_strings = I18N (_edit_mode_strings);
467 edit_point_strings = I18N (_edit_point_strings);
468 #ifdef USE_RUBBERBAND
469 rb_opt_strings = I18N (_rb_opt_strings);
473 build_edit_mode_menu();
474 build_zoom_focus_menu();
475 build_track_count_menu();
476 build_snap_mode_menu();
477 build_snap_type_menu();
478 build_edit_point_menu();
480 location_marker_color = UIConfiguration::instance().color ("location marker");
481 location_range_color = UIConfiguration::instance().color ("location range");
482 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
483 location_loop_color = UIConfiguration::instance().color ("location loop");
484 location_punch_color = UIConfiguration::instance().color ("location punch");
486 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
488 TimeAxisView::setup_sizes ();
489 ArdourMarker::setup_sizes (timebar_height);
490 TempoCurve::setup_sizes (timebar_height);
492 bbt_label.set_name ("EditorRulerLabel");
493 bbt_label.set_size_request (-1, (int)timebar_height);
494 bbt_label.set_alignment (1.0, 0.5);
495 bbt_label.set_padding (5,0);
497 bbt_label.set_no_show_all();
498 minsec_label.set_name ("EditorRulerLabel");
499 minsec_label.set_size_request (-1, (int)timebar_height);
500 minsec_label.set_alignment (1.0, 0.5);
501 minsec_label.set_padding (5,0);
502 minsec_label.hide ();
503 minsec_label.set_no_show_all();
504 timecode_label.set_name ("EditorRulerLabel");
505 timecode_label.set_size_request (-1, (int)timebar_height);
506 timecode_label.set_alignment (1.0, 0.5);
507 timecode_label.set_padding (5,0);
508 timecode_label.hide ();
509 timecode_label.set_no_show_all();
510 samples_label.set_name ("EditorRulerLabel");
511 samples_label.set_size_request (-1, (int)timebar_height);
512 samples_label.set_alignment (1.0, 0.5);
513 samples_label.set_padding (5,0);
514 samples_label.hide ();
515 samples_label.set_no_show_all();
517 tempo_label.set_name ("EditorRulerLabel");
518 tempo_label.set_size_request (-1, (int)timebar_height);
519 tempo_label.set_alignment (1.0, 0.5);
520 tempo_label.set_padding (5,0);
522 tempo_label.set_no_show_all();
524 meter_label.set_name ("EditorRulerLabel");
525 meter_label.set_size_request (-1, (int)timebar_height);
526 meter_label.set_alignment (1.0, 0.5);
527 meter_label.set_padding (5,0);
529 meter_label.set_no_show_all();
531 if (Profile->get_trx()) {
532 mark_label.set_text (_("Markers"));
534 mark_label.set_name ("EditorRulerLabel");
535 mark_label.set_size_request (-1, (int)timebar_height);
536 mark_label.set_alignment (1.0, 0.5);
537 mark_label.set_padding (5,0);
539 mark_label.set_no_show_all();
541 cd_mark_label.set_name ("EditorRulerLabel");
542 cd_mark_label.set_size_request (-1, (int)timebar_height);
543 cd_mark_label.set_alignment (1.0, 0.5);
544 cd_mark_label.set_padding (5,0);
545 cd_mark_label.hide();
546 cd_mark_label.set_no_show_all();
548 videotl_bar_height = 4;
549 videotl_label.set_name ("EditorRulerLabel");
550 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
551 videotl_label.set_alignment (1.0, 0.5);
552 videotl_label.set_padding (5,0);
553 videotl_label.hide();
554 videotl_label.set_no_show_all();
556 range_mark_label.set_name ("EditorRulerLabel");
557 range_mark_label.set_size_request (-1, (int)timebar_height);
558 range_mark_label.set_alignment (1.0, 0.5);
559 range_mark_label.set_padding (5,0);
560 range_mark_label.hide();
561 range_mark_label.set_no_show_all();
563 transport_mark_label.set_name ("EditorRulerLabel");
564 transport_mark_label.set_size_request (-1, (int)timebar_height);
565 transport_mark_label.set_alignment (1.0, 0.5);
566 transport_mark_label.set_padding (5,0);
567 transport_mark_label.hide();
568 transport_mark_label.set_no_show_all();
570 initialize_canvas ();
572 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
574 _summary = new EditorSummary (this);
576 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
577 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
579 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
581 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
582 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
584 edit_controls_vbox.set_spacing (0);
585 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
586 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
588 HBox* h = manage (new HBox);
589 _group_tabs = new EditorGroupTabs (this);
590 if (!ARDOUR::Profile->get_trx()) {
591 h->pack_start (*_group_tabs, PACK_SHRINK);
593 h->pack_start (edit_controls_vbox);
594 controls_layout.add (*h);
596 controls_layout.set_name ("EditControlsBase");
597 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
598 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
599 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
601 _cursors = new MouseCursors;
602 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
603 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
605 /* Push default cursor to ever-present bottom of cursor stack. */
606 push_canvas_cursor(_cursors->grabber);
608 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
610 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
611 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
612 pad_line_1->set_outline_color (0xFF0000FF);
618 edit_packer.set_col_spacings (0);
619 edit_packer.set_row_spacings (0);
620 edit_packer.set_homogeneous (false);
621 edit_packer.set_border_width (0);
622 edit_packer.set_name ("EditorWindow");
624 time_bars_event_box.add (time_bars_vbox);
625 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
626 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
628 /* labels for the time bars */
629 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
631 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
633 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
635 bottom_hbox.set_border_width (2);
636 bottom_hbox.set_spacing (3);
638 _route_groups = new EditorRouteGroups (this);
639 _routes = new EditorRoutes (this);
640 _regions = new EditorRegions (this);
641 _snapshots = new EditorSnapshots (this);
642 _locations = new EditorLocations (this);
644 /* these are static location signals */
646 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
647 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
648 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
650 add_notebook_page (_("Regions"), _regions->widget ());
651 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
652 add_notebook_page (_("Snapshots"), _snapshots->widget ());
653 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
654 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
656 _the_notebook.set_show_tabs (true);
657 _the_notebook.set_scrollable (true);
658 _the_notebook.popup_disable ();
659 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
660 _the_notebook.show_all ();
662 _notebook_shrunk = false;
665 /* Pick up some settings we need to cache, early */
667 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
670 if (settings && (prop = settings->property ("notebook-shrunk"))) {
671 _notebook_shrunk = string_is_affirmative (prop->value ());
674 editor_summary_pane.add (edit_packer);
676 Button* summary_arrows_left_left = manage (new Button);
677 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
678 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
679 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
681 Button* summary_arrows_left_right = manage (new Button);
682 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
683 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
684 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
686 VBox* summary_arrows_left = manage (new VBox);
687 summary_arrows_left->pack_start (*summary_arrows_left_left);
688 summary_arrows_left->pack_start (*summary_arrows_left_right);
690 Button* summary_arrows_right_up = manage (new Button);
691 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
692 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
693 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
695 Button* summary_arrows_right_down = manage (new Button);
696 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
697 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
698 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
700 VBox* summary_arrows_right = manage (new VBox);
701 summary_arrows_right->pack_start (*summary_arrows_right_up);
702 summary_arrows_right->pack_start (*summary_arrows_right_down);
704 Frame* summary_frame = manage (new Frame);
705 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
707 summary_frame->add (*_summary);
708 summary_frame->show ();
710 _summary_hbox.pack_start (*summary_arrows_left, false, false);
711 _summary_hbox.pack_start (*summary_frame, true, true);
712 _summary_hbox.pack_start (*summary_arrows_right, false, false);
714 if (!ARDOUR::Profile->get_trx()) {
715 editor_summary_pane.add (_summary_hbox);
718 edit_pane.add (editor_summary_pane);
719 if (!ARDOUR::Profile->get_trx()) {
720 edit_pane.add (_the_notebook);
723 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
724 edit_pane.set_child_minsize (_the_notebook, 30); /* rough guess at width of notebook tabs */
725 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
729 if (!settings || ((prop = settings->property ("edit-horizontal-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) {
730 /* initial allocation is 90% to canvas, 10% to notebook */
731 edit_pane.set_divider (0, 0.90);
733 edit_pane.set_divider (0, fract);
736 if (!settings || ((prop = settings->property ("edit-vertical-pane-pos")) == 0) || ((fract = atof (prop->value())) > 1.0)) {
737 /* initial allocation is 90% to canvas, 10% to summary */
738 editor_summary_pane.set_divider (0, 0.90);
741 editor_summary_pane.set_divider (0, fract);
744 top_hbox.pack_start (toolbar_frame);
746 HBox *hbox = manage (new HBox);
747 hbox->pack_start (edit_pane, true, true);
749 global_vpacker.pack_start (top_hbox, false, false);
750 global_vpacker.pack_start (*hbox, true, true);
751 global_hpacker.pack_start (global_vpacker, true, true);
753 /* need to show the "contents" widget so that notebook will show if tab is switched to
756 global_hpacker.show ();
758 /* register actions now so that set_state() can find them and set toggles/checks etc */
765 _playlist_selector = new PlaylistSelector();
766 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
768 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
772 nudge_forward_button.set_name ("nudge button");
773 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
775 nudge_backward_button.set_name ("nudge button");
776 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
778 fade_context_menu.set_name ("ArdourContextMenu");
780 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
782 /* allow external control surfaces/protocols to do various things */
784 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
785 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
786 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
787 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
788 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
789 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
790 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
791 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
792 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
793 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
794 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
795 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
796 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
797 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
799 ControlProtocol::AddStripableToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
800 ControlProtocol::RemoveStripableFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
801 ControlProtocol::SetStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
802 ControlProtocol::ToggleStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
803 ControlProtocol::ClearStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
805 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
809 ARDOUR_UI::instance()->Escape.connect (*this, invalidator (*this), boost::bind (&Editor::escape, this), gui_context());
811 /* problematic: has to return a value and thus cannot be x-thread */
813 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
815 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
816 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
818 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
820 _ignore_region_action = false;
821 _last_region_menu_was_main = false;
822 _popup_region_menu_item = 0;
824 _ignore_follow_edits = false;
826 _show_marker_lines = false;
828 /* Button bindings */
830 button_bindings = new Bindings ("editor-mouse");
832 XMLNode* node = button_settings();
834 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
835 button_bindings->load_operation (**i);
841 /* grab current parameter state */
842 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
843 UIConfiguration::instance().map_parameters (pc);
845 setup_fade_images ();
847 LuaInstance::instance(); // instantiate
848 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &Editor::set_script_action_name));
855 delete button_bindings;
857 delete _route_groups;
858 delete _track_canvas_viewport;
861 delete quantize_dialog;
867 delete _playlist_selector;
869 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
875 Editor::button_settings () const
877 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
878 XMLNode* node = find_named_node (*settings, X_("Buttons"));
881 node = new XMLNode (X_("Buttons"));
888 Editor::get_smart_mode () const
890 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
894 Editor::catch_vanishing_regionview (RegionView *rv)
896 /* note: the selection will take care of the vanishing
897 audioregionview by itself.
900 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
904 if (clicked_regionview == rv) {
905 clicked_regionview = 0;
908 if (entered_regionview == rv) {
909 set_entered_regionview (0);
912 if (!_all_region_actions_sensitized) {
913 sensitize_all_region_actions (true);
918 Editor::set_entered_regionview (RegionView* rv)
920 if (rv == entered_regionview) {
924 if (entered_regionview) {
925 entered_regionview->exited ();
928 entered_regionview = rv;
930 if (entered_regionview != 0) {
931 entered_regionview->entered ();
934 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
935 /* This RegionView entry might have changed what region actions
936 are allowed, so sensitize them all in case a key is pressed.
938 sensitize_all_region_actions (true);
943 Editor::set_entered_track (TimeAxisView* tav)
946 entered_track->exited ();
952 entered_track->entered ();
957 Editor::instant_save ()
959 if (!constructed || !ARDOUR_UI::instance()->session_loaded || no_save_instant) {
964 _session->add_instant_xml(get_state());
966 Config->add_instant_xml(get_state());
971 Editor::control_vertical_zoom_in_all ()
973 tav_zoom_smooth (false, true);
977 Editor::control_vertical_zoom_out_all ()
979 tav_zoom_smooth (true, true);
983 Editor::control_vertical_zoom_in_selected ()
985 tav_zoom_smooth (false, false);
989 Editor::control_vertical_zoom_out_selected ()
991 tav_zoom_smooth (true, false);
995 Editor::control_view (uint32_t view)
997 goto_visual_state (view);
1001 Editor::control_unselect ()
1003 selection->clear_tracks ();
1007 Editor::control_select (PresentationInfo::global_order_t global_order, Selection::Operation op)
1009 /* handles the (static) signal from the ControlProtocol class that
1010 * requests setting the selected track to a given RID
1017 PresentationInfo::Flag select_flags;
1019 if (global_order & ~0xffffffff) {
1020 /* some flags are set, so the PresentationInfo constructor
1023 select_flags = PresentationInfo::Flag (0);
1025 /* no type flags set in the global order ID, so assume caller
1026 * wants to select a Route
1028 select_flags = PresentationInfo::Route;
1031 PresentationInfo pi (global_order, select_flags);
1032 boost::shared_ptr<Stripable> s = _session->get_remote_nth_stripable (pi.group_order(), pi.flags());
1034 /* selected object may not be a Route */
1036 boost::shared_ptr<Route> r = boost::dynamic_pointer_cast<Route> (s);
1042 TimeAxisView* tav = axis_view_from_route (r);
1046 case Selection::Add:
1047 selection->add (tav);
1049 case Selection::Toggle:
1050 selection->toggle (tav);
1052 case Selection::Extend:
1054 case Selection::Set:
1055 selection->set (tav);
1059 selection->clear_tracks ();
1064 Editor::control_step_tracks_up ()
1066 scroll_tracks_up_line ();
1070 Editor::control_step_tracks_down ()
1072 scroll_tracks_down_line ();
1076 Editor::control_scroll (float fraction)
1078 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1084 double step = fraction * current_page_samples();
1087 _control_scroll_target is an optional<T>
1089 it acts like a pointer to an framepos_t, with
1090 a operator conversion to boolean to check
1091 that it has a value could possibly use
1092 playhead_cursor->current_frame to store the
1093 value and a boolean in the class to know
1094 when it's out of date
1097 if (!_control_scroll_target) {
1098 _control_scroll_target = _session->transport_frame();
1099 _dragging_playhead = true;
1102 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1103 *_control_scroll_target = 0;
1104 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1105 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1107 *_control_scroll_target += (framepos_t) trunc (step);
1110 /* move visuals, we'll catch up with it later */
1112 playhead_cursor->set_position (*_control_scroll_target);
1113 UpdateAllTransportClocks (*_control_scroll_target);
1115 if (*_control_scroll_target > (current_page_samples() / 2)) {
1116 /* try to center PH in window */
1117 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1123 Now we do a timeout to actually bring the session to the right place
1124 according to the playhead. This is to avoid reading disk buffers on every
1125 call to control_scroll, which is driven by ScrollTimeline and therefore
1126 probably by a control surface wheel which can generate lots of events.
1128 /* cancel the existing timeout */
1130 control_scroll_connection.disconnect ();
1132 /* add the next timeout */
1134 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1138 Editor::deferred_control_scroll (framepos_t /*target*/)
1140 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1141 // reset for next stream
1142 _control_scroll_target = boost::none;
1143 _dragging_playhead = false;
1148 Editor::access_action (std::string action_group, std::string action_item)
1154 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1157 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1165 Editor::on_realize ()
1169 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1170 start_lock_event_timing ();
1175 Editor::start_lock_event_timing ()
1177 /* check if we should lock the GUI every 30 seconds */
1179 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1183 Editor::generic_event_handler (GdkEvent* ev)
1186 case GDK_BUTTON_PRESS:
1187 case GDK_BUTTON_RELEASE:
1188 case GDK_MOTION_NOTIFY:
1190 case GDK_KEY_RELEASE:
1191 if (contents().is_mapped()) {
1192 gettimeofday (&last_event_time, 0);
1196 case GDK_LEAVE_NOTIFY:
1197 switch (ev->crossing.detail) {
1198 case GDK_NOTIFY_UNKNOWN:
1199 case GDK_NOTIFY_INFERIOR:
1200 case GDK_NOTIFY_ANCESTOR:
1202 case GDK_NOTIFY_VIRTUAL:
1203 case GDK_NOTIFY_NONLINEAR:
1204 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1205 /* leaving window, so reset focus, thus ending any and
1206 all text entry operations.
1208 reset_focus (&contents());
1221 Editor::lock_timeout_callback ()
1223 struct timeval now, delta;
1225 gettimeofday (&now, 0);
1227 timersub (&now, &last_event_time, &delta);
1229 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1231 /* don't call again. Returning false will effectively
1232 disconnect us from the timer callback.
1234 unlock() will call start_lock_event_timing() to get things
1244 Editor::map_position_change (framepos_t frame)
1246 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1248 if (_session == 0) {
1252 if (_follow_playhead) {
1253 center_screen (frame);
1256 playhead_cursor->set_position (frame);
1260 Editor::center_screen (framepos_t frame)
1262 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1264 /* if we're off the page, then scroll.
1267 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1268 center_screen_internal (frame, page);
1273 Editor::center_screen_internal (framepos_t frame, float page)
1278 frame -= (framepos_t) page;
1283 reset_x_origin (frame);
1288 Editor::update_title ()
1290 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1292 if (!own_window()) {
1297 bool dirty = _session->dirty();
1299 string session_name;
1301 if (_session->snap_name() != _session->name()) {
1302 session_name = _session->snap_name();
1304 session_name = _session->name();
1308 session_name = "*" + session_name;
1311 WindowTitle title(session_name);
1312 title += S_("Window|Editor");
1313 title += Glib::get_application_name();
1314 own_window()->set_title (title.get_string());
1316 /* ::session_going_away() will have taken care of it */
1321 Editor::set_session (Session *t)
1323 SessionHandlePtr::set_session (t);
1329 _playlist_selector->set_session (_session);
1330 nudge_clock->set_session (_session);
1331 _summary->set_session (_session);
1332 _group_tabs->set_session (_session);
1333 _route_groups->set_session (_session);
1334 _regions->set_session (_session);
1335 _snapshots->set_session (_session);
1336 _routes->set_session (_session);
1337 _locations->set_session (_session);
1339 if (rhythm_ferret) {
1340 rhythm_ferret->set_session (_session);
1343 if (analysis_window) {
1344 analysis_window->set_session (_session);
1348 sfbrowser->set_session (_session);
1351 compute_fixed_ruler_scale ();
1353 /* Make sure we have auto loop and auto punch ranges */
1355 Location* loc = _session->locations()->auto_loop_location();
1357 loc->set_name (_("Loop"));
1360 loc = _session->locations()->auto_punch_location();
1363 loc->set_name (_("Punch"));
1366 refresh_location_display ();
1368 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1369 the selected Marker; this needs the LocationMarker list to be available.
1371 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1372 set_state (*node, Stateful::loading_state_version);
1374 /* catch up with the playhead */
1376 _session->request_locate (playhead_cursor->current_frame ());
1377 _pending_initial_locate = true;
1381 /* These signals can all be emitted by a non-GUI thread. Therefore the
1382 handlers for them must not attempt to directly interact with the GUI,
1383 but use PBD::Signal<T>::connect() which accepts an event loop
1384 ("context") where the handler will be asked to run.
1387 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1388 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1389 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1390 _session->vca_manager().VCAAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_vcas, this, _1), gui_context());
1391 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1392 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1393 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1394 _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::marker_position_changed, this), gui_context());
1395 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1396 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1397 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1398 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1399 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1400 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1401 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1403 playhead_cursor->show ();
1405 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1406 Config->map_parameters (pc);
1407 _session->config.map_parameters (pc);
1409 restore_ruler_visibility ();
1410 //tempo_map_changed (PropertyChange (0));
1411 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1413 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1414 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1417 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1418 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1421 switch (_snap_type) {
1422 case SnapToRegionStart:
1423 case SnapToRegionEnd:
1424 case SnapToRegionSync:
1425 case SnapToRegionBoundary:
1426 build_region_boundary_cache ();
1433 /* register for undo history */
1434 _session->register_with_memento_command_factory(id(), this);
1435 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1437 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1439 LuaInstance::instance()->set_session(_session);
1441 start_updating_meters ();
1445 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1447 if (a->get_name() == "RegionMenu") {
1448 /* When the main menu's region menu is opened, we setup the actions so that they look right
1449 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1450 so we resensitize all region actions when the entered regionview or the region selection
1451 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1452 happens after the region context menu is opened. So we set a flag here, too.
1456 sensitize_the_right_region_actions ();
1457 _last_region_menu_was_main = true;
1462 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1464 using namespace Menu_Helpers;
1466 void (Editor::*emf)(FadeShape);
1467 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1470 images = &_xfade_in_images;
1471 emf = &Editor::set_fade_in_shape;
1473 images = &_xfade_out_images;
1474 emf = &Editor::set_fade_out_shape;
1479 _("Linear (for highly correlated material)"),
1480 *(*images)[FadeLinear],
1481 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1485 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1489 _("Constant power"),
1490 *(*images)[FadeConstantPower],
1491 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1494 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1499 *(*images)[FadeSymmetric],
1500 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1504 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1509 *(*images)[FadeSlow],
1510 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1513 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1518 *(*images)[FadeFast],
1519 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1522 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1525 /** Pop up a context menu for when the user clicks on a start crossfade */
1527 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1529 using namespace Menu_Helpers;
1530 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1535 MenuList& items (xfade_in_context_menu.items());
1538 if (arv->audio_region()->fade_in_active()) {
1539 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1541 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1544 items.push_back (SeparatorElem());
1545 fill_xfade_menu (items, true);
1547 xfade_in_context_menu.popup (button, time);
1550 /** Pop up a context menu for when the user clicks on an end crossfade */
1552 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1554 using namespace Menu_Helpers;
1555 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1560 MenuList& items (xfade_out_context_menu.items());
1563 if (arv->audio_region()->fade_out_active()) {
1564 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1566 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1569 items.push_back (SeparatorElem());
1570 fill_xfade_menu (items, false);
1572 xfade_out_context_menu.popup (button, time);
1576 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1578 using namespace Menu_Helpers;
1579 Menu* (Editor::*build_menu_function)();
1582 switch (item_type) {
1584 case RegionViewName:
1585 case RegionViewNameHighlight:
1586 case LeftFrameHandle:
1587 case RightFrameHandle:
1588 if (with_selection) {
1589 build_menu_function = &Editor::build_track_selection_context_menu;
1591 build_menu_function = &Editor::build_track_region_context_menu;
1596 if (with_selection) {
1597 build_menu_function = &Editor::build_track_selection_context_menu;
1599 build_menu_function = &Editor::build_track_context_menu;
1604 if (clicked_routeview->track()) {
1605 build_menu_function = &Editor::build_track_context_menu;
1607 build_menu_function = &Editor::build_track_bus_context_menu;
1612 /* probably shouldn't happen but if it does, we don't care */
1616 menu = (this->*build_menu_function)();
1617 menu->set_name ("ArdourContextMenu");
1619 /* now handle specific situations */
1621 switch (item_type) {
1623 case RegionViewName:
1624 case RegionViewNameHighlight:
1625 case LeftFrameHandle:
1626 case RightFrameHandle:
1627 if (!with_selection) {
1628 if (region_edit_menu_split_item) {
1629 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1630 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1632 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1635 if (region_edit_menu_split_multichannel_item) {
1636 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1637 region_edit_menu_split_multichannel_item->set_sensitive (true);
1639 region_edit_menu_split_multichannel_item->set_sensitive (false);
1652 /* probably shouldn't happen but if it does, we don't care */
1656 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1658 /* Bounce to disk */
1660 using namespace Menu_Helpers;
1661 MenuList& edit_items = menu->items();
1663 edit_items.push_back (SeparatorElem());
1665 switch (clicked_routeview->audio_track()->freeze_state()) {
1666 case AudioTrack::NoFreeze:
1667 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1670 case AudioTrack::Frozen:
1671 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1674 case AudioTrack::UnFrozen:
1675 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1681 if (item_type == StreamItem && clicked_routeview) {
1682 clicked_routeview->build_underlay_menu(menu);
1685 /* When the region menu is opened, we setup the actions so that they look right
1688 sensitize_the_right_region_actions ();
1689 _last_region_menu_was_main = false;
1691 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1692 menu->popup (button, time);
1696 Editor::build_track_context_menu ()
1698 using namespace Menu_Helpers;
1700 MenuList& edit_items = track_context_menu.items();
1703 add_dstream_context_items (edit_items);
1704 return &track_context_menu;
1708 Editor::build_track_bus_context_menu ()
1710 using namespace Menu_Helpers;
1712 MenuList& edit_items = track_context_menu.items();
1715 add_bus_context_items (edit_items);
1716 return &track_context_menu;
1720 Editor::build_track_region_context_menu ()
1722 using namespace Menu_Helpers;
1723 MenuList& edit_items = track_region_context_menu.items();
1726 /* we've just cleared the track region context menu, so the menu that these
1727 two items were on will have disappeared; stop them dangling.
1729 region_edit_menu_split_item = 0;
1730 region_edit_menu_split_multichannel_item = 0;
1732 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1735 boost::shared_ptr<Track> tr;
1736 boost::shared_ptr<Playlist> pl;
1738 if ((tr = rtv->track())) {
1739 add_region_context_items (edit_items, tr);
1743 add_dstream_context_items (edit_items);
1745 return &track_region_context_menu;
1749 Editor::loudness_analyze_region_selection ()
1754 Selection& s (PublicEditor::instance ().get_selection ());
1755 RegionSelection ars = s.regions;
1756 ARDOUR::AnalysisGraph ag (_session);
1757 framecnt_t total_work = 0;
1759 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1760 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1764 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1767 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1768 total_work += arv->region ()->length ();
1771 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1773 ag.set_total_frames (total_work);
1774 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1777 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1778 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1782 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1786 ag.analyze_region (ar);
1789 if (!ag.canceled ()) {
1790 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1796 Editor::loudness_analyze_range_selection ()
1801 Selection& s (PublicEditor::instance ().get_selection ());
1802 TimeSelection ts = s.time;
1803 ARDOUR::AnalysisGraph ag (_session);
1804 framecnt_t total_work = 0;
1806 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1807 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1811 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1815 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1816 total_work += j->length ();
1820 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1822 ag.set_total_frames (total_work);
1823 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1826 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1827 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1831 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1835 ag.analyze_range (rui->route (), pl, ts);
1838 if (!ag.canceled ()) {
1839 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1845 Editor::spectral_analyze_region_selection ()
1847 if (analysis_window == 0) {
1848 analysis_window = new AnalysisWindow();
1851 analysis_window->set_session(_session);
1853 analysis_window->show_all();
1856 analysis_window->set_regionmode();
1857 analysis_window->analyze();
1859 analysis_window->present();
1863 Editor::spectral_analyze_range_selection()
1865 if (analysis_window == 0) {
1866 analysis_window = new AnalysisWindow();
1869 analysis_window->set_session(_session);
1871 analysis_window->show_all();
1874 analysis_window->set_rangemode();
1875 analysis_window->analyze();
1877 analysis_window->present();
1881 Editor::build_track_selection_context_menu ()
1883 using namespace Menu_Helpers;
1884 MenuList& edit_items = track_selection_context_menu.items();
1885 edit_items.clear ();
1887 add_selection_context_items (edit_items);
1888 // edit_items.push_back (SeparatorElem());
1889 // add_dstream_context_items (edit_items);
1891 return &track_selection_context_menu;
1895 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1897 using namespace Menu_Helpers;
1899 /* OK, stick the region submenu at the top of the list, and then add
1903 RegionSelection rs = get_regions_from_selection_and_entered ();
1905 string::size_type pos = 0;
1906 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1908 /* we have to hack up the region name because "_" has a special
1909 meaning for menu titles.
1912 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1913 menu_item_name.replace (pos, 1, "__");
1917 if (_popup_region_menu_item == 0) {
1918 _popup_region_menu_item = new MenuItem (menu_item_name);
1919 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1920 _popup_region_menu_item->show ();
1922 _popup_region_menu_item->set_label (menu_item_name);
1925 /* No latering allowed in later is higher layering model */
1926 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1927 if (act && Config->get_layer_model() == LaterHigher) {
1928 act->set_sensitive (false);
1930 act->set_sensitive (true);
1933 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1935 edit_items.push_back (*_popup_region_menu_item);
1936 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1937 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1939 edit_items.push_back (SeparatorElem());
1942 /** Add context menu items relevant to selection ranges.
1943 * @param edit_items List to add the items to.
1946 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1948 using namespace Menu_Helpers;
1950 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1951 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1953 edit_items.push_back (SeparatorElem());
1954 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1956 edit_items.push_back (SeparatorElem());
1957 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1958 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1960 edit_items.push_back (SeparatorElem());
1962 edit_items.push_back (
1964 _("Move Range Start to Previous Region Boundary"),
1965 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1969 edit_items.push_back (
1971 _("Move Range Start to Next Region Boundary"),
1972 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1976 edit_items.push_back (
1978 _("Move Range End to Previous Region Boundary"),
1979 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1983 edit_items.push_back (
1985 _("Move Range End to Next Region Boundary"),
1986 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1990 edit_items.push_back (SeparatorElem());
1991 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1992 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1994 edit_items.push_back (SeparatorElem());
1995 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1997 edit_items.push_back (SeparatorElem());
1998 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1999 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
2000 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
2002 edit_items.push_back (SeparatorElem());
2003 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
2005 edit_items.push_back (SeparatorElem());
2006 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
2007 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
2009 edit_items.push_back (SeparatorElem());
2010 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
2011 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
2012 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
2013 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
2014 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
2015 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
2016 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
2022 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
2024 using namespace Menu_Helpers;
2028 Menu *play_menu = manage (new Menu);
2029 MenuList& play_items = play_menu->items();
2030 play_menu->set_name ("ArdourContextMenu");
2032 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2033 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2034 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2035 play_items.push_back (SeparatorElem());
2036 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2038 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2042 Menu *select_menu = manage (new Menu);
2043 MenuList& select_items = select_menu->items();
2044 select_menu->set_name ("ArdourContextMenu");
2046 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2047 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2048 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2049 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2050 select_items.push_back (SeparatorElem());
2051 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2052 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2053 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2054 select_items.push_back (SeparatorElem());
2055 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2056 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2057 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2058 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2059 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2060 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2061 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2063 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2067 Menu *cutnpaste_menu = manage (new Menu);
2068 MenuList& cutnpaste_items = cutnpaste_menu->items();
2069 cutnpaste_menu->set_name ("ArdourContextMenu");
2071 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2072 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2073 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2075 cutnpaste_items.push_back (SeparatorElem());
2077 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2078 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2080 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2082 /* Adding new material */
2084 edit_items.push_back (SeparatorElem());
2085 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2086 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2090 Menu *nudge_menu = manage (new Menu());
2091 MenuList& nudge_items = nudge_menu->items();
2092 nudge_menu->set_name ("ArdourContextMenu");
2094 edit_items.push_back (SeparatorElem());
2095 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2096 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2097 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2098 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2100 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2104 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2106 using namespace Menu_Helpers;
2110 Menu *play_menu = manage (new Menu);
2111 MenuList& play_items = play_menu->items();
2112 play_menu->set_name ("ArdourContextMenu");
2114 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2115 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2116 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2120 Menu *select_menu = manage (new Menu);
2121 MenuList& select_items = select_menu->items();
2122 select_menu->set_name ("ArdourContextMenu");
2124 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2125 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2126 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2127 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2128 select_items.push_back (SeparatorElem());
2129 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2130 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2131 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2132 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2134 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2138 Menu *cutnpaste_menu = manage (new Menu);
2139 MenuList& cutnpaste_items = cutnpaste_menu->items();
2140 cutnpaste_menu->set_name ("ArdourContextMenu");
2142 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2143 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2144 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2146 Menu *nudge_menu = manage (new Menu());
2147 MenuList& nudge_items = nudge_menu->items();
2148 nudge_menu->set_name ("ArdourContextMenu");
2150 edit_items.push_back (SeparatorElem());
2151 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2152 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2153 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2154 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2156 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2160 Editor::snap_type() const
2166 Editor::snap_musical() const
2168 switch (_snap_type) {
2169 case SnapToBeatDiv128:
2170 case SnapToBeatDiv64:
2171 case SnapToBeatDiv32:
2172 case SnapToBeatDiv28:
2173 case SnapToBeatDiv24:
2174 case SnapToBeatDiv20:
2175 case SnapToBeatDiv16:
2176 case SnapToBeatDiv14:
2177 case SnapToBeatDiv12:
2178 case SnapToBeatDiv10:
2179 case SnapToBeatDiv8:
2180 case SnapToBeatDiv7:
2181 case SnapToBeatDiv6:
2182 case SnapToBeatDiv5:
2183 case SnapToBeatDiv4:
2184 case SnapToBeatDiv3:
2185 case SnapToBeatDiv2:
2197 Editor::snap_mode() const
2203 Editor::set_snap_to (SnapType st)
2205 unsigned int snap_ind = (unsigned int)st;
2207 if (internal_editing()) {
2208 internal_snap_type = st;
2210 pre_internal_snap_type = st;
2215 if (snap_ind > snap_type_strings.size() - 1) {
2217 _snap_type = (SnapType)snap_ind;
2220 string str = snap_type_strings[snap_ind];
2222 if (str != snap_type_selector.get_text()) {
2223 snap_type_selector.set_text (str);
2228 switch (_snap_type) {
2229 case SnapToBeatDiv128:
2230 case SnapToBeatDiv64:
2231 case SnapToBeatDiv32:
2232 case SnapToBeatDiv28:
2233 case SnapToBeatDiv24:
2234 case SnapToBeatDiv20:
2235 case SnapToBeatDiv16:
2236 case SnapToBeatDiv14:
2237 case SnapToBeatDiv12:
2238 case SnapToBeatDiv10:
2239 case SnapToBeatDiv8:
2240 case SnapToBeatDiv7:
2241 case SnapToBeatDiv6:
2242 case SnapToBeatDiv5:
2243 case SnapToBeatDiv4:
2244 case SnapToBeatDiv3:
2245 case SnapToBeatDiv2: {
2246 std::vector<TempoMap::BBTPoint> grid;
2247 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
2248 compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples());
2249 update_tempo_based_rulers (grid);
2253 case SnapToRegionStart:
2254 case SnapToRegionEnd:
2255 case SnapToRegionSync:
2256 case SnapToRegionBoundary:
2257 build_region_boundary_cache ();
2265 redisplay_tempo (false);
2267 SnapChanged (); /* EMIT SIGNAL */
2271 Editor::set_snap_mode (SnapMode mode)
2273 string str = snap_mode_strings[(int)mode];
2275 if (internal_editing()) {
2276 internal_snap_mode = mode;
2278 pre_internal_snap_mode = mode;
2283 if (str != snap_mode_selector.get_text ()) {
2284 snap_mode_selector.set_text (str);
2291 Editor::set_edit_point_preference (EditPoint ep, bool force)
2293 bool changed = (_edit_point != ep);
2296 if (Profile->get_mixbus())
2297 if (ep == EditAtSelectedMarker)
2298 ep = EditAtPlayhead;
2300 string str = edit_point_strings[(int)ep];
2301 if (str != edit_point_selector.get_text ()) {
2302 edit_point_selector.set_text (str);
2305 update_all_enter_cursors();
2307 if (!force && !changed) {
2311 const char* action=NULL;
2313 switch (_edit_point) {
2314 case EditAtPlayhead:
2315 action = "edit-at-playhead";
2317 case EditAtSelectedMarker:
2318 action = "edit-at-marker";
2321 action = "edit-at-mouse";
2325 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2327 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2331 bool in_track_canvas;
2333 if (!mouse_frame (foo, in_track_canvas)) {
2334 in_track_canvas = false;
2337 reset_canvas_action_sensitivity (in_track_canvas);
2343 Editor::set_state (const XMLNode& node, int version)
2345 XMLProperty const * prop;
2347 PBD::Unwinder<bool> nsi (no_save_instant, true);
2349 Tabbable::set_state (node, version);
2351 if (_session && (prop = node.property ("playhead"))) {
2353 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2355 playhead_cursor->set_position (pos);
2357 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2358 playhead_cursor->set_position (0);
2361 playhead_cursor->set_position (0);
2364 if ((prop = node.property ("mixer-width"))) {
2365 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2368 if ((prop = node.property ("zoom-focus"))) {
2369 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2372 if ((prop = node.property ("zoom"))) {
2373 /* older versions of ardour used floating point samples_per_pixel */
2374 double f = PBD::atof (prop->value());
2375 reset_zoom (llrintf (f));
2377 reset_zoom (samples_per_pixel);
2380 if ((prop = node.property ("visible-track-count"))) {
2381 set_visible_track_count (PBD::atoi (prop->value()));
2384 if ((prop = node.property ("snap-to"))) {
2385 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2386 set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
2389 if ((prop = node.property ("snap-mode"))) {
2390 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2391 /* set text of Dropdown. in case _snap_mode == SnapOff (default)
2392 * snap_mode_selection_done() will only mark an already active item as active
2393 * which does not trigger set_text().
2395 set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode));
2398 if ((prop = node.property ("internal-snap-to"))) {
2399 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2402 if ((prop = node.property ("internal-snap-mode"))) {
2403 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2406 if ((prop = node.property ("pre-internal-snap-to"))) {
2407 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2410 if ((prop = node.property ("pre-internal-snap-mode"))) {
2411 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2414 if ((prop = node.property ("mouse-mode"))) {
2415 MouseMode m = str2mousemode(prop->value());
2416 set_mouse_mode (m, true);
2418 set_mouse_mode (MouseObject, true);
2421 if ((prop = node.property ("left-frame")) != 0) {
2423 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2427 reset_x_origin (pos);
2431 if ((prop = node.property ("y-origin")) != 0) {
2432 reset_y_origin (atof (prop->value ()));
2435 if ((prop = node.property ("join-object-range"))) {
2436 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2437 bool yn = string_is_affirmative (prop->value());
2439 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2440 tact->set_active (!yn);
2441 tact->set_active (yn);
2443 set_mouse_mode(mouse_mode, true);
2446 if ((prop = node.property ("edit-point"))) {
2447 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2450 if ((prop = node.property ("show-measures"))) {
2451 bool yn = string_is_affirmative (prop->value());
2452 _show_measures = yn;
2455 if ((prop = node.property ("follow-playhead"))) {
2456 bool yn = string_is_affirmative (prop->value());
2457 set_follow_playhead (yn);
2460 if ((prop = node.property ("stationary-playhead"))) {
2461 bool yn = string_is_affirmative (prop->value());
2462 set_stationary_playhead (yn);
2465 if ((prop = node.property ("region-list-sort-type"))) {
2466 RegionListSortType st;
2467 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2470 if ((prop = node.property ("show-editor-mixer"))) {
2472 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
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 ("show-editor-list"))) {
2486 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2489 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2490 bool yn = string_is_affirmative (prop->value());
2492 /* do it twice to force the change */
2494 tact->set_active (!yn);
2495 tact->set_active (yn);
2498 if ((prop = node.property (X_("editor-list-page")))) {
2499 _the_notebook.set_current_page (atoi (prop->value ()));
2502 if ((prop = node.property (X_("show-marker-lines")))) {
2503 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2505 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2506 bool yn = string_is_affirmative (prop->value ());
2508 tact->set_active (!yn);
2509 tact->set_active (yn);
2512 XMLNodeList children = node.children ();
2513 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2514 selection->set_state (**i, Stateful::current_state_version);
2515 _regions->set_state (**i);
2518 if ((prop = node.property ("maximised"))) {
2519 bool yn = string_is_affirmative (prop->value());
2520 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2522 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2523 bool fs = tact && tact->get_active();
2525 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2529 if ((prop = node.property ("nudge-clock-value"))) {
2531 sscanf (prop->value().c_str(), "%" PRId64, &f);
2532 nudge_clock->set (f);
2534 nudge_clock->set_mode (AudioClock::Timecode);
2535 nudge_clock->set (_session->frame_rate() * 5, true);
2540 * Not all properties may have been in XML, but
2541 * those that are linked to a private variable may need changing
2546 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2548 yn = _show_measures;
2549 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2550 /* do it twice to force the change */
2551 tact->set_active (!yn);
2552 tact->set_active (yn);
2555 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2556 yn = _follow_playhead;
2558 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2559 if (tact->get_active() != yn) {
2560 tact->set_active (yn);
2564 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2565 yn = _stationary_playhead;
2567 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2568 if (tact->get_active() != yn) {
2569 tact->set_active (yn);
2574 return LuaInstance::instance()->set_state(node);
2578 Editor::get_state ()
2580 XMLNode* node = new XMLNode (X_("Editor"));
2584 id().print (buf, sizeof (buf));
2585 node->add_property ("id", buf);
2587 node->add_child_nocopy (Tabbable::get_state());
2589 snprintf(buf,sizeof(buf), "%f", edit_pane.get_divider ());
2590 node->add_property("edit-horizontal-pane-pos", string(buf));
2591 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2592 snprintf(buf,sizeof(buf), "%f", editor_summary_pane.get_divider());
2593 node->add_property("edit-vertical-pane-pos", string(buf));
2595 maybe_add_mixer_strip_width (*node);
2597 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2599 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2600 node->add_property ("zoom", buf);
2601 node->add_property ("snap-to", enum_2_string (_snap_type));
2602 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2603 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2604 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2605 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2606 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2607 node->add_property ("edit-point", enum_2_string (_edit_point));
2608 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2609 node->add_property ("visible-track-count", buf);
2611 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2612 node->add_property ("playhead", buf);
2613 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2614 node->add_property ("left-frame", buf);
2615 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2616 node->add_property ("y-origin", buf);
2618 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2619 node->add_property ("maximised", _maximised ? "yes" : "no");
2620 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2621 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2622 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2623 node->add_property ("mouse-mode", enum2str(mouse_mode));
2624 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2626 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2628 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2629 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2632 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2634 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2635 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2638 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2639 node->add_property (X_("editor-list-page"), buf);
2641 if (button_bindings) {
2642 XMLNode* bb = new XMLNode (X_("Buttons"));
2643 button_bindings->save (*bb);
2644 node->add_child_nocopy (*bb);
2647 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2649 node->add_child_nocopy (selection->get_state ());
2650 node->add_child_nocopy (_regions->get_state ());
2652 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2653 node->add_property ("nudge-clock-value", buf);
2655 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2656 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2661 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2662 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2664 * @return pair: TimeAxisView that y is over, layer index.
2666 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2667 * in stacked or expanded region display mode, otherwise 0.
2669 std::pair<TimeAxisView *, double>
2670 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2672 if (!trackview_relative_offset) {
2673 y -= _trackview_group->canvas_origin().y;
2677 return std::make_pair ( (TimeAxisView *) 0, 0);
2680 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2682 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2689 return std::make_pair ( (TimeAxisView *) 0, 0);
2692 /** Snap a position to the grid, if appropriate, taking into account current
2693 * grid settings and also the state of any snap modifier keys that may be pressed.
2694 * @param start Position to snap.
2695 * @param event Event to get current key modifier information from, or 0.
2698 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2700 if (!_session || !event) {
2704 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2705 if (_snap_mode == SnapOff) {
2706 snap_to_internal (start, direction, for_mark);
2709 if (_snap_mode != SnapOff) {
2710 snap_to_internal (start, direction, for_mark);
2711 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2712 /* SnapOff, but we pressed the snap_delta modifier */
2713 snap_to_internal (start, direction, for_mark);
2719 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2721 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2725 snap_to_internal (start, direction, for_mark, ensure_snap);
2729 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2731 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2732 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2734 switch (_snap_type) {
2735 case SnapToTimecodeFrame:
2736 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2737 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2738 /* start is already on a whole timecode frame, do nothing */
2739 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2740 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2742 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2746 case SnapToTimecodeSeconds:
2747 if (_session->config.get_timecode_offset_negative()) {
2748 start += _session->config.get_timecode_offset ();
2750 start -= _session->config.get_timecode_offset ();
2752 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2753 (start % one_timecode_second == 0)) {
2754 /* start is already on a whole second, do nothing */
2755 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2756 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2758 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2761 if (_session->config.get_timecode_offset_negative()) {
2762 start -= _session->config.get_timecode_offset ();
2764 start += _session->config.get_timecode_offset ();
2768 case SnapToTimecodeMinutes:
2769 if (_session->config.get_timecode_offset_negative()) {
2770 start += _session->config.get_timecode_offset ();
2772 start -= _session->config.get_timecode_offset ();
2774 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2775 (start % one_timecode_minute == 0)) {
2776 /* start is already on a whole minute, do nothing */
2777 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2778 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2780 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2782 if (_session->config.get_timecode_offset_negative()) {
2783 start -= _session->config.get_timecode_offset ();
2785 start += _session->config.get_timecode_offset ();
2789 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2790 abort(); /*NOTREACHED*/
2795 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2797 const framepos_t one_second = _session->frame_rate();
2798 const framepos_t one_minute = _session->frame_rate() * 60;
2799 framepos_t presnap = start;
2803 switch (_snap_type) {
2804 case SnapToTimecodeFrame:
2805 case SnapToTimecodeSeconds:
2806 case SnapToTimecodeMinutes:
2807 return timecode_snap_to_internal (start, direction, for_mark);
2810 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2811 start % (one_second/75) == 0) {
2812 /* start is already on a whole CD frame, do nothing */
2813 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2814 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2816 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2821 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2822 start % one_second == 0) {
2823 /* start is already on a whole second, do nothing */
2824 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2825 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2827 start = (framepos_t) floor ((double) start / one_second) * one_second;
2832 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2833 start % one_minute == 0) {
2834 /* start is already on a whole minute, do nothing */
2835 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2836 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2838 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2843 start = _session->tempo_map().round_to_bar (start, direction);
2847 start = _session->tempo_map().round_to_beat (start, direction);
2850 case SnapToBeatDiv128:
2851 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2853 case SnapToBeatDiv64:
2854 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2856 case SnapToBeatDiv32:
2857 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2859 case SnapToBeatDiv28:
2860 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2862 case SnapToBeatDiv24:
2863 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2865 case SnapToBeatDiv20:
2866 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2868 case SnapToBeatDiv16:
2869 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2871 case SnapToBeatDiv14:
2872 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2874 case SnapToBeatDiv12:
2875 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2877 case SnapToBeatDiv10:
2878 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2880 case SnapToBeatDiv8:
2881 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2883 case SnapToBeatDiv7:
2884 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2886 case SnapToBeatDiv6:
2887 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2889 case SnapToBeatDiv5:
2890 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2892 case SnapToBeatDiv4:
2893 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2895 case SnapToBeatDiv3:
2896 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2898 case SnapToBeatDiv2:
2899 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2907 _session->locations()->marks_either_side (start, before, after);
2909 if (before == max_framepos && after == max_framepos) {
2910 /* No marks to snap to, so just don't snap */
2912 } else if (before == max_framepos) {
2914 } else if (after == max_framepos) {
2916 } else if (before != max_framepos && after != max_framepos) {
2917 /* have before and after */
2918 if ((start - before) < (after - start)) {
2927 case SnapToRegionStart:
2928 case SnapToRegionEnd:
2929 case SnapToRegionSync:
2930 case SnapToRegionBoundary:
2931 if (!region_boundary_cache.empty()) {
2933 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2934 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2936 if (direction > 0) {
2937 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2939 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2942 if (next != region_boundary_cache.begin ()) {
2947 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2948 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2950 if (start > (p + n) / 2) {
2959 switch (_snap_mode) {
2969 if (presnap > start) {
2970 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2974 } else if (presnap < start) {
2975 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2981 /* handled at entry */
2989 Editor::setup_toolbar ()
2991 HBox* mode_box = manage(new HBox);
2992 mode_box->set_border_width (2);
2993 mode_box->set_spacing(2);
2995 HBox* mouse_mode_box = manage (new HBox);
2996 HBox* mouse_mode_hbox = manage (new HBox);
2997 VBox* mouse_mode_vbox = manage (new VBox);
2998 Alignment* mouse_mode_align = manage (new Alignment);
3000 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
3001 mouse_mode_size_group->add_widget (smart_mode_button);
3002 mouse_mode_size_group->add_widget (mouse_move_button);
3003 mouse_mode_size_group->add_widget (mouse_cut_button);
3004 mouse_mode_size_group->add_widget (mouse_select_button);
3005 mouse_mode_size_group->add_widget (mouse_timefx_button);
3006 mouse_mode_size_group->add_widget (mouse_audition_button);
3007 mouse_mode_size_group->add_widget (mouse_draw_button);
3008 mouse_mode_size_group->add_widget (mouse_content_button);
3010 mouse_mode_size_group->add_widget (zoom_in_button);
3011 mouse_mode_size_group->add_widget (zoom_out_button);
3012 mouse_mode_size_group->add_widget (zoom_preset_selector);
3013 mouse_mode_size_group->add_widget (zoom_out_full_button);
3014 mouse_mode_size_group->add_widget (zoom_focus_selector);
3016 mouse_mode_size_group->add_widget (tav_shrink_button);
3017 mouse_mode_size_group->add_widget (tav_expand_button);
3018 mouse_mode_size_group->add_widget (visible_tracks_selector);
3020 mouse_mode_size_group->add_widget (snap_type_selector);
3021 mouse_mode_size_group->add_widget (snap_mode_selector);
3023 mouse_mode_size_group->add_widget (edit_point_selector);
3024 mouse_mode_size_group->add_widget (edit_mode_selector);
3026 mouse_mode_size_group->add_widget (*nudge_clock);
3027 mouse_mode_size_group->add_widget (nudge_forward_button);
3028 mouse_mode_size_group->add_widget (nudge_backward_button);
3030 mouse_mode_hbox->set_spacing (2);
3032 if (!ARDOUR::Profile->get_trx()) {
3033 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
3036 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
3037 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
3039 if (!ARDOUR::Profile->get_mixbus()) {
3040 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
3043 if (!ARDOUR::Profile->get_trx()) {
3044 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
3045 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
3046 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
3047 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
3050 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
3052 mouse_mode_align->add (*mouse_mode_vbox);
3053 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
3055 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
3057 edit_mode_selector.set_name ("mouse mode button");
3059 if (!ARDOUR::Profile->get_trx()) {
3060 mode_box->pack_start (edit_mode_selector, false, false);
3063 mode_box->pack_start (*mouse_mode_box, false, false);
3067 _zoom_box.set_spacing (2);
3068 _zoom_box.set_border_width (2);
3072 zoom_preset_selector.set_name ("zoom button");
3073 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3074 zoom_preset_selector.set_size_request (42, -1);
3076 zoom_in_button.set_name ("zoom button");
3077 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3078 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3079 zoom_in_button.set_related_action (act);
3081 zoom_out_button.set_name ("zoom button");
3082 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3083 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3084 zoom_out_button.set_related_action (act);
3086 zoom_out_full_button.set_name ("zoom button");
3087 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3088 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3089 zoom_out_full_button.set_related_action (act);
3091 zoom_focus_selector.set_name ("zoom button");
3093 if (ARDOUR::Profile->get_mixbus()) {
3094 _zoom_box.pack_start (zoom_preset_selector, false, false);
3095 } else if (ARDOUR::Profile->get_trx()) {
3096 mode_box->pack_start (zoom_out_button, false, false);
3097 mode_box->pack_start (zoom_in_button, false, false);
3099 _zoom_box.pack_start (zoom_out_button, false, false);
3100 _zoom_box.pack_start (zoom_in_button, false, false);
3101 _zoom_box.pack_start (zoom_out_full_button, false, false);
3102 _zoom_box.pack_start (zoom_focus_selector, false, false);
3105 /* Track zoom buttons */
3106 visible_tracks_selector.set_name ("zoom button");
3107 if (Profile->get_mixbus()) {
3108 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3109 visible_tracks_selector.set_size_request (42, -1);
3111 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3114 tav_expand_button.set_name ("zoom button");
3115 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3116 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3117 tav_expand_button.set_related_action (act);
3119 tav_shrink_button.set_name ("zoom button");
3120 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3121 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3122 tav_shrink_button.set_related_action (act);
3124 if (ARDOUR::Profile->get_mixbus()) {
3125 _zoom_box.pack_start (visible_tracks_selector);
3126 } else if (ARDOUR::Profile->get_trx()) {
3127 _zoom_box.pack_start (tav_shrink_button);
3128 _zoom_box.pack_start (tav_expand_button);
3130 _zoom_box.pack_start (visible_tracks_selector);
3131 _zoom_box.pack_start (tav_shrink_button);
3132 _zoom_box.pack_start (tav_expand_button);
3135 snap_box.set_spacing (2);
3136 snap_box.set_border_width (2);
3138 snap_type_selector.set_name ("mouse mode button");
3140 snap_mode_selector.set_name ("mouse mode button");
3142 edit_point_selector.set_name ("mouse mode button");
3144 snap_box.pack_start (snap_mode_selector, false, false);
3145 snap_box.pack_start (snap_type_selector, false, false);
3146 snap_box.pack_start (edit_point_selector, false, false);
3150 HBox *nudge_box = manage (new HBox);
3151 nudge_box->set_spacing (2);
3152 nudge_box->set_border_width (2);
3154 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3155 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3157 nudge_box->pack_start (nudge_backward_button, false, false);
3158 nudge_box->pack_start (nudge_forward_button, false, false);
3159 nudge_box->pack_start (*nudge_clock, false, false);
3162 /* Pack everything in... */
3164 HBox* hbox = manage (new HBox);
3165 hbox->set_spacing(2);
3167 toolbar_hbox.set_spacing (2);
3168 toolbar_hbox.set_border_width (1);
3170 toolbar_hbox.pack_start (*mode_box, false, false);
3171 if (!ARDOUR::Profile->get_trx()) {
3172 toolbar_hbox.pack_start (_zoom_box, false, false);
3173 toolbar_hbox.pack_start (*hbox, false, false);
3176 if (!ARDOUR::Profile->get_trx()) {
3177 hbox->pack_start (snap_box, false, false);
3178 hbox->pack_start (*nudge_box, false, false);
3183 toolbar_base.set_name ("ToolBarBase");
3184 toolbar_base.add (toolbar_hbox);
3186 _toolbar_viewport.add (toolbar_base);
3187 /* stick to the required height but allow width to vary if there's not enough room */
3188 _toolbar_viewport.set_size_request (1, -1);
3190 toolbar_frame.set_shadow_type (SHADOW_OUT);
3191 toolbar_frame.set_name ("BaseFrame");
3192 toolbar_frame.add (_toolbar_viewport);
3196 Editor::build_edit_point_menu ()
3198 using namespace Menu_Helpers;
3200 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3201 if(!Profile->get_mixbus())
3202 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3203 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3205 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3209 Editor::build_edit_mode_menu ()
3211 using namespace Menu_Helpers;
3213 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3214 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3215 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3216 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3218 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3222 Editor::build_snap_mode_menu ()
3224 using namespace Menu_Helpers;
3226 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3227 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3228 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3230 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3234 Editor::build_snap_type_menu ()
3236 using namespace Menu_Helpers;
3238 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3239 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3240 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3241 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3242 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3243 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3244 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3245 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3246 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3247 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3248 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3249 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3250 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3251 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3252 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3253 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3254 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3255 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3256 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3257 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3258 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3259 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3260 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3261 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3262 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3263 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3264 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3265 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3266 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3267 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3269 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3274 Editor::setup_tooltips ()
3276 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3277 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3278 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3279 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3280 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3281 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3282 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3283 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3284 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3285 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3286 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3287 set_tooltip (zoom_in_button, _("Zoom In"));
3288 set_tooltip (zoom_out_button, _("Zoom Out"));
3289 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3290 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3291 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3292 set_tooltip (tav_expand_button, _("Expand Tracks"));
3293 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3294 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3295 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3296 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3297 set_tooltip (edit_point_selector, _("Edit Point"));
3298 set_tooltip (edit_mode_selector, _("Edit Mode"));
3299 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3303 Editor::convert_drop_to_paths (
3304 vector<string>& paths,
3305 const RefPtr<Gdk::DragContext>& /*context*/,
3308 const SelectionData& data,
3312 if (_session == 0) {
3316 vector<string> uris = data.get_uris();
3320 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3321 are actually URI lists. So do it by hand.
3324 if (data.get_target() != "text/plain") {
3328 /* Parse the "uri-list" format that Nautilus provides,
3329 where each pathname is delimited by \r\n.
3331 THERE MAY BE NO NULL TERMINATING CHAR!!!
3334 string txt = data.get_text();
3338 p = (char *) malloc (txt.length() + 1);
3339 txt.copy (p, txt.length(), 0);
3340 p[txt.length()] = '\0';
3346 while (g_ascii_isspace (*p))
3350 while (*q && (*q != '\n') && (*q != '\r')) {
3357 while (q > p && g_ascii_isspace (*q))
3362 uris.push_back (string (p, q - p + 1));
3366 p = strchr (p, '\n');
3378 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3379 if ((*i).substr (0,7) == "file://") {
3380 paths.push_back (Glib::filename_from_uri (*i));
3388 Editor::new_tempo_section ()
3393 Editor::map_transport_state ()
3395 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3397 if (_session && _session->transport_stopped()) {
3398 have_pending_keyboard_selection = false;
3401 update_loop_range_view ();
3407 Editor::begin_selection_op_history ()
3409 selection_op_cmd_depth = 0;
3410 selection_op_history_it = 0;
3412 while(!selection_op_history.empty()) {
3413 delete selection_op_history.front();
3414 selection_op_history.pop_front();
3417 selection_undo_action->set_sensitive (false);
3418 selection_redo_action->set_sensitive (false);
3419 selection_op_history.push_front (&_selection_memento->get_state ());
3423 Editor::begin_reversible_selection_op (string name)
3426 //cerr << name << endl;
3427 /* begin/commit pairs can be nested */
3428 selection_op_cmd_depth++;
3433 Editor::commit_reversible_selection_op ()
3436 if (selection_op_cmd_depth == 1) {
3438 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3440 The user has undone some selection ops and then made a new one,
3441 making anything earlier in the list invalid.
3444 list<XMLNode *>::iterator it = selection_op_history.begin();
3445 list<XMLNode *>::iterator e_it = it;
3446 advance (e_it, selection_op_history_it);
3448 for ( ; it != e_it; ++it) {
3451 selection_op_history.erase (selection_op_history.begin(), e_it);
3454 selection_op_history.push_front (&_selection_memento->get_state ());
3455 selection_op_history_it = 0;
3457 selection_undo_action->set_sensitive (true);
3458 selection_redo_action->set_sensitive (false);
3461 if (selection_op_cmd_depth > 0) {
3462 selection_op_cmd_depth--;
3468 Editor::undo_selection_op ()
3471 selection_op_history_it++;
3473 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3474 if (n == selection_op_history_it) {
3475 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3476 selection_redo_action->set_sensitive (true);
3480 /* is there an earlier entry? */
3481 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3482 selection_undo_action->set_sensitive (false);
3488 Editor::redo_selection_op ()
3491 if (selection_op_history_it > 0) {
3492 selection_op_history_it--;
3495 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3496 if (n == selection_op_history_it) {
3497 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3498 selection_undo_action->set_sensitive (true);
3503 if (selection_op_history_it == 0) {
3504 selection_redo_action->set_sensitive (false);
3510 Editor::begin_reversible_command (string name)
3513 before.push_back (&_selection_memento->get_state ());
3514 _session->begin_reversible_command (name);
3519 Editor::begin_reversible_command (GQuark q)
3522 before.push_back (&_selection_memento->get_state ());
3523 _session->begin_reversible_command (q);
3528 Editor::abort_reversible_command ()
3531 while(!before.empty()) {
3532 delete before.front();
3535 _session->abort_reversible_command ();
3540 Editor::commit_reversible_command ()
3543 if (before.size() == 1) {
3544 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3545 redo_action->set_sensitive(false);
3546 undo_action->set_sensitive(true);
3547 begin_selection_op_history ();
3550 if (before.empty()) {
3551 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3556 _session->commit_reversible_command ();
3561 Editor::history_changed ()
3565 if (undo_action && _session) {
3566 if (_session->undo_depth() == 0) {
3567 label = S_("Command|Undo");
3569 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3571 undo_action->property_label() = label;
3574 if (redo_action && _session) {
3575 if (_session->redo_depth() == 0) {
3577 redo_action->set_sensitive (false);
3579 label = string_compose(_("Redo (%1)"), _session->next_redo());
3580 redo_action->set_sensitive (true);
3582 redo_action->property_label() = label;
3587 Editor::duplicate_range (bool with_dialog)
3591 RegionSelection rs = get_regions_from_selection_and_entered ();
3593 if ( selection->time.length() == 0 && rs.empty()) {
3599 ArdourDialog win (_("Duplicate"));
3600 Label label (_("Number of duplications:"));
3601 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3602 SpinButton spinner (adjustment, 0.0, 1);
3605 win.get_vbox()->set_spacing (12);
3606 win.get_vbox()->pack_start (hbox);
3607 hbox.set_border_width (6);
3608 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3610 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3611 place, visually. so do this by hand.
3614 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3615 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3616 spinner.grab_focus();
3622 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3623 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3624 win.set_default_response (RESPONSE_ACCEPT);
3626 spinner.grab_focus ();
3628 switch (win.run ()) {
3629 case RESPONSE_ACCEPT:
3635 times = adjustment.get_value();
3638 if ((current_mouse_mode() == Editing::MouseRange)) {
3639 if (selection->time.length()) {
3640 duplicate_selection (times);
3642 } else if (get_smart_mode()) {
3643 if (selection->time.length()) {
3644 duplicate_selection (times);
3646 duplicate_some_regions (rs, times);
3648 duplicate_some_regions (rs, times);
3653 Editor::set_edit_mode (EditMode m)
3655 Config->set_edit_mode (m);
3659 Editor::cycle_edit_mode ()
3661 switch (Config->get_edit_mode()) {
3663 Config->set_edit_mode (Ripple);
3667 Config->set_edit_mode (Lock);
3670 Config->set_edit_mode (Slide);
3676 Editor::edit_mode_selection_done ( EditMode m )
3678 Config->set_edit_mode ( m );
3682 Editor::snap_type_selection_done (SnapType snaptype)
3684 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3686 ract->set_active ();
3691 Editor::snap_mode_selection_done (SnapMode mode)
3693 RefPtr<RadioAction> ract = snap_mode_action (mode);
3696 ract->set_active (true);
3701 Editor::cycle_edit_point (bool with_marker)
3703 if(Profile->get_mixbus())
3704 with_marker = false;
3706 switch (_edit_point) {
3708 set_edit_point_preference (EditAtPlayhead);
3710 case EditAtPlayhead:
3712 set_edit_point_preference (EditAtSelectedMarker);
3714 set_edit_point_preference (EditAtMouse);
3717 case EditAtSelectedMarker:
3718 set_edit_point_preference (EditAtMouse);
3724 Editor::edit_point_selection_done (EditPoint ep)
3726 set_edit_point_preference ( ep );
3730 Editor::build_zoom_focus_menu ()
3732 using namespace Menu_Helpers;
3734 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3735 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3736 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3737 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3738 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3739 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3741 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3745 Editor::zoom_focus_selection_done ( ZoomFocus f )
3747 RefPtr<RadioAction> ract = zoom_focus_action (f);
3749 ract->set_active ();
3754 Editor::build_track_count_menu ()
3756 using namespace Menu_Helpers;
3758 if (!Profile->get_mixbus()) {
3759 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3760 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3761 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3762 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3763 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3764 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3765 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3766 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3767 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3768 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3769 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3770 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3771 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3773 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3774 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3775 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3776 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3777 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3778 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3779 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3780 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3781 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3782 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3784 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3785 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3786 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3787 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3788 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3789 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3790 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3791 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3792 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3793 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3794 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3799 Editor::set_zoom_preset (int64_t ms)
3802 temporal_zoom_session();
3806 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3807 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3811 Editor::set_visible_track_count (int32_t n)
3813 _visible_track_count = n;
3815 /* if the canvas hasn't really been allocated any size yet, just
3816 record the desired number of visible tracks and return. when canvas
3817 allocation happens, we will get called again and then we can do the
3821 if (_visible_canvas_height <= 1) {
3827 DisplaySuspender ds;
3829 if (_visible_track_count > 0) {
3830 h = trackviews_height() / _visible_track_count;
3831 std::ostringstream s;
3832 s << _visible_track_count;
3834 } else if (_visible_track_count == 0) {
3836 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3837 if ((*i)->marked_for_display()) {
3841 h = trackviews_height() / n;
3844 /* negative value means that the visible track count has
3845 been overridden by explicit track height changes.
3847 visible_tracks_selector.set_text (X_("*"));
3851 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3852 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3855 if (str != visible_tracks_selector.get_text()) {
3856 visible_tracks_selector.set_text (str);
3861 Editor::override_visible_track_count ()
3863 _visible_track_count = -1;
3864 visible_tracks_selector.set_text ( _("*") );
3868 Editor::edit_controls_button_release (GdkEventButton* ev)
3870 if (Keyboard::is_context_menu_event (ev)) {
3871 ARDOUR_UI::instance()->add_route ();
3872 } else if (ev->button == 1) {
3873 selection->clear_tracks ();
3880 Editor::mouse_select_button_release (GdkEventButton* ev)
3882 /* this handles just right-clicks */
3884 if (ev->button != 3) {
3892 Editor::set_zoom_focus (ZoomFocus f)
3894 string str = zoom_focus_strings[(int)f];
3896 if (str != zoom_focus_selector.get_text()) {
3897 zoom_focus_selector.set_text (str);
3900 if (zoom_focus != f) {
3907 Editor::cycle_zoom_focus ()
3909 switch (zoom_focus) {
3911 set_zoom_focus (ZoomFocusRight);
3913 case ZoomFocusRight:
3914 set_zoom_focus (ZoomFocusCenter);
3916 case ZoomFocusCenter:
3917 set_zoom_focus (ZoomFocusPlayhead);
3919 case ZoomFocusPlayhead:
3920 set_zoom_focus (ZoomFocusMouse);
3922 case ZoomFocusMouse:
3923 set_zoom_focus (ZoomFocusEdit);
3926 set_zoom_focus (ZoomFocusLeft);
3932 Editor::set_show_measures (bool yn)
3934 if (_show_measures != yn) {
3937 if ((_show_measures = yn) == true) {
3939 tempo_lines->show();
3942 std::vector<TempoMap::BBTPoint> grid;
3943 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
3944 draw_measures (grid);
3952 Editor::toggle_follow_playhead ()
3954 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3956 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3957 set_follow_playhead (tact->get_active());
3961 /** @param yn true to follow playhead, otherwise false.
3962 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3965 Editor::set_follow_playhead (bool yn, bool catch_up)
3967 if (_follow_playhead != yn) {
3968 if ((_follow_playhead = yn) == true && catch_up) {
3970 reset_x_origin_to_follow_playhead ();
3977 Editor::toggle_stationary_playhead ()
3979 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3981 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3982 set_stationary_playhead (tact->get_active());
3987 Editor::set_stationary_playhead (bool yn)
3989 if (_stationary_playhead != yn) {
3990 if ((_stationary_playhead = yn) == true) {
3992 // FIXME need a 3.0 equivalent of this 2.X call
3993 // update_current_screen ();
4000 Editor::playlist_selector () const
4002 return *_playlist_selector;
4006 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4008 if (paste_count == 0) {
4009 /* don't bother calculating an offset that will be zero anyway */
4013 /* calculate basic unsnapped multi-paste offset */
4014 framecnt_t offset = paste_count * duration;
4016 /* snap offset so pos + offset is aligned to the grid */
4017 framepos_t offset_pos = pos + offset;
4018 snap_to(offset_pos, RoundUpMaybe);
4019 offset = offset_pos - pos;
4025 Editor::get_grid_beat_divisions(framepos_t position)
4027 switch (_snap_type) {
4028 case SnapToBeatDiv128: return 128;
4029 case SnapToBeatDiv64: return 64;
4030 case SnapToBeatDiv32: return 32;
4031 case SnapToBeatDiv28: return 28;
4032 case SnapToBeatDiv24: return 24;
4033 case SnapToBeatDiv20: return 20;
4034 case SnapToBeatDiv16: return 16;
4035 case SnapToBeatDiv14: return 14;
4036 case SnapToBeatDiv12: return 12;
4037 case SnapToBeatDiv10: return 10;
4038 case SnapToBeatDiv8: return 8;
4039 case SnapToBeatDiv7: return 7;
4040 case SnapToBeatDiv6: return 6;
4041 case SnapToBeatDiv5: return 5;
4042 case SnapToBeatDiv4: return 4;
4043 case SnapToBeatDiv3: return 3;
4044 case SnapToBeatDiv2: return 2;
4051 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4055 const unsigned divisions = get_grid_beat_divisions(position);
4057 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4060 switch (_snap_type) {
4062 return Evoral::Beats(1.0);
4065 return Evoral::Beats(_session->tempo_map().meter_at_frame (position).divisions_per_bar());
4073 return Evoral::Beats();
4077 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4081 ret = nudge_clock->current_duration (pos);
4082 next = ret + 1; /* XXXX fix me */
4088 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4090 ArdourDialog dialog (_("Playlist Deletion"));
4091 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4092 "If it is kept, its audio files will not be cleaned.\n"
4093 "If it is deleted, audio files used by it alone will be cleaned."),
4096 dialog.set_position (WIN_POS_CENTER);
4097 dialog.get_vbox()->pack_start (label);
4101 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4102 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4103 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4104 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4105 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4107 // by default gtk uses the left most button
4108 keep->grab_focus ();
4110 switch (dialog.run ()) {
4112 /* keep this and all remaining ones */
4117 /* delete this and all others */
4121 case RESPONSE_ACCEPT:
4122 /* delete the playlist */
4126 case RESPONSE_REJECT:
4127 /* keep the playlist */
4139 Editor::audio_region_selection_covers (framepos_t where)
4141 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4142 if ((*a)->region()->covers (where)) {
4151 Editor::prepare_for_cleanup ()
4153 cut_buffer->clear_regions ();
4154 cut_buffer->clear_playlists ();
4156 selection->clear_regions ();
4157 selection->clear_playlists ();
4159 _regions->suspend_redisplay ();
4163 Editor::finish_cleanup ()
4165 _regions->resume_redisplay ();
4169 Editor::transport_loop_location()
4172 return _session->locations()->auto_loop_location();
4179 Editor::transport_punch_location()
4182 return _session->locations()->auto_punch_location();
4189 Editor::control_layout_scroll (GdkEventScroll* ev)
4191 /* Just forward to the normal canvas scroll method. The coordinate
4192 systems are different but since the canvas is always larger than the
4193 track headers, and aligned with the trackview area, this will work.
4195 In the not too distant future this layout is going away anyway and
4196 headers will be on the canvas.
4198 return canvas_scroll_event (ev, false);
4202 Editor::session_state_saved (string)
4205 _snapshots->redisplay ();
4209 Editor::maximise_editing_space ()
4215 Gtk::Window* toplevel = current_toplevel();
4218 toplevel->fullscreen ();
4224 Editor::restore_editing_space ()
4230 Gtk::Window* toplevel = current_toplevel();
4233 toplevel->unfullscreen();
4239 * Make new playlists for a given track and also any others that belong
4240 * to the same active route group with the `select' property.
4245 Editor::new_playlists (TimeAxisView* v)
4247 begin_reversible_command (_("new playlists"));
4248 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4249 _session->playlists->get (playlists);
4250 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4251 commit_reversible_command ();
4255 * Use a copy of the current playlist for a given track and also any others that belong
4256 * to the same active route group with the `select' property.
4261 Editor::copy_playlists (TimeAxisView* v)
4263 begin_reversible_command (_("copy playlists"));
4264 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4265 _session->playlists->get (playlists);
4266 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4267 commit_reversible_command ();
4270 /** Clear the current playlist for a given track and also any others that belong
4271 * to the same active route group with the `select' property.
4276 Editor::clear_playlists (TimeAxisView* v)
4278 begin_reversible_command (_("clear playlists"));
4279 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4280 _session->playlists->get (playlists);
4281 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4282 commit_reversible_command ();
4286 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4288 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4292 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4294 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4298 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4300 atv.clear_playlist ();
4304 Editor::get_y_origin () const
4306 return vertical_adjustment.get_value ();
4309 /** Queue up a change to the viewport x origin.
4310 * @param frame New x origin.
4313 Editor::reset_x_origin (framepos_t frame)
4315 pending_visual_change.add (VisualChange::TimeOrigin);
4316 pending_visual_change.time_origin = frame;
4317 ensure_visual_change_idle_handler ();
4321 Editor::reset_y_origin (double y)
4323 pending_visual_change.add (VisualChange::YOrigin);
4324 pending_visual_change.y_origin = y;
4325 ensure_visual_change_idle_handler ();
4329 Editor::reset_zoom (framecnt_t spp)
4331 if (spp == samples_per_pixel) {
4335 pending_visual_change.add (VisualChange::ZoomLevel);
4336 pending_visual_change.samples_per_pixel = spp;
4337 ensure_visual_change_idle_handler ();
4341 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4343 reset_x_origin (frame);
4346 if (!no_save_visual) {
4347 undo_visual_stack.push_back (current_visual_state(false));
4351 Editor::VisualState::VisualState (bool with_tracks)
4352 : gui_state (with_tracks ? new GUIObjectState : 0)
4356 Editor::VisualState::~VisualState ()
4361 Editor::VisualState*
4362 Editor::current_visual_state (bool with_tracks)
4364 VisualState* vs = new VisualState (with_tracks);
4365 vs->y_position = vertical_adjustment.get_value();
4366 vs->samples_per_pixel = samples_per_pixel;
4367 vs->leftmost_frame = leftmost_frame;
4368 vs->zoom_focus = zoom_focus;
4371 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4378 Editor::undo_visual_state ()
4380 if (undo_visual_stack.empty()) {
4384 VisualState* vs = undo_visual_stack.back();
4385 undo_visual_stack.pop_back();
4388 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4391 use_visual_state (*vs);
4396 Editor::redo_visual_state ()
4398 if (redo_visual_stack.empty()) {
4402 VisualState* vs = redo_visual_stack.back();
4403 redo_visual_stack.pop_back();
4405 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4406 // why do we check here?
4407 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4410 use_visual_state (*vs);
4415 Editor::swap_visual_state ()
4417 if (undo_visual_stack.empty()) {
4418 redo_visual_state ();
4420 undo_visual_state ();
4425 Editor::use_visual_state (VisualState& vs)
4427 PBD::Unwinder<bool> nsv (no_save_visual, true);
4428 DisplaySuspender ds;
4430 vertical_adjustment.set_value (vs.y_position);
4432 set_zoom_focus (vs.zoom_focus);
4433 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4436 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4438 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4439 (*i)->clear_property_cache();
4440 (*i)->reset_visual_state ();
4444 _routes->update_visibility ();
4447 /** This is the core function that controls the zoom level of the canvas. It is called
4448 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4449 * @param spp new number of samples per pixel
4452 Editor::set_samples_per_pixel (framecnt_t spp)
4458 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4459 const framecnt_t lots_of_pixels = 4000;
4461 /* if the zoom level is greater than what you'd get trying to display 3
4462 * days of audio on a really big screen, then it's too big.
4465 if (spp * lots_of_pixels > three_days) {
4469 samples_per_pixel = spp;
4472 tempo_lines->tempo_map_changed();
4475 bool const showing_time_selection = selection->time.length() > 0;
4477 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4478 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4479 (*i)->reshow_selection (selection->time);
4483 ZoomChanged (); /* EMIT_SIGNAL */
4485 ArdourCanvas::GtkCanvasViewport* c;
4487 c = get_track_canvas();
4489 c->canvas()->zoomed ();
4492 if (playhead_cursor) {
4493 playhead_cursor->set_position (playhead_cursor->current_frame ());
4496 refresh_location_display();
4497 _summary->set_overlays_dirty ();
4499 update_marker_labels ();
4505 Editor::queue_visual_videotimeline_update ()
4508 * pending_visual_change.add (VisualChange::VideoTimeline);
4509 * or maybe even more specific: which videotimeline-image
4510 * currently it calls update_video_timeline() to update
4511 * _all outdated_ images on the video-timeline.
4512 * see 'exposeimg()' in video_image_frame.cc
4514 ensure_visual_change_idle_handler ();
4518 Editor::ensure_visual_change_idle_handler ()
4520 if (pending_visual_change.idle_handler_id < 0) {
4521 // see comment in add_to_idle_resize above.
4522 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4523 pending_visual_change.being_handled = false;
4528 Editor::_idle_visual_changer (void* arg)
4530 return static_cast<Editor*>(arg)->idle_visual_changer ();
4534 Editor::idle_visual_changer ()
4536 /* set_horizontal_position() below (and maybe other calls) call
4537 gtk_main_iteration(), so it's possible that a signal will be handled
4538 half-way through this method. If this signal wants an
4539 idle_visual_changer we must schedule another one after this one, so
4540 mark the idle_handler_id as -1 here to allow that. Also make a note
4541 that we are doing the visual change, so that changes in response to
4542 super-rapid-screen-update can be dropped if we are still processing
4546 pending_visual_change.idle_handler_id = -1;
4547 pending_visual_change.being_handled = true;
4549 VisualChange vc = pending_visual_change;
4551 pending_visual_change.pending = (VisualChange::Type) 0;
4553 visual_changer (vc);
4555 pending_visual_change.being_handled = false;
4557 return 0; /* this is always a one-shot call */
4561 Editor::visual_changer (const VisualChange& vc)
4563 double const last_time_origin = horizontal_position ();
4565 if (vc.pending & VisualChange::ZoomLevel) {
4566 set_samples_per_pixel (vc.samples_per_pixel);
4568 compute_fixed_ruler_scale ();
4570 std::vector<TempoMap::BBTPoint> grid;
4571 compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4572 compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4573 update_tempo_based_rulers (grid);
4575 update_video_timeline();
4578 if (vc.pending & VisualChange::TimeOrigin) {
4579 set_horizontal_position (vc.time_origin / samples_per_pixel);
4582 if (vc.pending & VisualChange::YOrigin) {
4583 vertical_adjustment.set_value (vc.y_origin);
4586 if (last_time_origin == horizontal_position ()) {
4587 /* changed signal not emitted */
4588 update_fixed_rulers ();
4589 redisplay_tempo (true);
4592 if (!(vc.pending & VisualChange::ZoomLevel)) {
4593 update_video_timeline();
4596 _summary->set_overlays_dirty ();
4599 struct EditorOrderTimeAxisSorter {
4600 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4601 return a->order () < b->order ();
4606 Editor::sort_track_selection (TrackViewList& sel)
4608 EditorOrderTimeAxisSorter cmp;
4613 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4616 framepos_t where = 0;
4617 EditPoint ep = _edit_point;
4619 if (Profile->get_mixbus())
4620 if (ep == EditAtSelectedMarker)
4621 ep = EditAtPlayhead;
4623 if (from_outside_canvas && (ep == EditAtMouse)) {
4624 ep = EditAtPlayhead;
4625 } else if (from_context_menu && (ep == EditAtMouse)) {
4626 return canvas_event_sample (&context_click_event, 0, 0);
4629 if (entered_marker) {
4630 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4631 return entered_marker->position();
4634 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4635 ep = EditAtSelectedMarker;
4638 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4639 ep = EditAtPlayhead;
4643 case EditAtPlayhead:
4644 if (_dragging_playhead) {
4645 where = *_control_scroll_target;
4647 where = _session->audible_frame();
4649 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4652 case EditAtSelectedMarker:
4653 if (!selection->markers.empty()) {
4655 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4658 where = loc->start();
4662 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4670 if (!mouse_frame (where, ignored)) {
4671 /* XXX not right but what can we do ? */
4675 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4683 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4685 if (!_session) return;
4687 begin_reversible_command (cmd);
4691 if ((tll = transport_loop_location()) == 0) {
4692 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4693 XMLNode &before = _session->locations()->get_state();
4694 _session->locations()->add (loc, true);
4695 _session->set_auto_loop_location (loc);
4696 XMLNode &after = _session->locations()->get_state();
4697 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4699 XMLNode &before = tll->get_state();
4700 tll->set_hidden (false, this);
4701 tll->set (start, end);
4702 XMLNode &after = tll->get_state();
4703 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4706 commit_reversible_command ();
4710 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4712 if (!_session) return;
4714 begin_reversible_command (cmd);
4718 if ((tpl = transport_punch_location()) == 0) {
4719 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4720 XMLNode &before = _session->locations()->get_state();
4721 _session->locations()->add (loc, true);
4722 _session->set_auto_punch_location (loc);
4723 XMLNode &after = _session->locations()->get_state();
4724 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4726 XMLNode &before = tpl->get_state();
4727 tpl->set_hidden (false, this);
4728 tpl->set (start, end);
4729 XMLNode &after = tpl->get_state();
4730 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4733 commit_reversible_command ();
4736 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4737 * @param rs List to which found regions are added.
4738 * @param where Time to look at.
4739 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4742 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4744 const TrackViewList* tracks;
4747 tracks = &track_views;
4752 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4754 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4757 boost::shared_ptr<Track> tr;
4758 boost::shared_ptr<Playlist> pl;
4760 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4762 boost::shared_ptr<RegionList> regions = pl->regions_at (
4763 (framepos_t) floor ( (double) where * tr->speed()));
4765 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4766 RegionView* rv = rtv->view()->find_view (*i);
4777 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4779 const TrackViewList* tracks;
4782 tracks = &track_views;
4787 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4788 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4790 boost::shared_ptr<Track> tr;
4791 boost::shared_ptr<Playlist> pl;
4793 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4795 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4796 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4798 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4800 RegionView* rv = rtv->view()->find_view (*i);
4811 /** Get regions using the following method:
4813 * Make a region list using:
4814 * (a) any selected regions
4815 * (b) the intersection of any selected tracks and the edit point(*)
4816 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4818 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4820 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4824 Editor::get_regions_from_selection_and_edit_point ()
4826 RegionSelection regions;
4828 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4829 regions.add (entered_regionview);
4831 regions = selection->regions;
4834 if ( regions.empty() ) {
4835 TrackViewList tracks = selection->tracks;
4837 if (!tracks.empty()) {
4838 /* no region selected or entered, but some selected tracks:
4839 * act on all regions on the selected tracks at the edit point
4841 framepos_t const where = get_preferred_edit_position ();
4842 get_regions_at(regions, where, tracks);
4849 /** Get regions using the following method:
4851 * Make a region list using:
4852 * (a) any selected regions
4853 * (b) the intersection of any selected tracks and the edit point(*)
4854 * (c) if neither exists, then whatever region is under the mouse
4856 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4858 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4861 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4863 RegionSelection regions;
4865 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4866 regions.add (entered_regionview);
4868 regions = selection->regions;
4871 if ( regions.empty() ) {
4872 TrackViewList tracks = selection->tracks;
4874 if (!tracks.empty()) {
4875 /* no region selected or entered, but some selected tracks:
4876 * act on all regions on the selected tracks at the edit point
4878 get_regions_at(regions, pos, tracks);
4885 /** Start with regions that are selected, or the entered regionview if none are selected.
4886 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4887 * of the regions that we started with.
4891 Editor::get_regions_from_selection_and_entered () const
4893 RegionSelection regions = selection->regions;
4895 if (regions.empty() && entered_regionview) {
4896 regions.add (entered_regionview);
4903 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4905 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4906 RouteTimeAxisView* rtav;
4908 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4909 boost::shared_ptr<Playlist> pl;
4910 std::vector<boost::shared_ptr<Region> > results;
4911 boost::shared_ptr<Track> tr;
4913 if ((tr = rtav->track()) == 0) {
4918 if ((pl = (tr->playlist())) != 0) {
4919 boost::shared_ptr<Region> r = pl->region_by_id (id);
4921 RegionView* rv = rtav->view()->find_view (r);
4923 regions.push_back (rv);
4932 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4935 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4936 MidiTimeAxisView* mtav;
4938 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4940 mtav->get_per_region_note_selection (selection);
4947 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4949 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4951 RouteTimeAxisView* tatv;
4953 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4955 boost::shared_ptr<Playlist> pl;
4956 vector<boost::shared_ptr<Region> > results;
4958 boost::shared_ptr<Track> tr;
4960 if ((tr = tatv->track()) == 0) {
4965 if ((pl = (tr->playlist())) != 0) {
4966 if (src_comparison) {
4967 pl->get_source_equivalent_regions (region, results);
4969 pl->get_region_list_equivalent_regions (region, results);
4973 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4974 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4975 regions.push_back (marv);
4984 Editor::show_rhythm_ferret ()
4986 if (rhythm_ferret == 0) {
4987 rhythm_ferret = new RhythmFerret(*this);
4990 rhythm_ferret->set_session (_session);
4991 rhythm_ferret->show ();
4992 rhythm_ferret->present ();
4996 Editor::first_idle ()
4998 MessageDialog* dialog = 0;
5000 if (track_views.size() > 1) {
5001 Timers::TimerSuspender t;
5002 dialog = new MessageDialog (
5003 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5007 ARDOUR_UI::instance()->flush_pending ();
5010 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5014 // first idle adds route children (automation tracks), so we need to redisplay here
5015 _routes->redisplay ();
5019 if (_session->undo_depth() == 0) {
5020 undo_action->set_sensitive(false);
5022 redo_action->set_sensitive(false);
5023 begin_selection_op_history ();
5029 Editor::_idle_resize (gpointer arg)
5031 return ((Editor*)arg)->idle_resize ();
5035 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5037 if (resize_idle_id < 0) {
5038 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5039 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5040 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5042 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5043 _pending_resize_amount = 0;
5046 /* make a note of the smallest resulting height, so that we can clamp the
5047 lower limit at TimeAxisView::hSmall */
5049 int32_t min_resulting = INT32_MAX;
5051 _pending_resize_amount += h;
5052 _pending_resize_view = view;
5054 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5056 if (selection->tracks.contains (_pending_resize_view)) {
5057 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5058 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5062 if (min_resulting < 0) {
5067 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5068 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5072 /** Handle pending resizing of tracks */
5074 Editor::idle_resize ()
5076 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5078 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5079 selection->tracks.contains (_pending_resize_view)) {
5081 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5082 if (*i != _pending_resize_view) {
5083 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5088 _pending_resize_amount = 0;
5089 _group_tabs->set_dirty ();
5090 resize_idle_id = -1;
5098 ENSURE_GUI_THREAD (*this, &Editor::located);
5101 playhead_cursor->set_position (_session->audible_frame ());
5102 if (_follow_playhead && !_pending_initial_locate) {
5103 reset_x_origin_to_follow_playhead ();
5107 _pending_locate_request = false;
5108 _pending_initial_locate = false;
5112 Editor::region_view_added (RegionView * rv)
5114 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5115 if (rv->region ()->id () == (*pr)) {
5116 selection->add (rv);
5117 selection->regions.pending.erase (pr);
5122 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5124 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5125 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5126 if (rv->region()->id () == (*rnote).first) {
5127 mrv->select_notes ((*rnote).second);
5128 selection->pending_midi_note_selection.erase(rnote);
5134 _summary->set_background_dirty ();
5138 Editor::region_view_removed ()
5140 _summary->set_background_dirty ();
5144 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5146 TrackViewList::const_iterator j = track_views.begin ();
5147 while (j != track_views.end()) {
5148 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5149 if (rtv && rtv->route() == r) {
5160 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5164 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5165 TimeAxisView* tv = axis_view_from_route (*i);
5175 Editor::suspend_route_redisplay ()
5178 _routes->suspend_redisplay();
5183 Editor::resume_route_redisplay ()
5186 _routes->redisplay(); // queue redisplay
5187 _routes->resume_redisplay();
5192 Editor::add_vcas (VCAList& vcas)
5194 VCATimeAxisView* vtv;
5195 list<VCATimeAxisView*> new_views;
5197 for (VCAList::iterator v = vcas.begin(); v != vcas.end(); ++v) {
5198 vtv = new VCATimeAxisView (*this, _session, *_track_canvas);
5200 new_views.push_back (vtv);
5203 if (new_views.size() > 0) {
5204 _routes->vcas_added (new_views);
5209 Editor::add_routes (RouteList& routes)
5211 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5213 RouteTimeAxisView *rtv;
5214 list<RouteTimeAxisView*> new_views;
5215 TrackViewList new_selection;
5216 bool from_scratch = (track_views.size() == 0);
5218 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5219 boost::shared_ptr<Route> route = (*x);
5221 if (route->is_auditioner() || route->is_monitor()) {
5225 DataType dt = route->input()->default_type();
5227 if (dt == ARDOUR::DataType::AUDIO) {
5228 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5229 rtv->set_route (route);
5230 } else if (dt == ARDOUR::DataType::MIDI) {
5231 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5232 rtv->set_route (route);
5234 throw unknown_type();
5237 new_views.push_back (rtv);
5238 track_views.push_back (rtv);
5239 new_selection.push_back (rtv);
5241 rtv->effective_gain_display ();
5243 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5244 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5247 if (new_views.size() > 0) {
5248 _routes->routes_added (new_views);
5249 _summary->routes_added (new_views);
5252 if (!from_scratch) {
5253 selection->tracks.clear();
5254 selection->add (new_selection);
5255 begin_selection_op_history();
5258 if (show_editor_mixer_when_tracks_arrive) {
5259 show_editor_mixer (true);
5262 editor_list_button.set_sensitive (true);
5266 Editor::timeaxisview_deleted (TimeAxisView *tv)
5268 if (tv == entered_track) {
5272 if (_session && _session->deletion_in_progress()) {
5273 /* the situation is under control */
5277 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5279 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5281 _routes->route_removed (tv);
5283 TimeAxisView::Children c = tv->get_child_list ();
5284 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5285 if (entered_track == i->get()) {
5290 /* remove it from the list of track views */
5292 TrackViewList::iterator i;
5294 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5295 i = track_views.erase (i);
5298 /* update whatever the current mixer strip is displaying, if revelant */
5300 boost::shared_ptr<Route> route;
5303 route = rtav->route ();
5306 if (current_mixer_strip && current_mixer_strip->route() == route) {
5308 TimeAxisView* next_tv;
5310 if (track_views.empty()) {
5312 } else if (i == track_views.end()) {
5313 next_tv = track_views.front();
5320 set_selected_mixer_strip (*next_tv);
5322 /* make the editor mixer strip go away setting the
5323 * button to inactive (which also unticks the menu option)
5326 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5332 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5334 if (apply_to_selection) {
5335 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5337 TrackSelection::iterator j = i;
5340 hide_track_in_display (*i, false);
5345 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5347 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5348 // this will hide the mixer strip
5349 set_selected_mixer_strip (*tv);
5352 _routes->hide_track_in_display (*tv);
5357 Editor::sync_track_view_list_and_routes ()
5359 track_views = TrackViewList (_routes->views ());
5361 _summary->set_background_dirty();
5362 _group_tabs->set_dirty ();
5364 return false; // do not call again (until needed)
5368 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5370 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5375 /** Find a RouteTimeAxisView by the ID of its route */
5377 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5379 RouteTimeAxisView* v;
5381 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5382 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5383 if(v->route()->id() == id) {
5393 Editor::fit_route_group (RouteGroup *g)
5395 TrackViewList ts = axis_views_from_routes (g->route_list ());
5400 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5402 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5405 _session->cancel_audition ();
5409 if (_session->is_auditioning()) {
5410 _session->cancel_audition ();
5411 if (r == last_audition_region) {
5416 _session->audition_region (r);
5417 last_audition_region = r;
5422 Editor::hide_a_region (boost::shared_ptr<Region> r)
5424 r->set_hidden (true);
5428 Editor::show_a_region (boost::shared_ptr<Region> r)
5430 r->set_hidden (false);
5434 Editor::audition_region_from_region_list ()
5436 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5440 Editor::hide_region_from_region_list ()
5442 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5446 Editor::show_region_in_region_list ()
5448 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5452 Editor::step_edit_status_change (bool yn)
5455 start_step_editing ();
5457 stop_step_editing ();
5462 Editor::start_step_editing ()
5464 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5468 Editor::stop_step_editing ()
5470 step_edit_connection.disconnect ();
5474 Editor::check_step_edit ()
5476 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5477 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5479 mtv->check_step_edit ();
5483 return true; // do it again, till we stop
5487 Editor::scroll_press (Direction dir)
5489 ++_scroll_callbacks;
5491 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5492 /* delay the first auto-repeat */
5498 scroll_backward (1);
5506 scroll_up_one_track ();
5510 scroll_down_one_track ();
5514 /* do hacky auto-repeat */
5515 if (!_scroll_connection.connected ()) {
5517 _scroll_connection = Glib::signal_timeout().connect (
5518 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5521 _scroll_callbacks = 0;
5528 Editor::scroll_release ()
5530 _scroll_connection.disconnect ();
5533 /** Queue a change for the Editor viewport x origin to follow the playhead */
5535 Editor::reset_x_origin_to_follow_playhead ()
5537 framepos_t const frame = playhead_cursor->current_frame ();
5539 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5541 if (_session->transport_speed() < 0) {
5543 if (frame > (current_page_samples() / 2)) {
5544 center_screen (frame-(current_page_samples()/2));
5546 center_screen (current_page_samples()/2);
5553 if (frame < leftmost_frame) {
5555 if (_session->transport_rolling()) {
5556 /* rolling; end up with the playhead at the right of the page */
5557 l = frame - current_page_samples ();
5559 /* not rolling: end up with the playhead 1/4 of the way along the page */
5560 l = frame - current_page_samples() / 4;
5564 if (_session->transport_rolling()) {
5565 /* rolling: end up with the playhead on the left of the page */
5568 /* not rolling: end up with the playhead 3/4 of the way along the page */
5569 l = frame - 3 * current_page_samples() / 4;
5577 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5583 Editor::super_rapid_screen_update ()
5585 if (!_session || !_session->engine().running()) {
5589 /* METERING / MIXER STRIPS */
5591 /* update track meters, if required */
5592 if (contents().is_mapped() && meters_running) {
5593 RouteTimeAxisView* rtv;
5594 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5595 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5596 rtv->fast_update ();
5601 /* and any current mixer strip */
5602 if (current_mixer_strip) {
5603 current_mixer_strip->fast_update ();
5606 /* PLAYHEAD AND VIEWPORT */
5608 framepos_t const frame = _session->audible_frame();
5610 /* There are a few reasons why we might not update the playhead / viewport stuff:
5612 * 1. we don't update things when there's a pending locate request, otherwise
5613 * when the editor requests a locate there is a chance that this method
5614 * will move the playhead before the locate request is processed, causing
5616 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5617 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5620 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5622 last_update_frame = frame;
5624 if (!_dragging_playhead) {
5625 playhead_cursor->set_position (frame);
5628 if (!_stationary_playhead) {
5630 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5631 /* We only do this if we aren't already
5632 handling a visual change (ie if
5633 pending_visual_change.being_handled is
5634 false) so that these requests don't stack
5635 up there are too many of them to handle in
5638 reset_x_origin_to_follow_playhead ();
5643 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5644 framepos_t const frame = playhead_cursor->current_frame ();
5645 double target = ((double)frame - (double)current_page_samples()/2.0);
5646 if (target <= 0.0) {
5649 // compare to EditorCursor::set_position()
5650 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5651 double const new_pos = sample_to_pixel_unrounded (target);
5652 if (rint (new_pos) != rint (old_pos)) {
5653 reset_x_origin (pixel_to_sample (floor (new_pos)));
5664 Editor::session_going_away ()
5666 _have_idled = false;
5668 _session_connections.drop_connections ();
5670 super_rapid_screen_update_connection.disconnect ();
5672 selection->clear ();
5673 cut_buffer->clear ();
5675 clicked_regionview = 0;
5676 clicked_axisview = 0;
5677 clicked_routeview = 0;
5678 entered_regionview = 0;
5680 last_update_frame = 0;
5683 playhead_cursor->hide ();
5685 /* rip everything out of the list displays */
5689 _route_groups->clear ();
5691 /* do this first so that deleting a track doesn't reset cms to null
5692 and thus cause a leak.
5695 if (current_mixer_strip) {
5696 if (current_mixer_strip->get_parent() != 0) {
5697 global_hpacker.remove (*current_mixer_strip);
5699 delete current_mixer_strip;
5700 current_mixer_strip = 0;
5703 /* delete all trackviews */
5705 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5708 track_views.clear ();
5710 nudge_clock->set_session (0);
5712 editor_list_button.set_active(false);
5713 editor_list_button.set_sensitive(false);
5715 /* clear tempo/meter rulers */
5716 remove_metric_marks ();
5718 clear_marker_display ();
5720 stop_step_editing ();
5724 /* get rid of any existing editor mixer strip */
5726 WindowTitle title(Glib::get_application_name());
5727 title += _("Editor");
5729 own_window()->set_title (title.get_string());
5732 SessionHandlePtr::session_going_away ();
5736 Editor::trigger_script (int i)
5738 LuaInstance::instance()-> call_action (i);
5742 Editor::set_script_action_name (int i, const std::string& n)
5744 string const a = string_compose (X_("script-action-%1"), i + 1);
5745 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5748 act->set_label (string_compose (_("Unset #%1"), i + 1));
5749 act->set_tooltip (_("no action bound"));
5750 act->set_sensitive (false);
5753 act->set_tooltip (n);
5754 act->set_sensitive (true);
5756 KeyEditor::UpdateBindings ();
5760 Editor::show_editor_list (bool yn)
5763 _the_notebook.show ();
5765 _the_notebook.hide ();
5770 Editor::change_region_layering_order (bool from_context_menu)
5772 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5774 if (!clicked_routeview) {
5775 if (layering_order_editor) {
5776 layering_order_editor->hide ();
5781 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5787 boost::shared_ptr<Playlist> pl = track->playlist();
5793 if (layering_order_editor == 0) {
5794 layering_order_editor = new RegionLayeringOrderEditor (*this);
5797 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5798 layering_order_editor->maybe_present ();
5802 Editor::update_region_layering_order_editor ()
5804 if (layering_order_editor && layering_order_editor->is_visible ()) {
5805 change_region_layering_order (true);
5810 Editor::setup_fade_images ()
5812 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5813 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5814 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5815 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5816 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5818 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5819 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5820 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5821 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5822 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5824 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5825 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5826 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5827 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5828 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5830 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5831 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5832 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5833 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5834 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5838 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5840 Editor::action_menu_item (std::string const & name)
5842 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5845 return *manage (a->create_menu_item ());
5849 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5851 EventBox* b = manage (new EventBox);
5852 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5853 Label* l = manage (new Label (name));
5857 _the_notebook.append_page (widget, *b);
5861 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5863 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5864 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5867 if (ev->type == GDK_2BUTTON_PRESS) {
5869 /* double-click on a notebook tab shrinks or expands the notebook */
5871 if (_notebook_shrunk) {
5872 if (pre_notebook_shrink_pane_width) {
5873 edit_pane.set_divider (0, *pre_notebook_shrink_pane_width);
5875 _notebook_shrunk = false;
5877 pre_notebook_shrink_pane_width = edit_pane.get_divider();
5879 /* this expands the LHS of the edit pane to cover the notebook
5880 PAGE but leaves the tabs visible.
5882 edit_pane.set_divider (0, edit_pane.get_divider() + page->get_width());
5883 _notebook_shrunk = true;
5891 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5893 using namespace Menu_Helpers;
5895 MenuList& items = _control_point_context_menu.items ();
5898 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5899 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5900 if (!can_remove_control_point (item)) {
5901 items.back().set_sensitive (false);
5904 _control_point_context_menu.popup (event->button.button, event->button.time);
5908 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5910 using namespace Menu_Helpers;
5912 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5917 /* We need to get the selection here and pass it to the operations, since
5918 popping up the menu will cause a region leave event which clears
5919 entered_regionview. */
5921 MidiRegionView& mrv = note->region_view();
5922 const RegionSelection rs = get_regions_from_selection_and_entered ();
5923 const uint32_t sel_size = mrv.selection_size ();
5925 MenuList& items = _note_context_menu.items();
5929 items.push_back(MenuElem(_("Delete"),
5930 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5933 items.push_back(MenuElem(_("Edit..."),
5934 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5935 if (sel_size != 1) {
5936 items.back().set_sensitive (false);
5939 items.push_back(MenuElem(_("Transpose..."),
5940 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5943 items.push_back(MenuElem(_("Legatize"),
5944 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5946 items.back().set_sensitive (false);
5949 items.push_back(MenuElem(_("Quantize..."),
5950 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5952 items.push_back(MenuElem(_("Remove Overlap"),
5953 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5955 items.back().set_sensitive (false);
5958 items.push_back(MenuElem(_("Transform..."),
5959 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5961 _note_context_menu.popup (event->button.button, event->button.time);
5965 Editor::zoom_vertical_modifier_released()
5967 _stepping_axis_view = 0;
5971 Editor::ui_parameter_changed (string parameter)
5973 if (parameter == "icon-set") {
5974 while (!_cursor_stack.empty()) {
5975 _cursor_stack.pop_back();
5977 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5978 _cursor_stack.push_back(_cursors->grabber);
5979 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
5980 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
5982 } else if (parameter == "draggable-playhead") {
5983 if (_verbose_cursor) {
5984 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5990 Editor::use_own_window (bool and_fill_it)
5992 bool new_window = !own_window();
5994 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5996 if (win && new_window) {
5997 win->set_name ("EditorWindow");
5999 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
6001 // win->signal_realize().connect (*this, &Editor::on_realize);
6002 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
6003 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
6004 win->set_data ("ardour-bindings", bindings);
6009 DisplaySuspender ds;
6010 contents().show_all ();
6012 /* XXX: this is a bit unfortunate; it would probably
6013 be nicer if we could just call show () above rather
6014 than needing the show_all ()
6017 /* re-hide stuff if necessary */
6018 editor_list_button_toggled ();
6019 parameter_changed ("show-summary");
6020 parameter_changed ("show-group-tabs");
6021 parameter_changed ("show-zoom-tools");
6023 /* now reset all audio_time_axis heights, because widgets might need
6029 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6030 tv = (static_cast<TimeAxisView*>(*i));
6031 tv->reset_height ();
6034 if (current_mixer_strip) {
6035 current_mixer_strip->hide_things ();
6036 current_mixer_strip->parameter_changed ("mixer-element-visibility");