2 Copyright (C) 2000-2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* Note: public Editor methods are documented in public_editor.h */
30 #include "ardour_ui.h"
32 * ardour_ui.h include was moved to the top of the list
33 * due to a conflicting definition of 'Style' between
34 * Apple's MacTypes.h and BarController.
37 #include <boost/none.hpp>
39 #include <sigc++/bind.h>
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
48 #include "pbd/timersub.h"
50 #include <glibmm/miscutils.h>
51 #include <glibmm/uriutils.h>
52 #include <gtkmm/image.h>
53 #include <gdkmm/color.h>
54 #include <gdkmm/bitmap.h>
56 #include <gtkmm/menu.h>
57 #include <gtkmm/menuitem.h>
59 #include "gtkmm2ext/bindings.h"
60 #include "gtkmm2ext/grouped_buttons.h"
61 #include "gtkmm2ext/gtk_ui.h"
62 #include <gtkmm2ext/keyboard.h>
63 #include "gtkmm2ext/utils.h"
64 #include "gtkmm2ext/window_title.h"
65 #include "gtkmm2ext/choice.h"
66 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
68 #include "ardour/analysis_graph.h"
69 #include "ardour/audio_track.h"
70 #include "ardour/audioengine.h"
71 #include "ardour/audioregion.h"
72 #include "ardour/lmath.h"
73 #include "ardour/location.h"
74 #include "ardour/profile.h"
75 #include "ardour/route_group.h"
76 #include "ardour/session_playlists.h"
77 #include "ardour/tempo.h"
78 #include "ardour/utils.h"
80 #include "canvas/debug.h"
81 #include "canvas/text.h"
83 #include "control_protocol/control_protocol.h"
86 #include "analysis_window.h"
87 #include "audio_clock.h"
88 #include "audio_region_view.h"
89 #include "audio_streamview.h"
90 #include "audio_time_axis.h"
91 #include "automation_time_axis.h"
92 #include "bundle_manager.h"
93 #include "crossfade_edit.h"
97 #include "editor_cursors.h"
98 #include "editor_drag.h"
99 #include "editor_group_tabs.h"
100 #include "editor_locations.h"
101 #include "editor_regions.h"
102 #include "editor_route_groups.h"
103 #include "editor_routes.h"
104 #include "editor_snapshots.h"
105 #include "editor_summary.h"
106 #include "export_report.h"
107 #include "global_port_matrix.h"
108 #include "gui_object.h"
109 #include "gui_thread.h"
110 #include "keyboard.h"
111 #include "keyeditor.h"
112 #include "luainstance.h"
114 #include "midi_region_view.h"
115 #include "midi_time_axis.h"
116 #include "mixer_strip.h"
117 #include "mixer_ui.h"
118 #include "mouse_cursors.h"
119 #include "note_base.h"
120 #include "playlist_selector.h"
121 #include "public_editor.h"
122 #include "quantize_dialog.h"
123 #include "region_layering_order_editor.h"
124 #include "rgb_macros.h"
125 #include "rhythm_ferret.h"
126 #include "selection.h"
127 #include "simple_progress_dialog.h"
129 #include "tempo_lines.h"
130 #include "time_axis_view.h"
132 #include "tooltips.h"
133 #include "ui_config.h"
135 #include "verbose_cursor.h"
140 using namespace ARDOUR;
141 using namespace ARDOUR_UI_UTILS;
144 using namespace Glib;
145 using namespace Gtkmm2ext;
146 using namespace Editing;
148 using PBD::internationalize;
150 using Gtkmm2ext::Keyboard;
152 double Editor::timebar_height = 15.0;
154 static const gchar *_snap_type_strings[] = {
188 static const gchar *_snap_mode_strings[] = {
195 static const gchar *_edit_point_strings[] = {
202 static const gchar *_edit_mode_strings[] = {
210 static const gchar *_zoom_focus_strings[] = {
220 #ifdef USE_RUBBERBAND
221 static const gchar *_rb_opt_strings[] = {
224 N_("Balanced multitimbral mixture"),
225 N_("Unpitched percussion with stable notes"),
226 N_("Crisp monophonic instrumental"),
227 N_("Unpitched solo percussion"),
228 N_("Resample without preserving pitch"),
233 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
236 pane_size_watcher (Paned* pane)
238 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
242 Quartz: impossible to access
244 so stop that by preventing it from ever getting too narrow. 35
245 pixels is basically a rough guess at the tab width.
250 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
252 gint pos = pane->get_position ();
254 if (pos > max_width_of_lhs) {
255 pane->set_position (max_width_of_lhs);
260 : PublicEditor (global_hpacker)
261 , editor_mixer_strip_width (Wide)
262 , constructed (false)
263 , _playlist_selector (0)
264 , no_save_visual (false)
266 , samples_per_pixel (2048)
267 , zoom_focus (ZoomFocusPlayhead)
268 , mouse_mode (MouseObject)
269 , pre_internal_snap_type (SnapToBeat)
270 , pre_internal_snap_mode (SnapOff)
271 , internal_snap_type (SnapToBeat)
272 , internal_snap_mode (SnapOff)
273 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
274 , _notebook_shrunk (false)
275 , location_marker_color (0)
276 , location_range_color (0)
277 , location_loop_color (0)
278 , location_punch_color (0)
279 , location_cd_marker_color (0)
281 , _show_marker_lines (false)
282 , clicked_axisview (0)
283 , clicked_routeview (0)
284 , clicked_regionview (0)
285 , clicked_selection (0)
286 , clicked_control_point (0)
287 , button_release_can_deselect (true)
288 , _mouse_changed_selection (false)
289 , region_edit_menu_split_item (0)
290 , region_edit_menu_split_multichannel_item (0)
291 , track_region_edit_playlist_menu (0)
292 , track_edit_playlist_submenu (0)
293 , track_selection_edit_playlist_submenu (0)
294 , _popup_region_menu_item (0)
296 , _track_canvas_viewport (0)
297 , within_track_canvas (false)
298 , _verbose_cursor (0)
302 , range_marker_group (0)
303 , transport_marker_group (0)
304 , cd_marker_group (0)
305 , _time_markers_group (0)
306 , hv_scroll_group (0)
308 , cursor_scroll_group (0)
309 , no_scroll_group (0)
310 , _trackview_group (0)
311 , _drag_motion_group (0)
312 , _canvas_drop_zone (0)
313 , no_ruler_shown_update (false)
314 , ruler_grabbed_widget (0)
316 , minsec_mark_interval (0)
317 , minsec_mark_modulo (0)
319 , timecode_mark_modulo (0)
320 , timecode_nmarks (0)
321 , _samples_ruler_interval (0)
324 , bbt_bar_helper_on (0)
325 , bbt_accent_modulo (0)
330 , visible_timebars (0)
331 , editor_ruler_menu (0)
335 , range_marker_bar (0)
336 , transport_marker_bar (0)
338 , minsec_label (_("Mins:Secs"))
339 , bbt_label (_("Bars:Beats"))
340 , timecode_label (_("Timecode"))
341 , samples_label (_("Samples"))
342 , tempo_label (_("Tempo"))
343 , meter_label (_("Meter"))
344 , mark_label (_("Location Markers"))
345 , range_mark_label (_("Range Markers"))
346 , transport_mark_label (_("Loop/Punch Ranges"))
347 , cd_mark_label (_("CD Markers"))
348 , videotl_label (_("Video Timeline"))
350 , playhead_cursor (0)
351 , edit_packer (4, 4, true)
352 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
353 , horizontal_adjustment (0.0, 0.0, 1e16)
354 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
355 , controls_layout (unused_adjustment, vertical_adjustment)
356 , _scroll_callbacks (0)
357 , _visible_canvas_width (0)
358 , _visible_canvas_height (0)
359 , _full_canvas_height (0)
360 , edit_controls_left_menu (0)
361 , edit_controls_right_menu (0)
362 , last_update_frame (0)
363 , cut_buffer_start (0)
364 , cut_buffer_length (0)
365 , button_bindings (0)
369 , current_interthread_info (0)
370 , analysis_window (0)
371 , select_new_marker (false)
373 , scrubbing_direction (0)
374 , scrub_reversals (0)
375 , scrub_reverse_distance (0)
376 , have_pending_keyboard_selection (false)
377 , pending_keyboard_selection_start (0)
378 , _snap_type (SnapToBeat)
379 , _snap_mode (SnapOff)
380 , snap_threshold (5.0)
381 , ignore_gui_changes (false)
382 , _drags (new DragManager (this))
384 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
385 , _dragging_playhead (false)
386 , _dragging_edit_point (false)
387 , _show_measures (true)
388 , _follow_playhead (true)
389 , _stationary_playhead (false)
392 , global_rect_group (0)
393 , time_line_group (0)
394 , tempo_or_meter_marker_menu (0)
396 , range_marker_menu (0)
397 , transport_marker_menu (0)
398 , new_transport_marker_menu (0)
400 , marker_menu_item (0)
401 , bbt_beat_subdivision (4)
402 , _visible_track_count (-1)
403 , toolbar_selection_clock_table (2,3)
404 , automation_mode_button (_("mode"))
405 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
406 , selection (new Selection (this))
407 , cut_buffer (new Selection (this))
408 , _selection_memento (new SelectionMemento())
409 , _all_region_actions_sensitized (false)
410 , _ignore_region_action (false)
411 , _last_region_menu_was_main (false)
412 , _ignore_follow_edits (false)
413 , cd_marker_bar_drag_rect (0)
414 , range_bar_drag_rect (0)
415 , transport_bar_drag_rect (0)
416 , transport_bar_range_rect (0)
417 , transport_bar_preroll_rect (0)
418 , transport_bar_postroll_rect (0)
419 , transport_loop_range_rect (0)
420 , transport_punch_range_rect (0)
421 , transport_punchin_line (0)
422 , transport_punchout_line (0)
423 , transport_preroll_rect (0)
424 , transport_postroll_rect (0)
426 , rubberband_rect (0)
432 , autoscroll_horizontal_allowed (false)
433 , autoscroll_vertical_allowed (false)
435 , autoscroll_widget (0)
436 , show_gain_after_trim (false)
437 , selection_op_cmd_depth (0)
438 , selection_op_history_it (0)
439 , no_save_instant (false)
441 , current_mixer_strip (0)
442 , show_editor_mixer_when_tracks_arrive (false)
443 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
444 , current_stepping_trackview (0)
445 , last_track_height_step_timestamp (0)
447 , entered_regionview (0)
448 , clear_entered_track (false)
449 , _edit_point (EditAtMouse)
450 , meters_running (false)
452 , _have_idled (false)
453 , resize_idle_id (-1)
454 , _pending_resize_amount (0)
455 , _pending_resize_view (0)
456 , _pending_locate_request (false)
457 , _pending_initial_locate (false)
461 , layering_order_editor (0)
462 , _last_cut_copy_source_track (0)
463 , _region_selection_change_updates_region_list (true)
465 , _following_mixer_selection (false)
466 , _control_point_toggled_on_press (false)
467 , _stepping_axis_view (0)
468 , quantize_dialog (0)
469 , _main_menu_disabler (0)
470 , myactions (X_("editor"))
472 /* we are a singleton */
474 PublicEditor::_instance = this;
478 last_event_time.tv_sec = 0;
479 last_event_time.tv_usec = 0;
481 selection_op_history.clear();
484 snap_type_strings = I18N (_snap_type_strings);
485 snap_mode_strings = I18N (_snap_mode_strings);
486 zoom_focus_strings = I18N (_zoom_focus_strings);
487 edit_mode_strings = I18N (_edit_mode_strings);
488 edit_point_strings = I18N (_edit_point_strings);
489 #ifdef USE_RUBBERBAND
490 rb_opt_strings = I18N (_rb_opt_strings);
494 build_edit_mode_menu();
495 build_zoom_focus_menu();
496 build_track_count_menu();
497 build_snap_mode_menu();
498 build_snap_type_menu();
499 build_edit_point_menu();
501 location_marker_color = UIConfiguration::instance().color ("location marker");
502 location_range_color = UIConfiguration::instance().color ("location range");
503 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
504 location_loop_color = UIConfiguration::instance().color ("location loop");
505 location_punch_color = UIConfiguration::instance().color ("location punch");
507 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
509 TimeAxisView::setup_sizes ();
510 ArdourMarker::setup_sizes (timebar_height);
512 bbt_label.set_name ("EditorRulerLabel");
513 bbt_label.set_size_request (-1, (int)timebar_height);
514 bbt_label.set_alignment (1.0, 0.5);
515 bbt_label.set_padding (5,0);
517 bbt_label.set_no_show_all();
518 minsec_label.set_name ("EditorRulerLabel");
519 minsec_label.set_size_request (-1, (int)timebar_height);
520 minsec_label.set_alignment (1.0, 0.5);
521 minsec_label.set_padding (5,0);
522 minsec_label.hide ();
523 minsec_label.set_no_show_all();
524 timecode_label.set_name ("EditorRulerLabel");
525 timecode_label.set_size_request (-1, (int)timebar_height);
526 timecode_label.set_alignment (1.0, 0.5);
527 timecode_label.set_padding (5,0);
528 timecode_label.hide ();
529 timecode_label.set_no_show_all();
530 samples_label.set_name ("EditorRulerLabel");
531 samples_label.set_size_request (-1, (int)timebar_height);
532 samples_label.set_alignment (1.0, 0.5);
533 samples_label.set_padding (5,0);
534 samples_label.hide ();
535 samples_label.set_no_show_all();
537 tempo_label.set_name ("EditorRulerLabel");
538 tempo_label.set_size_request (-1, (int)timebar_height);
539 tempo_label.set_alignment (1.0, 0.5);
540 tempo_label.set_padding (5,0);
542 tempo_label.set_no_show_all();
544 meter_label.set_name ("EditorRulerLabel");
545 meter_label.set_size_request (-1, (int)timebar_height);
546 meter_label.set_alignment (1.0, 0.5);
547 meter_label.set_padding (5,0);
549 meter_label.set_no_show_all();
551 if (Profile->get_trx()) {
552 mark_label.set_text (_("Markers"));
554 mark_label.set_name ("EditorRulerLabel");
555 mark_label.set_size_request (-1, (int)timebar_height);
556 mark_label.set_alignment (1.0, 0.5);
557 mark_label.set_padding (5,0);
559 mark_label.set_no_show_all();
561 cd_mark_label.set_name ("EditorRulerLabel");
562 cd_mark_label.set_size_request (-1, (int)timebar_height);
563 cd_mark_label.set_alignment (1.0, 0.5);
564 cd_mark_label.set_padding (5,0);
565 cd_mark_label.hide();
566 cd_mark_label.set_no_show_all();
568 videotl_bar_height = 4;
569 videotl_label.set_name ("EditorRulerLabel");
570 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
571 videotl_label.set_alignment (1.0, 0.5);
572 videotl_label.set_padding (5,0);
573 videotl_label.hide();
574 videotl_label.set_no_show_all();
576 range_mark_label.set_name ("EditorRulerLabel");
577 range_mark_label.set_size_request (-1, (int)timebar_height);
578 range_mark_label.set_alignment (1.0, 0.5);
579 range_mark_label.set_padding (5,0);
580 range_mark_label.hide();
581 range_mark_label.set_no_show_all();
583 transport_mark_label.set_name ("EditorRulerLabel");
584 transport_mark_label.set_size_request (-1, (int)timebar_height);
585 transport_mark_label.set_alignment (1.0, 0.5);
586 transport_mark_label.set_padding (5,0);
587 transport_mark_label.hide();
588 transport_mark_label.set_no_show_all();
590 initialize_canvas ();
592 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
594 _summary = new EditorSummary (this);
596 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
597 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
599 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
601 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
602 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
604 edit_controls_vbox.set_spacing (0);
605 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
606 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
608 HBox* h = manage (new HBox);
609 _group_tabs = new EditorGroupTabs (this);
610 if (!ARDOUR::Profile->get_trx()) {
611 h->pack_start (*_group_tabs, PACK_SHRINK);
613 h->pack_start (edit_controls_vbox);
614 controls_layout.add (*h);
616 controls_layout.set_name ("EditControlsBase");
617 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
618 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
619 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
621 _cursors = new MouseCursors;
622 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
623 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
625 /* Push default cursor to ever-present bottom of cursor stack. */
626 push_canvas_cursor(_cursors->grabber);
628 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
630 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
631 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
632 pad_line_1->set_outline_color (0xFF0000FF);
638 edit_packer.set_col_spacings (0);
639 edit_packer.set_row_spacings (0);
640 edit_packer.set_homogeneous (false);
641 edit_packer.set_border_width (0);
642 edit_packer.set_name ("EditorWindow");
644 time_bars_event_box.add (time_bars_vbox);
645 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
646 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
648 /* labels for the time bars */
649 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
651 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
653 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
655 bottom_hbox.set_border_width (2);
656 bottom_hbox.set_spacing (3);
658 _route_groups = new EditorRouteGroups (this);
659 _routes = new EditorRoutes (this);
660 _regions = new EditorRegions (this);
661 _snapshots = new EditorSnapshots (this);
662 _locations = new EditorLocations (this);
664 /* these are static location signals */
666 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
667 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
668 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
670 add_notebook_page (_("Regions"), _regions->widget ());
671 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
672 add_notebook_page (_("Snapshots"), _snapshots->widget ());
673 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
674 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
676 _the_notebook.set_show_tabs (true);
677 _the_notebook.set_scrollable (true);
678 _the_notebook.popup_disable ();
679 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
680 _the_notebook.show_all ();
682 _notebook_shrunk = false;
684 editor_summary_pane.pack1(edit_packer);
686 Button* summary_arrows_left_left = manage (new Button);
687 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
688 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
689 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
691 Button* summary_arrows_left_right = manage (new Button);
692 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
693 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
694 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
696 VBox* summary_arrows_left = manage (new VBox);
697 summary_arrows_left->pack_start (*summary_arrows_left_left);
698 summary_arrows_left->pack_start (*summary_arrows_left_right);
700 Button* summary_arrows_right_up = manage (new Button);
701 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
702 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
703 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
705 Button* summary_arrows_right_down = manage (new Button);
706 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
707 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
708 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
710 VBox* summary_arrows_right = manage (new VBox);
711 summary_arrows_right->pack_start (*summary_arrows_right_up);
712 summary_arrows_right->pack_start (*summary_arrows_right_down);
714 Frame* summary_frame = manage (new Frame);
715 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
717 summary_frame->add (*_summary);
718 summary_frame->show ();
720 _summary_hbox.pack_start (*summary_arrows_left, false, false);
721 _summary_hbox.pack_start (*summary_frame, true, true);
722 _summary_hbox.pack_start (*summary_arrows_right, false, false);
724 if (!ARDOUR::Profile->get_trx()) {
725 editor_summary_pane.pack2 (_summary_hbox);
728 edit_pane.pack1 (editor_summary_pane, true, true);
729 if (!ARDOUR::Profile->get_trx()) {
730 edit_pane.pack2 (_the_notebook, false, true);
733 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
735 /* XXX: editor_summary_pane might need similar to the edit_pane */
737 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
739 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
740 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
742 top_hbox.pack_start (toolbar_frame);
744 HBox *hbox = manage (new HBox);
745 hbox->pack_start (edit_pane, true, true);
747 global_vpacker.pack_start (top_hbox, false, false);
748 global_vpacker.pack_start (*hbox, true, true);
749 global_hpacker.pack_start (global_vpacker, true, true);
751 /* need to show the "contents" widget so that notebook will show if tab is switched to
754 global_hpacker.show ();
756 /* register actions now so that set_state() can find them and set toggles/checks etc */
763 _playlist_selector = new PlaylistSelector();
764 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
766 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
770 nudge_forward_button.set_name ("nudge button");
771 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
773 nudge_backward_button.set_name ("nudge button");
774 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
776 fade_context_menu.set_name ("ArdourContextMenu");
778 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
780 /* allow external control surfaces/protocols to do various things */
782 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
783 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
784 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
785 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
786 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
787 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
788 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
789 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
790 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
791 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
792 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
793 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
794 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
795 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
797 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
798 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
799 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
800 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
801 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
803 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
805 /* problematic: has to return a value and thus cannot be x-thread */
807 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
809 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
810 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
812 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
814 _ignore_region_action = false;
815 _last_region_menu_was_main = false;
816 _popup_region_menu_item = 0;
818 _ignore_follow_edits = false;
820 _show_marker_lines = false;
822 /* Button bindings */
824 button_bindings = new Bindings ("editor-mouse");
826 XMLNode* node = button_settings();
828 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
829 button_bindings->load_operation (**i);
835 /* grab current parameter state */
836 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
837 UIConfiguration::instance().map_parameters (pc);
839 setup_fade_images ();
841 LuaInstance::instance(); // instantiate
842 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &Editor::set_script_action_name));
849 delete button_bindings;
851 delete _route_groups;
852 delete _track_canvas_viewport;
855 delete quantize_dialog;
861 delete _playlist_selector;
863 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
869 Editor::button_settings () const
871 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
872 XMLNode* node = find_named_node (*settings, X_("Buttons"));
875 node = new XMLNode (X_("Buttons"));
882 Editor::get_smart_mode () const
884 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
888 Editor::catch_vanishing_regionview (RegionView *rv)
890 /* note: the selection will take care of the vanishing
891 audioregionview by itself.
894 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
898 if (clicked_regionview == rv) {
899 clicked_regionview = 0;
902 if (entered_regionview == rv) {
903 set_entered_regionview (0);
906 if (!_all_region_actions_sensitized) {
907 sensitize_all_region_actions (true);
912 Editor::set_entered_regionview (RegionView* rv)
914 if (rv == entered_regionview) {
918 if (entered_regionview) {
919 entered_regionview->exited ();
922 entered_regionview = rv;
924 if (entered_regionview != 0) {
925 entered_regionview->entered ();
928 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
929 /* This RegionView entry might have changed what region actions
930 are allowed, so sensitize them all in case a key is pressed.
932 sensitize_all_region_actions (true);
937 Editor::set_entered_track (TimeAxisView* tav)
940 entered_track->exited ();
946 entered_track->entered ();
951 Editor::instant_save ()
953 if (!constructed || !ARDOUR_UI::instance()->session_loaded || no_save_instant) {
958 _session->add_instant_xml(get_state());
960 Config->add_instant_xml(get_state());
965 Editor::control_vertical_zoom_in_all ()
967 tav_zoom_smooth (false, true);
971 Editor::control_vertical_zoom_out_all ()
973 tav_zoom_smooth (true, true);
977 Editor::control_vertical_zoom_in_selected ()
979 tav_zoom_smooth (false, false);
983 Editor::control_vertical_zoom_out_selected ()
985 tav_zoom_smooth (true, false);
989 Editor::control_view (uint32_t view)
991 goto_visual_state (view);
995 Editor::control_unselect ()
997 selection->clear_tracks ();
1001 Editor::control_select (uint32_t rid, Selection::Operation op)
1003 /* handles the (static) signal from the ControlProtocol class that
1004 * requests setting the selected track to a given RID
1011 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1017 TimeAxisView* tav = axis_view_from_route (r);
1021 case Selection::Add:
1022 selection->add (tav);
1024 case Selection::Toggle:
1025 selection->toggle (tav);
1027 case Selection::Extend:
1029 case Selection::Set:
1030 selection->set (tav);
1034 selection->clear_tracks ();
1039 Editor::control_step_tracks_up ()
1041 scroll_tracks_up_line ();
1045 Editor::control_step_tracks_down ()
1047 scroll_tracks_down_line ();
1051 Editor::control_scroll (float fraction)
1053 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1059 double step = fraction * current_page_samples();
1062 _control_scroll_target is an optional<T>
1064 it acts like a pointer to an framepos_t, with
1065 a operator conversion to boolean to check
1066 that it has a value could possibly use
1067 playhead_cursor->current_frame to store the
1068 value and a boolean in the class to know
1069 when it's out of date
1072 if (!_control_scroll_target) {
1073 _control_scroll_target = _session->transport_frame();
1074 _dragging_playhead = true;
1077 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1078 *_control_scroll_target = 0;
1079 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1080 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1082 *_control_scroll_target += (framepos_t) trunc (step);
1085 /* move visuals, we'll catch up with it later */
1087 playhead_cursor->set_position (*_control_scroll_target);
1088 UpdateAllTransportClocks (*_control_scroll_target);
1090 if (*_control_scroll_target > (current_page_samples() / 2)) {
1091 /* try to center PH in window */
1092 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1098 Now we do a timeout to actually bring the session to the right place
1099 according to the playhead. This is to avoid reading disk buffers on every
1100 call to control_scroll, which is driven by ScrollTimeline and therefore
1101 probably by a control surface wheel which can generate lots of events.
1103 /* cancel the existing timeout */
1105 control_scroll_connection.disconnect ();
1107 /* add the next timeout */
1109 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1113 Editor::deferred_control_scroll (framepos_t /*target*/)
1115 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1116 // reset for next stream
1117 _control_scroll_target = boost::none;
1118 _dragging_playhead = false;
1123 Editor::access_action (std::string action_group, std::string action_item)
1129 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1132 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1140 Editor::on_realize ()
1144 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1145 start_lock_event_timing ();
1150 Editor::start_lock_event_timing ()
1152 /* check if we should lock the GUI every 30 seconds */
1154 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1158 Editor::generic_event_handler (GdkEvent* ev)
1161 case GDK_BUTTON_PRESS:
1162 case GDK_BUTTON_RELEASE:
1163 case GDK_MOTION_NOTIFY:
1165 case GDK_KEY_RELEASE:
1166 if (contents().is_mapped()) {
1167 gettimeofday (&last_event_time, 0);
1171 case GDK_LEAVE_NOTIFY:
1172 switch (ev->crossing.detail) {
1173 case GDK_NOTIFY_UNKNOWN:
1174 case GDK_NOTIFY_INFERIOR:
1175 case GDK_NOTIFY_ANCESTOR:
1177 case GDK_NOTIFY_VIRTUAL:
1178 case GDK_NOTIFY_NONLINEAR:
1179 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1180 /* leaving window, so reset focus, thus ending any and
1181 all text entry operations.
1183 reset_focus (&contents());
1196 Editor::lock_timeout_callback ()
1198 struct timeval now, delta;
1200 gettimeofday (&now, 0);
1202 timersub (&now, &last_event_time, &delta);
1204 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1206 /* don't call again. Returning false will effectively
1207 disconnect us from the timer callback.
1209 unlock() will call start_lock_event_timing() to get things
1219 Editor::map_position_change (framepos_t frame)
1221 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1223 if (_session == 0) {
1227 if (_follow_playhead) {
1228 center_screen (frame);
1231 playhead_cursor->set_position (frame);
1235 Editor::center_screen (framepos_t frame)
1237 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1239 /* if we're off the page, then scroll.
1242 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1243 center_screen_internal (frame, page);
1248 Editor::center_screen_internal (framepos_t frame, float page)
1253 frame -= (framepos_t) page;
1258 reset_x_origin (frame);
1263 Editor::update_title ()
1265 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1267 if (!own_window()) {
1272 bool dirty = _session->dirty();
1274 string session_name;
1276 if (_session->snap_name() != _session->name()) {
1277 session_name = _session->snap_name();
1279 session_name = _session->name();
1283 session_name = "*" + session_name;
1286 WindowTitle title(session_name);
1287 title += S_("Window|Editor");
1288 title += Glib::get_application_name();
1289 own_window()->set_title (title.get_string());
1291 /* ::session_going_away() will have taken care of it */
1296 Editor::set_session (Session *t)
1298 SessionHandlePtr::set_session (t);
1304 _playlist_selector->set_session (_session);
1305 nudge_clock->set_session (_session);
1306 _summary->set_session (_session);
1307 _group_tabs->set_session (_session);
1308 _route_groups->set_session (_session);
1309 _regions->set_session (_session);
1310 _snapshots->set_session (_session);
1311 _routes->set_session (_session);
1312 _locations->set_session (_session);
1314 if (rhythm_ferret) {
1315 rhythm_ferret->set_session (_session);
1318 if (analysis_window) {
1319 analysis_window->set_session (_session);
1323 sfbrowser->set_session (_session);
1326 compute_fixed_ruler_scale ();
1328 /* Make sure we have auto loop and auto punch ranges */
1330 Location* loc = _session->locations()->auto_loop_location();
1332 loc->set_name (_("Loop"));
1335 loc = _session->locations()->auto_punch_location();
1338 loc->set_name (_("Punch"));
1341 refresh_location_display ();
1343 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1344 the selected Marker; this needs the LocationMarker list to be available.
1346 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1347 set_state (*node, Stateful::loading_state_version);
1349 /* catch up with the playhead */
1351 _session->request_locate (playhead_cursor->current_frame ());
1352 _pending_initial_locate = true;
1356 /* These signals can all be emitted by a non-GUI thread. Therefore the
1357 handlers for them must not attempt to directly interact with the GUI,
1358 but use PBD::Signal<T>::connect() which accepts an event loop
1359 ("context") where the handler will be asked to run.
1362 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1363 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1364 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1365 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1366 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1367 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1368 _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::marker_position_changed, this), gui_context());
1369 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1370 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1371 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1372 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1373 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1374 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1375 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1377 playhead_cursor->show ();
1379 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1380 Config->map_parameters (pc);
1381 _session->config.map_parameters (pc);
1383 restore_ruler_visibility ();
1384 //tempo_map_changed (PropertyChange (0));
1385 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1387 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1388 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1391 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1392 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1395 switch (_snap_type) {
1396 case SnapToRegionStart:
1397 case SnapToRegionEnd:
1398 case SnapToRegionSync:
1399 case SnapToRegionBoundary:
1400 build_region_boundary_cache ();
1407 /* register for undo history */
1408 _session->register_with_memento_command_factory(id(), this);
1409 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1411 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1413 LuaInstance::instance()->set_session(_session);
1415 start_updating_meters ();
1419 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1421 if (a->get_name() == "RegionMenu") {
1422 /* When the main menu's region menu is opened, we setup the actions so that they look right
1423 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1424 so we resensitize all region actions when the entered regionview or the region selection
1425 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1426 happens after the region context menu is opened. So we set a flag here, too.
1430 sensitize_the_right_region_actions ();
1431 _last_region_menu_was_main = true;
1436 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1438 using namespace Menu_Helpers;
1440 void (Editor::*emf)(FadeShape);
1441 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1444 images = &_xfade_in_images;
1445 emf = &Editor::set_fade_in_shape;
1447 images = &_xfade_out_images;
1448 emf = &Editor::set_fade_out_shape;
1453 _("Linear (for highly correlated material)"),
1454 *(*images)[FadeLinear],
1455 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1459 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1463 _("Constant power"),
1464 *(*images)[FadeConstantPower],
1465 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1468 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1473 *(*images)[FadeSymmetric],
1474 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1478 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1483 *(*images)[FadeSlow],
1484 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1487 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1492 *(*images)[FadeFast],
1493 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1496 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1499 /** Pop up a context menu for when the user clicks on a start crossfade */
1501 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1503 using namespace Menu_Helpers;
1504 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1509 MenuList& items (xfade_in_context_menu.items());
1512 if (arv->audio_region()->fade_in_active()) {
1513 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1515 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1518 items.push_back (SeparatorElem());
1519 fill_xfade_menu (items, true);
1521 xfade_in_context_menu.popup (button, time);
1524 /** Pop up a context menu for when the user clicks on an end crossfade */
1526 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1528 using namespace Menu_Helpers;
1529 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1534 MenuList& items (xfade_out_context_menu.items());
1537 if (arv->audio_region()->fade_out_active()) {
1538 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1540 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1543 items.push_back (SeparatorElem());
1544 fill_xfade_menu (items, false);
1546 xfade_out_context_menu.popup (button, time);
1550 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1552 using namespace Menu_Helpers;
1553 Menu* (Editor::*build_menu_function)();
1556 switch (item_type) {
1558 case RegionViewName:
1559 case RegionViewNameHighlight:
1560 case LeftFrameHandle:
1561 case RightFrameHandle:
1562 if (with_selection) {
1563 build_menu_function = &Editor::build_track_selection_context_menu;
1565 build_menu_function = &Editor::build_track_region_context_menu;
1570 if (with_selection) {
1571 build_menu_function = &Editor::build_track_selection_context_menu;
1573 build_menu_function = &Editor::build_track_context_menu;
1578 if (clicked_routeview->track()) {
1579 build_menu_function = &Editor::build_track_context_menu;
1581 build_menu_function = &Editor::build_track_bus_context_menu;
1586 /* probably shouldn't happen but if it does, we don't care */
1590 menu = (this->*build_menu_function)();
1591 menu->set_name ("ArdourContextMenu");
1593 /* now handle specific situations */
1595 switch (item_type) {
1597 case RegionViewName:
1598 case RegionViewNameHighlight:
1599 case LeftFrameHandle:
1600 case RightFrameHandle:
1601 if (!with_selection) {
1602 if (region_edit_menu_split_item) {
1603 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1604 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1606 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1609 if (region_edit_menu_split_multichannel_item) {
1610 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1611 region_edit_menu_split_multichannel_item->set_sensitive (true);
1613 region_edit_menu_split_multichannel_item->set_sensitive (false);
1626 /* probably shouldn't happen but if it does, we don't care */
1630 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1632 /* Bounce to disk */
1634 using namespace Menu_Helpers;
1635 MenuList& edit_items = menu->items();
1637 edit_items.push_back (SeparatorElem());
1639 switch (clicked_routeview->audio_track()->freeze_state()) {
1640 case AudioTrack::NoFreeze:
1641 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1644 case AudioTrack::Frozen:
1645 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1648 case AudioTrack::UnFrozen:
1649 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1655 if (item_type == StreamItem && clicked_routeview) {
1656 clicked_routeview->build_underlay_menu(menu);
1659 /* When the region menu is opened, we setup the actions so that they look right
1662 sensitize_the_right_region_actions ();
1663 _last_region_menu_was_main = false;
1665 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1666 menu->popup (button, time);
1670 Editor::build_track_context_menu ()
1672 using namespace Menu_Helpers;
1674 MenuList& edit_items = track_context_menu.items();
1677 add_dstream_context_items (edit_items);
1678 return &track_context_menu;
1682 Editor::build_track_bus_context_menu ()
1684 using namespace Menu_Helpers;
1686 MenuList& edit_items = track_context_menu.items();
1689 add_bus_context_items (edit_items);
1690 return &track_context_menu;
1694 Editor::build_track_region_context_menu ()
1696 using namespace Menu_Helpers;
1697 MenuList& edit_items = track_region_context_menu.items();
1700 /* we've just cleared the track region context menu, so the menu that these
1701 two items were on will have disappeared; stop them dangling.
1703 region_edit_menu_split_item = 0;
1704 region_edit_menu_split_multichannel_item = 0;
1706 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1709 boost::shared_ptr<Track> tr;
1710 boost::shared_ptr<Playlist> pl;
1712 if ((tr = rtv->track())) {
1713 add_region_context_items (edit_items, tr);
1717 add_dstream_context_items (edit_items);
1719 return &track_region_context_menu;
1723 Editor::loudness_analyze_region_selection ()
1728 Selection& s (PublicEditor::instance ().get_selection ());
1729 RegionSelection ars = s.regions;
1730 ARDOUR::AnalysisGraph ag (_session);
1731 framecnt_t total_work = 0;
1733 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1734 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1738 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1741 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1742 total_work += arv->region ()->length ();
1745 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1747 ag.set_total_frames (total_work);
1748 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1751 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1752 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1756 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1760 ag.analyze_region (ar);
1763 if (!ag.canceled ()) {
1764 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1770 Editor::loudness_analyze_range_selection ()
1775 Selection& s (PublicEditor::instance ().get_selection ());
1776 TimeSelection ts = s.time;
1777 ARDOUR::AnalysisGraph ag (_session);
1778 framecnt_t total_work = 0;
1780 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1781 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1785 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1789 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1790 total_work += j->length ();
1794 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1796 ag.set_total_frames (total_work);
1797 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1800 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1801 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1805 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1809 ag.analyze_range (rui->route (), pl, ts);
1812 if (!ag.canceled ()) {
1813 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1819 Editor::spectral_analyze_region_selection ()
1821 if (analysis_window == 0) {
1822 analysis_window = new AnalysisWindow();
1825 analysis_window->set_session(_session);
1827 analysis_window->show_all();
1830 analysis_window->set_regionmode();
1831 analysis_window->analyze();
1833 analysis_window->present();
1837 Editor::spectral_analyze_range_selection()
1839 if (analysis_window == 0) {
1840 analysis_window = new AnalysisWindow();
1843 analysis_window->set_session(_session);
1845 analysis_window->show_all();
1848 analysis_window->set_rangemode();
1849 analysis_window->analyze();
1851 analysis_window->present();
1855 Editor::build_track_selection_context_menu ()
1857 using namespace Menu_Helpers;
1858 MenuList& edit_items = track_selection_context_menu.items();
1859 edit_items.clear ();
1861 add_selection_context_items (edit_items);
1862 // edit_items.push_back (SeparatorElem());
1863 // add_dstream_context_items (edit_items);
1865 return &track_selection_context_menu;
1869 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1871 using namespace Menu_Helpers;
1873 /* OK, stick the region submenu at the top of the list, and then add
1877 RegionSelection rs = get_regions_from_selection_and_entered ();
1879 string::size_type pos = 0;
1880 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1882 /* we have to hack up the region name because "_" has a special
1883 meaning for menu titles.
1886 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1887 menu_item_name.replace (pos, 1, "__");
1891 if (_popup_region_menu_item == 0) {
1892 _popup_region_menu_item = new MenuItem (menu_item_name);
1893 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1894 _popup_region_menu_item->show ();
1896 _popup_region_menu_item->set_label (menu_item_name);
1899 /* No latering allowed in later is higher layering model */
1900 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1901 if (act && Config->get_layer_model() == LaterHigher) {
1902 act->set_sensitive (false);
1904 act->set_sensitive (true);
1907 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1909 edit_items.push_back (*_popup_region_menu_item);
1910 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1911 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1913 edit_items.push_back (SeparatorElem());
1916 /** Add context menu items relevant to selection ranges.
1917 * @param edit_items List to add the items to.
1920 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1922 using namespace Menu_Helpers;
1924 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1925 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1927 edit_items.push_back (SeparatorElem());
1928 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1930 edit_items.push_back (SeparatorElem());
1931 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1932 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1934 edit_items.push_back (SeparatorElem());
1936 edit_items.push_back (
1938 _("Move Range Start to Previous Region Boundary"),
1939 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1943 edit_items.push_back (
1945 _("Move Range Start to Next Region Boundary"),
1946 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1950 edit_items.push_back (
1952 _("Move Range End to Previous Region Boundary"),
1953 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1957 edit_items.push_back (
1959 _("Move Range End to Next Region Boundary"),
1960 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1964 edit_items.push_back (SeparatorElem());
1965 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1966 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1968 edit_items.push_back (SeparatorElem());
1969 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1971 edit_items.push_back (SeparatorElem());
1972 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1973 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1974 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1976 edit_items.push_back (SeparatorElem());
1977 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1979 edit_items.push_back (SeparatorElem());
1980 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1981 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1983 edit_items.push_back (SeparatorElem());
1984 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1985 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1986 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1987 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1988 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1989 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1990 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1996 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1998 using namespace Menu_Helpers;
2002 Menu *play_menu = manage (new Menu);
2003 MenuList& play_items = play_menu->items();
2004 play_menu->set_name ("ArdourContextMenu");
2006 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2007 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2008 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2009 play_items.push_back (SeparatorElem());
2010 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2012 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2016 Menu *select_menu = manage (new Menu);
2017 MenuList& select_items = select_menu->items();
2018 select_menu->set_name ("ArdourContextMenu");
2020 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2021 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2022 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2023 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2024 select_items.push_back (SeparatorElem());
2025 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2026 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2027 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2028 select_items.push_back (SeparatorElem());
2029 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2030 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2031 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2032 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2033 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2034 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2035 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2037 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2041 Menu *cutnpaste_menu = manage (new Menu);
2042 MenuList& cutnpaste_items = cutnpaste_menu->items();
2043 cutnpaste_menu->set_name ("ArdourContextMenu");
2045 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2046 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2047 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2049 cutnpaste_items.push_back (SeparatorElem());
2051 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2052 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2054 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2056 /* Adding new material */
2058 edit_items.push_back (SeparatorElem());
2059 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2060 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2064 Menu *nudge_menu = manage (new Menu());
2065 MenuList& nudge_items = nudge_menu->items();
2066 nudge_menu->set_name ("ArdourContextMenu");
2068 edit_items.push_back (SeparatorElem());
2069 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2070 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2071 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2072 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2074 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2078 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2080 using namespace Menu_Helpers;
2084 Menu *play_menu = manage (new Menu);
2085 MenuList& play_items = play_menu->items();
2086 play_menu->set_name ("ArdourContextMenu");
2088 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2089 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2090 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2094 Menu *select_menu = manage (new Menu);
2095 MenuList& select_items = select_menu->items();
2096 select_menu->set_name ("ArdourContextMenu");
2098 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2099 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2100 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2101 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2102 select_items.push_back (SeparatorElem());
2103 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2104 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2105 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2106 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2108 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2112 Menu *cutnpaste_menu = manage (new Menu);
2113 MenuList& cutnpaste_items = cutnpaste_menu->items();
2114 cutnpaste_menu->set_name ("ArdourContextMenu");
2116 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2117 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2118 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2120 Menu *nudge_menu = manage (new Menu());
2121 MenuList& nudge_items = nudge_menu->items();
2122 nudge_menu->set_name ("ArdourContextMenu");
2124 edit_items.push_back (SeparatorElem());
2125 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2126 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2127 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2128 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2130 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2134 Editor::snap_type() const
2140 Editor::snap_mode() const
2146 Editor::set_snap_to (SnapType st)
2148 unsigned int snap_ind = (unsigned int)st;
2150 if (internal_editing()) {
2151 internal_snap_type = st;
2153 pre_internal_snap_type = st;
2158 if (snap_ind > snap_type_strings.size() - 1) {
2160 _snap_type = (SnapType)snap_ind;
2163 string str = snap_type_strings[snap_ind];
2165 if (str != snap_type_selector.get_text()) {
2166 snap_type_selector.set_text (str);
2171 switch (_snap_type) {
2172 case SnapToBeatDiv128:
2173 case SnapToBeatDiv64:
2174 case SnapToBeatDiv32:
2175 case SnapToBeatDiv28:
2176 case SnapToBeatDiv24:
2177 case SnapToBeatDiv20:
2178 case SnapToBeatDiv16:
2179 case SnapToBeatDiv14:
2180 case SnapToBeatDiv12:
2181 case SnapToBeatDiv10:
2182 case SnapToBeatDiv8:
2183 case SnapToBeatDiv7:
2184 case SnapToBeatDiv6:
2185 case SnapToBeatDiv5:
2186 case SnapToBeatDiv4:
2187 case SnapToBeatDiv3:
2188 case SnapToBeatDiv2: {
2189 std::vector<TempoMap::BBTPoint> grid;
2190 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
2191 compute_bbt_ruler_scale (grid, leftmost_frame, leftmost_frame + current_page_samples());
2192 update_tempo_based_rulers (grid);
2196 case SnapToRegionStart:
2197 case SnapToRegionEnd:
2198 case SnapToRegionSync:
2199 case SnapToRegionBoundary:
2200 build_region_boundary_cache ();
2208 redisplay_tempo (false);
2210 SnapChanged (); /* EMIT SIGNAL */
2214 Editor::set_snap_mode (SnapMode mode)
2216 string str = snap_mode_strings[(int)mode];
2218 if (internal_editing()) {
2219 internal_snap_mode = mode;
2221 pre_internal_snap_mode = mode;
2226 if (str != snap_mode_selector.get_text ()) {
2227 snap_mode_selector.set_text (str);
2234 Editor::set_edit_point_preference (EditPoint ep, bool force)
2236 bool changed = (_edit_point != ep);
2239 if (Profile->get_mixbus())
2240 if (ep == EditAtSelectedMarker)
2241 ep = EditAtPlayhead;
2243 string str = edit_point_strings[(int)ep];
2244 if (str != edit_point_selector.get_text ()) {
2245 edit_point_selector.set_text (str);
2248 update_all_enter_cursors();
2250 if (!force && !changed) {
2254 const char* action=NULL;
2256 switch (_edit_point) {
2257 case EditAtPlayhead:
2258 action = "edit-at-playhead";
2260 case EditAtSelectedMarker:
2261 action = "edit-at-marker";
2264 action = "edit-at-mouse";
2268 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2270 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2274 bool in_track_canvas;
2276 if (!mouse_frame (foo, in_track_canvas)) {
2277 in_track_canvas = false;
2280 reset_canvas_action_sensitivity (in_track_canvas);
2286 Editor::set_state (const XMLNode& node, int version)
2288 XMLProperty const * prop;
2290 PBD::Unwinder<bool> nsi (no_save_instant, true);
2292 Tabbable::set_state (node, version);
2294 if (_session && (prop = node.property ("playhead"))) {
2296 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2298 playhead_cursor->set_position (pos);
2300 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2301 playhead_cursor->set_position (0);
2304 playhead_cursor->set_position (0);
2307 if ((prop = node.property ("mixer-width"))) {
2308 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2311 if ((prop = node.property ("zoom-focus"))) {
2312 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2315 if ((prop = node.property ("zoom"))) {
2316 /* older versions of ardour used floating point samples_per_pixel */
2317 double f = PBD::atof (prop->value());
2318 reset_zoom (llrintf (f));
2320 reset_zoom (samples_per_pixel);
2323 if ((prop = node.property ("visible-track-count"))) {
2324 set_visible_track_count (PBD::atoi (prop->value()));
2327 if ((prop = node.property ("snap-to"))) {
2328 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2329 set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
2332 if ((prop = node.property ("snap-mode"))) {
2333 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2334 /* set text of Dropdown. in case _snap_mode == SnapOff (default)
2335 * snap_mode_selection_done() will only mark an already active item as active
2336 * which does not trigger set_text().
2338 set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode));
2341 if ((prop = node.property ("internal-snap-to"))) {
2342 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2345 if ((prop = node.property ("internal-snap-mode"))) {
2346 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2349 if ((prop = node.property ("pre-internal-snap-to"))) {
2350 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2353 if ((prop = node.property ("pre-internal-snap-mode"))) {
2354 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2357 if ((prop = node.property ("mouse-mode"))) {
2358 MouseMode m = str2mousemode(prop->value());
2359 set_mouse_mode (m, true);
2361 set_mouse_mode (MouseObject, true);
2364 if ((prop = node.property ("left-frame")) != 0) {
2366 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2370 reset_x_origin (pos);
2374 if ((prop = node.property ("y-origin")) != 0) {
2375 reset_y_origin (atof (prop->value ()));
2378 if ((prop = node.property ("join-object-range"))) {
2379 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2380 bool yn = string_is_affirmative (prop->value());
2382 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2383 tact->set_active (!yn);
2384 tact->set_active (yn);
2386 set_mouse_mode(mouse_mode, true);
2389 if ((prop = node.property ("edit-point"))) {
2390 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2393 if ((prop = node.property ("show-measures"))) {
2394 bool yn = string_is_affirmative (prop->value());
2395 _show_measures = yn;
2398 if ((prop = node.property ("follow-playhead"))) {
2399 bool yn = string_is_affirmative (prop->value());
2400 set_follow_playhead (yn);
2403 if ((prop = node.property ("stationary-playhead"))) {
2404 bool yn = string_is_affirmative (prop->value());
2405 set_stationary_playhead (yn);
2408 if ((prop = node.property ("region-list-sort-type"))) {
2409 RegionListSortType st;
2410 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2413 if ((prop = node.property ("show-editor-mixer"))) {
2415 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2418 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2419 bool yn = string_is_affirmative (prop->value());
2421 /* do it twice to force the change */
2423 tact->set_active (!yn);
2424 tact->set_active (yn);
2427 if ((prop = node.property ("show-editor-list"))) {
2429 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2432 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2433 bool yn = string_is_affirmative (prop->value());
2435 /* do it twice to force the change */
2437 tact->set_active (!yn);
2438 tact->set_active (yn);
2441 if ((prop = node.property (X_("editor-list-page")))) {
2442 _the_notebook.set_current_page (atoi (prop->value ()));
2445 if ((prop = node.property (X_("show-marker-lines")))) {
2446 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2448 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2449 bool yn = string_is_affirmative (prop->value ());
2451 tact->set_active (!yn);
2452 tact->set_active (yn);
2455 XMLNodeList children = node.children ();
2456 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2457 selection->set_state (**i, Stateful::current_state_version);
2458 _regions->set_state (**i);
2461 if ((prop = node.property ("maximised"))) {
2462 bool yn = string_is_affirmative (prop->value());
2463 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2465 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2466 bool fs = tact && tact->get_active();
2468 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2472 if ((prop = node.property ("nudge-clock-value"))) {
2474 sscanf (prop->value().c_str(), "%" PRId64, &f);
2475 nudge_clock->set (f);
2477 nudge_clock->set_mode (AudioClock::Timecode);
2478 nudge_clock->set (_session->frame_rate() * 5, true);
2483 * Not all properties may have been in XML, but
2484 * those that are linked to a private variable may need changing
2489 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2491 yn = _show_measures;
2492 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2493 /* do it twice to force the change */
2494 tact->set_active (!yn);
2495 tact->set_active (yn);
2498 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2499 yn = _follow_playhead;
2501 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2502 if (tact->get_active() != yn) {
2503 tact->set_active (yn);
2507 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2508 yn = _stationary_playhead;
2510 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2511 if (tact->get_active() != yn) {
2512 tact->set_active (yn);
2517 return LuaInstance::instance()->set_state(node);
2521 Editor::get_state ()
2523 XMLNode* node = new XMLNode (X_("Editor"));
2526 id().print (buf, sizeof (buf));
2527 node->add_property ("id", buf);
2529 node->add_child_nocopy (Tabbable::get_state());
2531 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2532 node->add_property("edit-horizontal-pane-pos", string(buf));
2533 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2534 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2535 node->add_property("edit-vertical-pane-pos", string(buf));
2537 maybe_add_mixer_strip_width (*node);
2539 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2541 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2542 node->add_property ("zoom", buf);
2543 node->add_property ("snap-to", enum_2_string (_snap_type));
2544 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2545 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2546 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2547 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2548 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2549 node->add_property ("edit-point", enum_2_string (_edit_point));
2550 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2551 node->add_property ("visible-track-count", buf);
2553 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2554 node->add_property ("playhead", buf);
2555 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2556 node->add_property ("left-frame", buf);
2557 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2558 node->add_property ("y-origin", buf);
2560 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2561 node->add_property ("maximised", _maximised ? "yes" : "no");
2562 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2563 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2564 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2565 node->add_property ("mouse-mode", enum2str(mouse_mode));
2566 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2568 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2570 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2571 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2574 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2576 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2577 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2580 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2581 node->add_property (X_("editor-list-page"), buf);
2583 if (button_bindings) {
2584 XMLNode* bb = new XMLNode (X_("Buttons"));
2585 button_bindings->save (*bb);
2586 node->add_child_nocopy (*bb);
2589 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2591 node->add_child_nocopy (selection->get_state ());
2592 node->add_child_nocopy (_regions->get_state ());
2594 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2595 node->add_property ("nudge-clock-value", buf);
2597 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2598 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2603 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2604 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2606 * @return pair: TimeAxisView that y is over, layer index.
2608 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2609 * in stacked or expanded region display mode, otherwise 0.
2611 std::pair<TimeAxisView *, double>
2612 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2614 if (!trackview_relative_offset) {
2615 y -= _trackview_group->canvas_origin().y;
2619 return std::make_pair ( (TimeAxisView *) 0, 0);
2622 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2624 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2631 return std::make_pair ( (TimeAxisView *) 0, 0);
2634 /** Snap a position to the grid, if appropriate, taking into account current
2635 * grid settings and also the state of any snap modifier keys that may be pressed.
2636 * @param start Position to snap.
2637 * @param event Event to get current key modifier information from, or 0.
2640 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2642 if (!_session || !event) {
2646 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2647 if (_snap_mode == SnapOff) {
2648 snap_to_internal (start, direction, for_mark);
2651 if (_snap_mode != SnapOff) {
2652 snap_to_internal (start, direction, for_mark);
2653 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2654 /* SnapOff, but we pressed the snap_delta modifier */
2655 snap_to_internal (start, direction, for_mark);
2661 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2663 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2667 snap_to_internal (start, direction, for_mark, ensure_snap);
2671 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2673 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2674 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2676 switch (_snap_type) {
2677 case SnapToTimecodeFrame:
2678 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2679 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2680 /* start is already on a whole timecode frame, do nothing */
2681 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2682 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2684 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2688 case SnapToTimecodeSeconds:
2689 if (_session->config.get_timecode_offset_negative()) {
2690 start += _session->config.get_timecode_offset ();
2692 start -= _session->config.get_timecode_offset ();
2694 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2695 (start % one_timecode_second == 0)) {
2696 /* start is already on a whole second, do nothing */
2697 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2698 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2700 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2703 if (_session->config.get_timecode_offset_negative()) {
2704 start -= _session->config.get_timecode_offset ();
2706 start += _session->config.get_timecode_offset ();
2710 case SnapToTimecodeMinutes:
2711 if (_session->config.get_timecode_offset_negative()) {
2712 start += _session->config.get_timecode_offset ();
2714 start -= _session->config.get_timecode_offset ();
2716 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2717 (start % one_timecode_minute == 0)) {
2718 /* start is already on a whole minute, do nothing */
2719 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2720 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2722 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2724 if (_session->config.get_timecode_offset_negative()) {
2725 start -= _session->config.get_timecode_offset ();
2727 start += _session->config.get_timecode_offset ();
2731 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2732 abort(); /*NOTREACHED*/
2737 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2739 const framepos_t one_second = _session->frame_rate();
2740 const framepos_t one_minute = _session->frame_rate() * 60;
2741 framepos_t presnap = start;
2745 switch (_snap_type) {
2746 case SnapToTimecodeFrame:
2747 case SnapToTimecodeSeconds:
2748 case SnapToTimecodeMinutes:
2749 return timecode_snap_to_internal (start, direction, for_mark);
2752 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2753 start % (one_second/75) == 0) {
2754 /* start is already on a whole CD frame, do nothing */
2755 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2756 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2758 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2763 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2764 start % one_second == 0) {
2765 /* start is already on a whole second, do nothing */
2766 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2767 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2769 start = (framepos_t) floor ((double) start / one_second) * one_second;
2774 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2775 start % one_minute == 0) {
2776 /* start is already on a whole minute, do nothing */
2777 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2778 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2780 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2785 start = _session->tempo_map().round_to_bar (start, direction);
2789 start = _session->tempo_map().round_to_beat (start, direction);
2792 case SnapToBeatDiv128:
2793 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2795 case SnapToBeatDiv64:
2796 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2798 case SnapToBeatDiv32:
2799 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2801 case SnapToBeatDiv28:
2802 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2804 case SnapToBeatDiv24:
2805 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2807 case SnapToBeatDiv20:
2808 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2810 case SnapToBeatDiv16:
2811 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2813 case SnapToBeatDiv14:
2814 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2816 case SnapToBeatDiv12:
2817 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2819 case SnapToBeatDiv10:
2820 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2822 case SnapToBeatDiv8:
2823 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2825 case SnapToBeatDiv7:
2826 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2828 case SnapToBeatDiv6:
2829 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2831 case SnapToBeatDiv5:
2832 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2834 case SnapToBeatDiv4:
2835 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2837 case SnapToBeatDiv3:
2838 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2840 case SnapToBeatDiv2:
2841 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2849 _session->locations()->marks_either_side (start, before, after);
2851 if (before == max_framepos && after == max_framepos) {
2852 /* No marks to snap to, so just don't snap */
2854 } else if (before == max_framepos) {
2856 } else if (after == max_framepos) {
2858 } else if (before != max_framepos && after != max_framepos) {
2859 /* have before and after */
2860 if ((start - before) < (after - start)) {
2869 case SnapToRegionStart:
2870 case SnapToRegionEnd:
2871 case SnapToRegionSync:
2872 case SnapToRegionBoundary:
2873 if (!region_boundary_cache.empty()) {
2875 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2876 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2878 if (direction > 0) {
2879 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2881 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2884 if (next != region_boundary_cache.begin ()) {
2889 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2890 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2892 if (start > (p + n) / 2) {
2901 switch (_snap_mode) {
2911 if (presnap > start) {
2912 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2916 } else if (presnap < start) {
2917 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2923 /* handled at entry */
2931 Editor::setup_toolbar ()
2933 HBox* mode_box = manage(new HBox);
2934 mode_box->set_border_width (2);
2935 mode_box->set_spacing(2);
2937 HBox* mouse_mode_box = manage (new HBox);
2938 HBox* mouse_mode_hbox = manage (new HBox);
2939 VBox* mouse_mode_vbox = manage (new VBox);
2940 Alignment* mouse_mode_align = manage (new Alignment);
2942 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2943 mouse_mode_size_group->add_widget (smart_mode_button);
2944 mouse_mode_size_group->add_widget (mouse_move_button);
2945 mouse_mode_size_group->add_widget (mouse_cut_button);
2946 mouse_mode_size_group->add_widget (mouse_select_button);
2947 mouse_mode_size_group->add_widget (mouse_timefx_button);
2948 mouse_mode_size_group->add_widget (mouse_audition_button);
2949 mouse_mode_size_group->add_widget (mouse_draw_button);
2950 mouse_mode_size_group->add_widget (mouse_content_button);
2952 mouse_mode_size_group->add_widget (zoom_in_button);
2953 mouse_mode_size_group->add_widget (zoom_out_button);
2954 mouse_mode_size_group->add_widget (zoom_preset_selector);
2955 mouse_mode_size_group->add_widget (zoom_out_full_button);
2956 mouse_mode_size_group->add_widget (zoom_focus_selector);
2958 mouse_mode_size_group->add_widget (tav_shrink_button);
2959 mouse_mode_size_group->add_widget (tav_expand_button);
2960 mouse_mode_size_group->add_widget (visible_tracks_selector);
2962 mouse_mode_size_group->add_widget (snap_type_selector);
2963 mouse_mode_size_group->add_widget (snap_mode_selector);
2965 mouse_mode_size_group->add_widget (edit_point_selector);
2966 mouse_mode_size_group->add_widget (edit_mode_selector);
2968 mouse_mode_size_group->add_widget (*nudge_clock);
2969 mouse_mode_size_group->add_widget (nudge_forward_button);
2970 mouse_mode_size_group->add_widget (nudge_backward_button);
2972 mouse_mode_hbox->set_spacing (2);
2974 if (!ARDOUR::Profile->get_trx()) {
2975 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2978 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2979 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2981 if (!ARDOUR::Profile->get_mixbus()) {
2982 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2985 if (!ARDOUR::Profile->get_trx()) {
2986 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2987 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2988 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2989 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2992 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2994 mouse_mode_align->add (*mouse_mode_vbox);
2995 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2997 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2999 edit_mode_selector.set_name ("mouse mode button");
3001 if (!ARDOUR::Profile->get_trx()) {
3002 mode_box->pack_start (edit_mode_selector, false, false);
3005 mode_box->pack_start (*mouse_mode_box, false, false);
3009 _zoom_box.set_spacing (2);
3010 _zoom_box.set_border_width (2);
3014 zoom_preset_selector.set_name ("zoom button");
3015 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3016 zoom_preset_selector.set_size_request (42, -1);
3018 zoom_in_button.set_name ("zoom button");
3019 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3020 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3021 zoom_in_button.set_related_action (act);
3023 zoom_out_button.set_name ("zoom button");
3024 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3025 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3026 zoom_out_button.set_related_action (act);
3028 zoom_out_full_button.set_name ("zoom button");
3029 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3030 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3031 zoom_out_full_button.set_related_action (act);
3033 zoom_focus_selector.set_name ("zoom button");
3035 if (ARDOUR::Profile->get_mixbus()) {
3036 _zoom_box.pack_start (zoom_preset_selector, false, false);
3037 } else if (ARDOUR::Profile->get_trx()) {
3038 mode_box->pack_start (zoom_out_button, false, false);
3039 mode_box->pack_start (zoom_in_button, false, false);
3041 _zoom_box.pack_start (zoom_out_button, false, false);
3042 _zoom_box.pack_start (zoom_in_button, false, false);
3043 _zoom_box.pack_start (zoom_out_full_button, false, false);
3044 _zoom_box.pack_start (zoom_focus_selector, false, false);
3047 /* Track zoom buttons */
3048 visible_tracks_selector.set_name ("zoom button");
3049 if (Profile->get_mixbus()) {
3050 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3051 visible_tracks_selector.set_size_request (42, -1);
3053 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3056 tav_expand_button.set_name ("zoom button");
3057 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3058 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3059 tav_expand_button.set_related_action (act);
3061 tav_shrink_button.set_name ("zoom button");
3062 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3063 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3064 tav_shrink_button.set_related_action (act);
3066 if (ARDOUR::Profile->get_mixbus()) {
3067 _zoom_box.pack_start (visible_tracks_selector);
3068 } else if (ARDOUR::Profile->get_trx()) {
3069 _zoom_box.pack_start (tav_shrink_button);
3070 _zoom_box.pack_start (tav_expand_button);
3072 _zoom_box.pack_start (visible_tracks_selector);
3073 _zoom_box.pack_start (tav_shrink_button);
3074 _zoom_box.pack_start (tav_expand_button);
3077 snap_box.set_spacing (2);
3078 snap_box.set_border_width (2);
3080 snap_type_selector.set_name ("mouse mode button");
3082 snap_mode_selector.set_name ("mouse mode button");
3084 edit_point_selector.set_name ("mouse mode button");
3086 snap_box.pack_start (snap_mode_selector, false, false);
3087 snap_box.pack_start (snap_type_selector, false, false);
3088 snap_box.pack_start (edit_point_selector, false, false);
3092 HBox *nudge_box = manage (new HBox);
3093 nudge_box->set_spacing (2);
3094 nudge_box->set_border_width (2);
3096 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3097 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3099 nudge_box->pack_start (nudge_backward_button, false, false);
3100 nudge_box->pack_start (nudge_forward_button, false, false);
3101 nudge_box->pack_start (*nudge_clock, false, false);
3104 /* Pack everything in... */
3106 HBox* hbox = manage (new HBox);
3107 hbox->set_spacing(2);
3109 toolbar_hbox.set_spacing (2);
3110 toolbar_hbox.set_border_width (1);
3112 toolbar_hbox.pack_start (*mode_box, false, false);
3113 if (!ARDOUR::Profile->get_trx()) {
3114 toolbar_hbox.pack_start (_zoom_box, false, false);
3115 toolbar_hbox.pack_start (*hbox, false, false);
3118 if (!ARDOUR::Profile->get_trx()) {
3119 hbox->pack_start (snap_box, false, false);
3120 hbox->pack_start (*nudge_box, false, false);
3125 toolbar_base.set_name ("ToolBarBase");
3126 toolbar_base.add (toolbar_hbox);
3128 _toolbar_viewport.add (toolbar_base);
3129 /* stick to the required height but allow width to vary if there's not enough room */
3130 _toolbar_viewport.set_size_request (1, -1);
3132 toolbar_frame.set_shadow_type (SHADOW_OUT);
3133 toolbar_frame.set_name ("BaseFrame");
3134 toolbar_frame.add (_toolbar_viewport);
3138 Editor::build_edit_point_menu ()
3140 using namespace Menu_Helpers;
3142 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3143 if(!Profile->get_mixbus())
3144 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3145 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3147 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3151 Editor::build_edit_mode_menu ()
3153 using namespace Menu_Helpers;
3155 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3156 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3157 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3158 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3160 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3164 Editor::build_snap_mode_menu ()
3166 using namespace Menu_Helpers;
3168 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3169 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3170 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3172 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3176 Editor::build_snap_type_menu ()
3178 using namespace Menu_Helpers;
3180 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3181 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3182 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3183 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3184 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3185 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3186 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3187 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3188 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3189 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3190 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3191 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3192 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3193 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3194 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3195 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3196 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3197 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3198 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3199 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3200 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3201 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3202 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3203 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3204 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3205 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3206 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3207 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3208 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3209 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3211 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3216 Editor::setup_tooltips ()
3218 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3219 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3220 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3221 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3222 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3223 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3224 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3225 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3226 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3227 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3228 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3229 set_tooltip (zoom_in_button, _("Zoom In"));
3230 set_tooltip (zoom_out_button, _("Zoom Out"));
3231 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3232 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3233 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3234 set_tooltip (tav_expand_button, _("Expand Tracks"));
3235 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3236 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3237 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3238 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3239 set_tooltip (edit_point_selector, _("Edit Point"));
3240 set_tooltip (edit_mode_selector, _("Edit Mode"));
3241 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3245 Editor::convert_drop_to_paths (
3246 vector<string>& paths,
3247 const RefPtr<Gdk::DragContext>& /*context*/,
3250 const SelectionData& data,
3254 if (_session == 0) {
3258 vector<string> uris = data.get_uris();
3262 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3263 are actually URI lists. So do it by hand.
3266 if (data.get_target() != "text/plain") {
3270 /* Parse the "uri-list" format that Nautilus provides,
3271 where each pathname is delimited by \r\n.
3273 THERE MAY BE NO NULL TERMINATING CHAR!!!
3276 string txt = data.get_text();
3280 p = (char *) malloc (txt.length() + 1);
3281 txt.copy (p, txt.length(), 0);
3282 p[txt.length()] = '\0';
3288 while (g_ascii_isspace (*p))
3292 while (*q && (*q != '\n') && (*q != '\r')) {
3299 while (q > p && g_ascii_isspace (*q))
3304 uris.push_back (string (p, q - p + 1));
3308 p = strchr (p, '\n');
3320 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3321 if ((*i).substr (0,7) == "file://") {
3322 paths.push_back (Glib::filename_from_uri (*i));
3330 Editor::new_tempo_section ()
3335 Editor::map_transport_state ()
3337 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3339 if (_session && _session->transport_stopped()) {
3340 have_pending_keyboard_selection = false;
3343 update_loop_range_view ();
3349 Editor::begin_selection_op_history ()
3351 selection_op_cmd_depth = 0;
3352 selection_op_history_it = 0;
3354 while(!selection_op_history.empty()) {
3355 delete selection_op_history.front();
3356 selection_op_history.pop_front();
3359 selection_undo_action->set_sensitive (false);
3360 selection_redo_action->set_sensitive (false);
3361 selection_op_history.push_front (&_selection_memento->get_state ());
3365 Editor::begin_reversible_selection_op (string name)
3368 //cerr << name << endl;
3369 /* begin/commit pairs can be nested */
3370 selection_op_cmd_depth++;
3375 Editor::commit_reversible_selection_op ()
3378 if (selection_op_cmd_depth == 1) {
3380 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3382 The user has undone some selection ops and then made a new one,
3383 making anything earlier in the list invalid.
3386 list<XMLNode *>::iterator it = selection_op_history.begin();
3387 list<XMLNode *>::iterator e_it = it;
3388 advance (e_it, selection_op_history_it);
3390 for ( ; it != e_it; ++it) {
3393 selection_op_history.erase (selection_op_history.begin(), e_it);
3396 selection_op_history.push_front (&_selection_memento->get_state ());
3397 selection_op_history_it = 0;
3399 selection_undo_action->set_sensitive (true);
3400 selection_redo_action->set_sensitive (false);
3403 if (selection_op_cmd_depth > 0) {
3404 selection_op_cmd_depth--;
3410 Editor::undo_selection_op ()
3413 selection_op_history_it++;
3415 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3416 if (n == selection_op_history_it) {
3417 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3418 selection_redo_action->set_sensitive (true);
3422 /* is there an earlier entry? */
3423 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3424 selection_undo_action->set_sensitive (false);
3430 Editor::redo_selection_op ()
3433 if (selection_op_history_it > 0) {
3434 selection_op_history_it--;
3437 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3438 if (n == selection_op_history_it) {
3439 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3440 selection_undo_action->set_sensitive (true);
3445 if (selection_op_history_it == 0) {
3446 selection_redo_action->set_sensitive (false);
3452 Editor::begin_reversible_command (string name)
3455 before.push_back (&_selection_memento->get_state ());
3456 _session->begin_reversible_command (name);
3461 Editor::begin_reversible_command (GQuark q)
3464 before.push_back (&_selection_memento->get_state ());
3465 _session->begin_reversible_command (q);
3470 Editor::abort_reversible_command ()
3473 while(!before.empty()) {
3474 delete before.front();
3477 _session->abort_reversible_command ();
3482 Editor::commit_reversible_command ()
3485 if (before.size() == 1) {
3486 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3487 redo_action->set_sensitive(false);
3488 undo_action->set_sensitive(true);
3489 begin_selection_op_history ();
3492 if (before.empty()) {
3493 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3498 _session->commit_reversible_command ();
3503 Editor::history_changed ()
3507 if (undo_action && _session) {
3508 if (_session->undo_depth() == 0) {
3509 label = S_("Command|Undo");
3511 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3513 undo_action->property_label() = label;
3516 if (redo_action && _session) {
3517 if (_session->redo_depth() == 0) {
3519 redo_action->set_sensitive (false);
3521 label = string_compose(_("Redo (%1)"), _session->next_redo());
3522 redo_action->set_sensitive (true);
3524 redo_action->property_label() = label;
3529 Editor::duplicate_range (bool with_dialog)
3533 RegionSelection rs = get_regions_from_selection_and_entered ();
3535 if ( selection->time.length() == 0 && rs.empty()) {
3541 ArdourDialog win (_("Duplicate"));
3542 Label label (_("Number of duplications:"));
3543 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3544 SpinButton spinner (adjustment, 0.0, 1);
3547 win.get_vbox()->set_spacing (12);
3548 win.get_vbox()->pack_start (hbox);
3549 hbox.set_border_width (6);
3550 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3552 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3553 place, visually. so do this by hand.
3556 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3557 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3558 spinner.grab_focus();
3564 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3565 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3566 win.set_default_response (RESPONSE_ACCEPT);
3568 spinner.grab_focus ();
3570 switch (win.run ()) {
3571 case RESPONSE_ACCEPT:
3577 times = adjustment.get_value();
3580 if ((current_mouse_mode() == Editing::MouseRange)) {
3581 if (selection->time.length()) {
3582 duplicate_selection (times);
3584 } else if (get_smart_mode()) {
3585 if (selection->time.length()) {
3586 duplicate_selection (times);
3588 duplicate_some_regions (rs, times);
3590 duplicate_some_regions (rs, times);
3595 Editor::set_edit_mode (EditMode m)
3597 Config->set_edit_mode (m);
3601 Editor::cycle_edit_mode ()
3603 switch (Config->get_edit_mode()) {
3605 Config->set_edit_mode (Ripple);
3609 Config->set_edit_mode (Lock);
3612 Config->set_edit_mode (Slide);
3618 Editor::edit_mode_selection_done ( EditMode m )
3620 Config->set_edit_mode ( m );
3624 Editor::snap_type_selection_done (SnapType snaptype)
3626 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3628 ract->set_active ();
3633 Editor::snap_mode_selection_done (SnapMode mode)
3635 RefPtr<RadioAction> ract = snap_mode_action (mode);
3638 ract->set_active (true);
3643 Editor::cycle_edit_point (bool with_marker)
3645 if(Profile->get_mixbus())
3646 with_marker = false;
3648 switch (_edit_point) {
3650 set_edit_point_preference (EditAtPlayhead);
3652 case EditAtPlayhead:
3654 set_edit_point_preference (EditAtSelectedMarker);
3656 set_edit_point_preference (EditAtMouse);
3659 case EditAtSelectedMarker:
3660 set_edit_point_preference (EditAtMouse);
3666 Editor::edit_point_selection_done (EditPoint ep)
3668 set_edit_point_preference ( ep );
3672 Editor::build_zoom_focus_menu ()
3674 using namespace Menu_Helpers;
3676 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3677 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3678 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3679 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3680 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3681 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3683 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3687 Editor::zoom_focus_selection_done ( ZoomFocus f )
3689 RefPtr<RadioAction> ract = zoom_focus_action (f);
3691 ract->set_active ();
3696 Editor::build_track_count_menu ()
3698 using namespace Menu_Helpers;
3700 if (!Profile->get_mixbus()) {
3701 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3702 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3703 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3704 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3705 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3706 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3707 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3708 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3709 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3710 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3711 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3712 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3713 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3715 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3716 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3717 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3718 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3719 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3720 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3721 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3722 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3723 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3724 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3726 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3727 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3728 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3729 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3730 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3731 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3732 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3733 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3734 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3735 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3736 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3741 Editor::set_zoom_preset (int64_t ms)
3744 temporal_zoom_session();
3748 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3749 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3753 Editor::set_visible_track_count (int32_t n)
3755 _visible_track_count = n;
3757 /* if the canvas hasn't really been allocated any size yet, just
3758 record the desired number of visible tracks and return. when canvas
3759 allocation happens, we will get called again and then we can do the
3763 if (_visible_canvas_height <= 1) {
3769 DisplaySuspender ds;
3771 if (_visible_track_count > 0) {
3772 h = trackviews_height() / _visible_track_count;
3773 std::ostringstream s;
3774 s << _visible_track_count;
3776 } else if (_visible_track_count == 0) {
3778 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3779 if ((*i)->marked_for_display()) {
3783 h = trackviews_height() / n;
3786 /* negative value means that the visible track count has
3787 been overridden by explicit track height changes.
3789 visible_tracks_selector.set_text (X_("*"));
3793 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3794 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3797 if (str != visible_tracks_selector.get_text()) {
3798 visible_tracks_selector.set_text (str);
3803 Editor::override_visible_track_count ()
3805 _visible_track_count = -1;
3806 visible_tracks_selector.set_text ( _("*") );
3810 Editor::edit_controls_button_release (GdkEventButton* ev)
3812 if (Keyboard::is_context_menu_event (ev)) {
3813 ARDOUR_UI::instance()->add_route ();
3814 } else if (ev->button == 1) {
3815 selection->clear_tracks ();
3822 Editor::mouse_select_button_release (GdkEventButton* ev)
3824 /* this handles just right-clicks */
3826 if (ev->button != 3) {
3834 Editor::set_zoom_focus (ZoomFocus f)
3836 string str = zoom_focus_strings[(int)f];
3838 if (str != zoom_focus_selector.get_text()) {
3839 zoom_focus_selector.set_text (str);
3842 if (zoom_focus != f) {
3849 Editor::cycle_zoom_focus ()
3851 switch (zoom_focus) {
3853 set_zoom_focus (ZoomFocusRight);
3855 case ZoomFocusRight:
3856 set_zoom_focus (ZoomFocusCenter);
3858 case ZoomFocusCenter:
3859 set_zoom_focus (ZoomFocusPlayhead);
3861 case ZoomFocusPlayhead:
3862 set_zoom_focus (ZoomFocusMouse);
3864 case ZoomFocusMouse:
3865 set_zoom_focus (ZoomFocusEdit);
3868 set_zoom_focus (ZoomFocusLeft);
3874 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3876 /* recover or initialize pane positions. do this here rather than earlier because
3877 we don't want the positions to change the child allocations, which they seem to do.
3881 XMLProperty const * prop;
3883 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3892 XMLNode* geometry = find_named_node (*node, "geometry");
3894 if (which == static_cast<Paned*> (&edit_pane)) {
3896 if (done & Horizontal) {
3900 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3901 _notebook_shrunk = string_is_affirmative (prop->value ());
3904 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3905 /* initial allocation is 90% to canvas, 10% to notebook */
3906 pos = (int) floor (alloc.get_width() * 0.90f);
3907 snprintf (buf, sizeof(buf), "%d", pos);
3909 pos = atoi (prop->value());
3912 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3913 edit_pane.set_position (pos);
3916 done = (Pane) (done | Horizontal);
3918 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3920 if (done & Vertical) {
3924 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3925 /* initial allocation is 90% to canvas, 10% to summary */
3926 pos = (int) floor (alloc.get_height() * 0.90f);
3927 snprintf (buf, sizeof(buf), "%d", pos);
3930 pos = atoi (prop->value());
3933 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3934 editor_summary_pane.set_position (pos);
3937 done = (Pane) (done | Vertical);
3942 Editor::set_show_measures (bool yn)
3944 if (_show_measures != yn) {
3947 if ((_show_measures = yn) == true) {
3949 tempo_lines->show();
3952 std::vector<TempoMap::BBTPoint> grid;
3953 compute_current_bbt_points (grid, leftmost_frame, leftmost_frame + current_page_samples());
3954 draw_measures (grid);
3962 Editor::toggle_follow_playhead ()
3964 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3966 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3967 set_follow_playhead (tact->get_active());
3971 /** @param yn true to follow playhead, otherwise false.
3972 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3975 Editor::set_follow_playhead (bool yn, bool catch_up)
3977 if (_follow_playhead != yn) {
3978 if ((_follow_playhead = yn) == true && catch_up) {
3980 reset_x_origin_to_follow_playhead ();
3987 Editor::toggle_stationary_playhead ()
3989 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3991 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3992 set_stationary_playhead (tact->get_active());
3997 Editor::set_stationary_playhead (bool yn)
3999 if (_stationary_playhead != yn) {
4000 if ((_stationary_playhead = yn) == true) {
4002 // FIXME need a 3.0 equivalent of this 2.X call
4003 // update_current_screen ();
4010 Editor::playlist_selector () const
4012 return *_playlist_selector;
4016 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4018 if (paste_count == 0) {
4019 /* don't bother calculating an offset that will be zero anyway */
4023 /* calculate basic unsnapped multi-paste offset */
4024 framecnt_t offset = paste_count * duration;
4026 /* snap offset so pos + offset is aligned to the grid */
4027 framepos_t offset_pos = pos + offset;
4028 snap_to(offset_pos, RoundUpMaybe);
4029 offset = offset_pos - pos;
4035 Editor::get_grid_beat_divisions(framepos_t position)
4037 switch (_snap_type) {
4038 case SnapToBeatDiv128: return 128;
4039 case SnapToBeatDiv64: return 64;
4040 case SnapToBeatDiv32: return 32;
4041 case SnapToBeatDiv28: return 28;
4042 case SnapToBeatDiv24: return 24;
4043 case SnapToBeatDiv20: return 20;
4044 case SnapToBeatDiv16: return 16;
4045 case SnapToBeatDiv14: return 14;
4046 case SnapToBeatDiv12: return 12;
4047 case SnapToBeatDiv10: return 10;
4048 case SnapToBeatDiv8: return 8;
4049 case SnapToBeatDiv7: return 7;
4050 case SnapToBeatDiv6: return 6;
4051 case SnapToBeatDiv5: return 5;
4052 case SnapToBeatDiv4: return 4;
4053 case SnapToBeatDiv3: return 3;
4054 case SnapToBeatDiv2: return 2;
4061 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4065 const unsigned divisions = get_grid_beat_divisions(position);
4067 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4070 switch (_snap_type) {
4072 return Evoral::Beats(1.0);
4075 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4083 return Evoral::Beats();
4087 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4091 ret = nudge_clock->current_duration (pos);
4092 next = ret + 1; /* XXXX fix me */
4098 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4100 ArdourDialog dialog (_("Playlist Deletion"));
4101 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4102 "If it is kept, its audio files will not be cleaned.\n"
4103 "If it is deleted, audio files used by it alone will be cleaned."),
4106 dialog.set_position (WIN_POS_CENTER);
4107 dialog.get_vbox()->pack_start (label);
4111 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4112 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4113 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4114 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4115 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4117 // by default gtk uses the left most button
4118 keep->grab_focus ();
4120 switch (dialog.run ()) {
4122 /* keep this and all remaining ones */
4127 /* delete this and all others */
4131 case RESPONSE_ACCEPT:
4132 /* delete the playlist */
4136 case RESPONSE_REJECT:
4137 /* keep the playlist */
4149 Editor::audio_region_selection_covers (framepos_t where)
4151 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4152 if ((*a)->region()->covers (where)) {
4161 Editor::prepare_for_cleanup ()
4163 cut_buffer->clear_regions ();
4164 cut_buffer->clear_playlists ();
4166 selection->clear_regions ();
4167 selection->clear_playlists ();
4169 _regions->suspend_redisplay ();
4173 Editor::finish_cleanup ()
4175 _regions->resume_redisplay ();
4179 Editor::transport_loop_location()
4182 return _session->locations()->auto_loop_location();
4189 Editor::transport_punch_location()
4192 return _session->locations()->auto_punch_location();
4199 Editor::control_layout_scroll (GdkEventScroll* ev)
4201 /* Just forward to the normal canvas scroll method. The coordinate
4202 systems are different but since the canvas is always larger than the
4203 track headers, and aligned with the trackview area, this will work.
4205 In the not too distant future this layout is going away anyway and
4206 headers will be on the canvas.
4208 return canvas_scroll_event (ev, false);
4212 Editor::session_state_saved (string)
4215 _snapshots->redisplay ();
4219 Editor::maximise_editing_space ()
4225 Gtk::Window* toplevel = current_toplevel();
4228 toplevel->fullscreen ();
4234 Editor::restore_editing_space ()
4240 Gtk::Window* toplevel = current_toplevel();
4243 toplevel->unfullscreen();
4249 * Make new playlists for a given track and also any others that belong
4250 * to the same active route group with the `select' property.
4255 Editor::new_playlists (TimeAxisView* v)
4257 begin_reversible_command (_("new playlists"));
4258 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4259 _session->playlists->get (playlists);
4260 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4261 commit_reversible_command ();
4265 * Use a copy of the current playlist for a given track and also any others that belong
4266 * to the same active route group with the `select' property.
4271 Editor::copy_playlists (TimeAxisView* v)
4273 begin_reversible_command (_("copy playlists"));
4274 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4275 _session->playlists->get (playlists);
4276 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4277 commit_reversible_command ();
4280 /** Clear the current playlist for a given track and also any others that belong
4281 * to the same active route group with the `select' property.
4286 Editor::clear_playlists (TimeAxisView* v)
4288 begin_reversible_command (_("clear playlists"));
4289 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4290 _session->playlists->get (playlists);
4291 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4292 commit_reversible_command ();
4296 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4298 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4302 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4304 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4308 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4310 atv.clear_playlist ();
4314 Editor::get_y_origin () const
4316 return vertical_adjustment.get_value ();
4319 /** Queue up a change to the viewport x origin.
4320 * @param frame New x origin.
4323 Editor::reset_x_origin (framepos_t frame)
4325 pending_visual_change.add (VisualChange::TimeOrigin);
4326 pending_visual_change.time_origin = frame;
4327 ensure_visual_change_idle_handler ();
4331 Editor::reset_y_origin (double y)
4333 pending_visual_change.add (VisualChange::YOrigin);
4334 pending_visual_change.y_origin = y;
4335 ensure_visual_change_idle_handler ();
4339 Editor::reset_zoom (framecnt_t spp)
4341 if (spp == samples_per_pixel) {
4345 pending_visual_change.add (VisualChange::ZoomLevel);
4346 pending_visual_change.samples_per_pixel = spp;
4347 ensure_visual_change_idle_handler ();
4351 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4353 reset_x_origin (frame);
4356 if (!no_save_visual) {
4357 undo_visual_stack.push_back (current_visual_state(false));
4361 Editor::VisualState::VisualState (bool with_tracks)
4362 : gui_state (with_tracks ? new GUIObjectState : 0)
4366 Editor::VisualState::~VisualState ()
4371 Editor::VisualState*
4372 Editor::current_visual_state (bool with_tracks)
4374 VisualState* vs = new VisualState (with_tracks);
4375 vs->y_position = vertical_adjustment.get_value();
4376 vs->samples_per_pixel = samples_per_pixel;
4377 vs->leftmost_frame = leftmost_frame;
4378 vs->zoom_focus = zoom_focus;
4381 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4388 Editor::undo_visual_state ()
4390 if (undo_visual_stack.empty()) {
4394 VisualState* vs = undo_visual_stack.back();
4395 undo_visual_stack.pop_back();
4398 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4401 use_visual_state (*vs);
4406 Editor::redo_visual_state ()
4408 if (redo_visual_stack.empty()) {
4412 VisualState* vs = redo_visual_stack.back();
4413 redo_visual_stack.pop_back();
4415 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4416 // why do we check here?
4417 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4420 use_visual_state (*vs);
4425 Editor::swap_visual_state ()
4427 if (undo_visual_stack.empty()) {
4428 redo_visual_state ();
4430 undo_visual_state ();
4435 Editor::use_visual_state (VisualState& vs)
4437 PBD::Unwinder<bool> nsv (no_save_visual, true);
4438 DisplaySuspender ds;
4440 vertical_adjustment.set_value (vs.y_position);
4442 set_zoom_focus (vs.zoom_focus);
4443 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4446 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4448 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4449 (*i)->clear_property_cache();
4450 (*i)->reset_visual_state ();
4454 _routes->update_visibility ();
4457 /** This is the core function that controls the zoom level of the canvas. It is called
4458 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4459 * @param spp new number of samples per pixel
4462 Editor::set_samples_per_pixel (framecnt_t spp)
4468 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4469 const framecnt_t lots_of_pixels = 4000;
4471 /* if the zoom level is greater than what you'd get trying to display 3
4472 * days of audio on a really big screen, then it's too big.
4475 if (spp * lots_of_pixels > three_days) {
4479 samples_per_pixel = spp;
4482 tempo_lines->tempo_map_changed();
4485 bool const showing_time_selection = selection->time.length() > 0;
4487 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4488 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4489 (*i)->reshow_selection (selection->time);
4493 ZoomChanged (); /* EMIT_SIGNAL */
4495 ArdourCanvas::GtkCanvasViewport* c;
4497 c = get_track_canvas();
4499 c->canvas()->zoomed ();
4502 if (playhead_cursor) {
4503 playhead_cursor->set_position (playhead_cursor->current_frame ());
4506 refresh_location_display();
4507 _summary->set_overlays_dirty ();
4509 update_marker_labels ();
4515 Editor::queue_visual_videotimeline_update ()
4518 * pending_visual_change.add (VisualChange::VideoTimeline);
4519 * or maybe even more specific: which videotimeline-image
4520 * currently it calls update_video_timeline() to update
4521 * _all outdated_ images on the video-timeline.
4522 * see 'exposeimg()' in video_image_frame.cc
4524 ensure_visual_change_idle_handler ();
4528 Editor::ensure_visual_change_idle_handler ()
4530 if (pending_visual_change.idle_handler_id < 0) {
4531 // see comment in add_to_idle_resize above.
4532 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4533 pending_visual_change.being_handled = false;
4538 Editor::_idle_visual_changer (void* arg)
4540 return static_cast<Editor*>(arg)->idle_visual_changer ();
4544 Editor::idle_visual_changer ()
4546 /* set_horizontal_position() below (and maybe other calls) call
4547 gtk_main_iteration(), so it's possible that a signal will be handled
4548 half-way through this method. If this signal wants an
4549 idle_visual_changer we must schedule another one after this one, so
4550 mark the idle_handler_id as -1 here to allow that. Also make a note
4551 that we are doing the visual change, so that changes in response to
4552 super-rapid-screen-update can be dropped if we are still processing
4556 pending_visual_change.idle_handler_id = -1;
4557 pending_visual_change.being_handled = true;
4559 VisualChange vc = pending_visual_change;
4561 pending_visual_change.pending = (VisualChange::Type) 0;
4563 visual_changer (vc);
4565 pending_visual_change.being_handled = false;
4567 return 0; /* this is always a one-shot call */
4571 Editor::visual_changer (const VisualChange& vc)
4573 double const last_time_origin = horizontal_position ();
4575 if (vc.pending & VisualChange::ZoomLevel) {
4576 set_samples_per_pixel (vc.samples_per_pixel);
4578 compute_fixed_ruler_scale ();
4580 std::vector<TempoMap::BBTPoint> grid;
4581 compute_current_bbt_points (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4582 compute_bbt_ruler_scale (grid, vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4583 update_tempo_based_rulers (grid);
4585 update_video_timeline();
4588 if (vc.pending & VisualChange::TimeOrigin) {
4589 set_horizontal_position (vc.time_origin / samples_per_pixel);
4592 if (vc.pending & VisualChange::YOrigin) {
4593 vertical_adjustment.set_value (vc.y_origin);
4596 if (last_time_origin == horizontal_position ()) {
4597 /* changed signal not emitted */
4598 update_fixed_rulers ();
4599 redisplay_tempo (true);
4602 if (!(vc.pending & VisualChange::ZoomLevel)) {
4603 update_video_timeline();
4606 _summary->set_overlays_dirty ();
4609 struct EditorOrderTimeAxisSorter {
4610 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4611 return a->order () < b->order ();
4616 Editor::sort_track_selection (TrackViewList& sel)
4618 EditorOrderTimeAxisSorter cmp;
4623 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4626 framepos_t where = 0;
4627 EditPoint ep = _edit_point;
4629 if (Profile->get_mixbus())
4630 if (ep == EditAtSelectedMarker)
4631 ep = EditAtPlayhead;
4633 if (from_outside_canvas && (ep == EditAtMouse)) {
4634 ep = EditAtPlayhead;
4635 } else if (from_context_menu && (ep == EditAtMouse)) {
4636 return canvas_event_sample (&context_click_event, 0, 0);
4639 if (entered_marker) {
4640 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4641 return entered_marker->position();
4644 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4645 ep = EditAtSelectedMarker;
4648 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4649 ep = EditAtPlayhead;
4653 case EditAtPlayhead:
4654 if (_dragging_playhead) {
4655 where = *_control_scroll_target;
4657 where = _session->audible_frame();
4659 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4662 case EditAtSelectedMarker:
4663 if (!selection->markers.empty()) {
4665 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4668 where = loc->start();
4672 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4680 if (!mouse_frame (where, ignored)) {
4681 /* XXX not right but what can we do ? */
4685 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4693 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4695 if (!_session) return;
4697 begin_reversible_command (cmd);
4701 if ((tll = transport_loop_location()) == 0) {
4702 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4703 XMLNode &before = _session->locations()->get_state();
4704 _session->locations()->add (loc, true);
4705 _session->set_auto_loop_location (loc);
4706 XMLNode &after = _session->locations()->get_state();
4707 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4709 XMLNode &before = tll->get_state();
4710 tll->set_hidden (false, this);
4711 tll->set (start, end);
4712 XMLNode &after = tll->get_state();
4713 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4716 commit_reversible_command ();
4720 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4722 if (!_session) return;
4724 begin_reversible_command (cmd);
4728 if ((tpl = transport_punch_location()) == 0) {
4729 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4730 XMLNode &before = _session->locations()->get_state();
4731 _session->locations()->add (loc, true);
4732 _session->set_auto_punch_location (loc);
4733 XMLNode &after = _session->locations()->get_state();
4734 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4736 XMLNode &before = tpl->get_state();
4737 tpl->set_hidden (false, this);
4738 tpl->set (start, end);
4739 XMLNode &after = tpl->get_state();
4740 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4743 commit_reversible_command ();
4746 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4747 * @param rs List to which found regions are added.
4748 * @param where Time to look at.
4749 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4752 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4754 const TrackViewList* tracks;
4757 tracks = &track_views;
4762 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4764 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4767 boost::shared_ptr<Track> tr;
4768 boost::shared_ptr<Playlist> pl;
4770 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4772 boost::shared_ptr<RegionList> regions = pl->regions_at (
4773 (framepos_t) floor ( (double) where * tr->speed()));
4775 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4776 RegionView* rv = rtv->view()->find_view (*i);
4787 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4789 const TrackViewList* tracks;
4792 tracks = &track_views;
4797 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4798 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4800 boost::shared_ptr<Track> tr;
4801 boost::shared_ptr<Playlist> pl;
4803 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4805 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4806 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4808 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4810 RegionView* rv = rtv->view()->find_view (*i);
4821 /** Get regions using the following method:
4823 * Make a region list using:
4824 * (a) any selected regions
4825 * (b) the intersection of any selected tracks and the edit point(*)
4826 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4828 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4830 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4834 Editor::get_regions_from_selection_and_edit_point ()
4836 RegionSelection regions;
4838 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4839 regions.add (entered_regionview);
4841 regions = selection->regions;
4844 if ( regions.empty() ) {
4845 TrackViewList tracks = selection->tracks;
4847 if (!tracks.empty()) {
4848 /* no region selected or entered, but some selected tracks:
4849 * act on all regions on the selected tracks at the edit point
4851 framepos_t const where = get_preferred_edit_position ();
4852 get_regions_at(regions, where, tracks);
4859 /** Get regions using the following method:
4861 * Make a region list using:
4862 * (a) any selected regions
4863 * (b) the intersection of any selected tracks and the edit point(*)
4864 * (c) if neither exists, then whatever region is under the mouse
4866 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4868 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4871 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4873 RegionSelection regions;
4875 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4876 regions.add (entered_regionview);
4878 regions = selection->regions;
4881 if ( regions.empty() ) {
4882 TrackViewList tracks = selection->tracks;
4884 if (!tracks.empty()) {
4885 /* no region selected or entered, but some selected tracks:
4886 * act on all regions on the selected tracks at the edit point
4888 get_regions_at(regions, pos, tracks);
4895 /** Start with regions that are selected, or the entered regionview if none are selected.
4896 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4897 * of the regions that we started with.
4901 Editor::get_regions_from_selection_and_entered () const
4903 RegionSelection regions = selection->regions;
4905 if (regions.empty() && entered_regionview) {
4906 regions.add (entered_regionview);
4913 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4915 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4916 RouteTimeAxisView* rtav;
4918 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4919 boost::shared_ptr<Playlist> pl;
4920 std::vector<boost::shared_ptr<Region> > results;
4921 boost::shared_ptr<Track> tr;
4923 if ((tr = rtav->track()) == 0) {
4928 if ((pl = (tr->playlist())) != 0) {
4929 boost::shared_ptr<Region> r = pl->region_by_id (id);
4931 RegionView* rv = rtav->view()->find_view (r);
4933 regions.push_back (rv);
4942 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4945 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4946 MidiTimeAxisView* mtav;
4948 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4950 mtav->get_per_region_note_selection (selection);
4957 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4959 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4961 RouteTimeAxisView* tatv;
4963 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4965 boost::shared_ptr<Playlist> pl;
4966 vector<boost::shared_ptr<Region> > results;
4968 boost::shared_ptr<Track> tr;
4970 if ((tr = tatv->track()) == 0) {
4975 if ((pl = (tr->playlist())) != 0) {
4976 if (src_comparison) {
4977 pl->get_source_equivalent_regions (region, results);
4979 pl->get_region_list_equivalent_regions (region, results);
4983 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4984 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4985 regions.push_back (marv);
4994 Editor::show_rhythm_ferret ()
4996 if (rhythm_ferret == 0) {
4997 rhythm_ferret = new RhythmFerret(*this);
5000 rhythm_ferret->set_session (_session);
5001 rhythm_ferret->show ();
5002 rhythm_ferret->present ();
5006 Editor::first_idle ()
5008 MessageDialog* dialog = 0;
5010 if (track_views.size() > 1) {
5011 Timers::TimerSuspender t;
5012 dialog = new MessageDialog (
5013 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5017 ARDOUR_UI::instance()->flush_pending ();
5020 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5024 // first idle adds route children (automation tracks), so we need to redisplay here
5025 _routes->redisplay ();
5029 if (_session->undo_depth() == 0) {
5030 undo_action->set_sensitive(false);
5032 redo_action->set_sensitive(false);
5033 begin_selection_op_history ();
5039 Editor::_idle_resize (gpointer arg)
5041 return ((Editor*)arg)->idle_resize ();
5045 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5047 if (resize_idle_id < 0) {
5048 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5049 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5050 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5052 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5053 _pending_resize_amount = 0;
5056 /* make a note of the smallest resulting height, so that we can clamp the
5057 lower limit at TimeAxisView::hSmall */
5059 int32_t min_resulting = INT32_MAX;
5061 _pending_resize_amount += h;
5062 _pending_resize_view = view;
5064 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5066 if (selection->tracks.contains (_pending_resize_view)) {
5067 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5068 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5072 if (min_resulting < 0) {
5077 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5078 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5082 /** Handle pending resizing of tracks */
5084 Editor::idle_resize ()
5086 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5088 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5089 selection->tracks.contains (_pending_resize_view)) {
5091 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5092 if (*i != _pending_resize_view) {
5093 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5098 _pending_resize_amount = 0;
5099 _group_tabs->set_dirty ();
5100 resize_idle_id = -1;
5108 ENSURE_GUI_THREAD (*this, &Editor::located);
5111 playhead_cursor->set_position (_session->audible_frame ());
5112 if (_follow_playhead && !_pending_initial_locate) {
5113 reset_x_origin_to_follow_playhead ();
5117 _pending_locate_request = false;
5118 _pending_initial_locate = false;
5122 Editor::region_view_added (RegionView * rv)
5124 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5125 if (rv->region ()->id () == (*pr)) {
5126 selection->add (rv);
5127 selection->regions.pending.erase (pr);
5132 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5134 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5135 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5136 if (rv->region()->id () == (*rnote).first) {
5137 mrv->select_notes ((*rnote).second);
5138 selection->pending_midi_note_selection.erase(rnote);
5144 _summary->set_background_dirty ();
5148 Editor::region_view_removed ()
5150 _summary->set_background_dirty ();
5154 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5156 TrackViewList::const_iterator j = track_views.begin ();
5157 while (j != track_views.end()) {
5158 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5159 if (rtv && rtv->route() == r) {
5170 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5174 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5175 TimeAxisView* tv = axis_view_from_route (*i);
5185 Editor::suspend_route_redisplay ()
5188 _routes->suspend_redisplay();
5193 Editor::resume_route_redisplay ()
5196 _routes->redisplay(); // queue redisplay
5197 _routes->resume_redisplay();
5202 Editor::add_routes (RouteList& routes)
5204 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5206 RouteTimeAxisView *rtv;
5207 list<RouteTimeAxisView*> new_views;
5208 TrackViewList new_selection;
5209 bool from_scratch = (track_views.size() == 0);
5211 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5212 boost::shared_ptr<Route> route = (*x);
5214 if (route->is_auditioner() || route->is_monitor()) {
5218 DataType dt = route->input()->default_type();
5220 if (dt == ARDOUR::DataType::AUDIO) {
5221 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5222 rtv->set_route (route);
5223 } else if (dt == ARDOUR::DataType::MIDI) {
5224 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5225 rtv->set_route (route);
5227 throw unknown_type();
5230 new_views.push_back (rtv);
5231 track_views.push_back (rtv);
5232 new_selection.push_back (rtv);
5234 rtv->effective_gain_display ();
5236 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5237 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5240 if (new_views.size() > 0) {
5241 _routes->routes_added (new_views);
5242 _summary->routes_added (new_views);
5245 if (!from_scratch) {
5246 selection->tracks.clear();
5247 selection->add (new_selection);
5248 begin_selection_op_history();
5251 if (show_editor_mixer_when_tracks_arrive) {
5252 show_editor_mixer (true);
5255 editor_list_button.set_sensitive (true);
5259 Editor::timeaxisview_deleted (TimeAxisView *tv)
5261 if (tv == entered_track) {
5265 if (_session && _session->deletion_in_progress()) {
5266 /* the situation is under control */
5270 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5272 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5274 _routes->route_removed (tv);
5276 TimeAxisView::Children c = tv->get_child_list ();
5277 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5278 if (entered_track == i->get()) {
5283 /* remove it from the list of track views */
5285 TrackViewList::iterator i;
5287 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5288 i = track_views.erase (i);
5291 /* update whatever the current mixer strip is displaying, if revelant */
5293 boost::shared_ptr<Route> route;
5296 route = rtav->route ();
5299 if (current_mixer_strip && current_mixer_strip->route() == route) {
5301 TimeAxisView* next_tv;
5303 if (track_views.empty()) {
5305 } else if (i == track_views.end()) {
5306 next_tv = track_views.front();
5313 set_selected_mixer_strip (*next_tv);
5315 /* make the editor mixer strip go away setting the
5316 * button to inactive (which also unticks the menu option)
5319 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5325 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5327 if (apply_to_selection) {
5328 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5330 TrackSelection::iterator j = i;
5333 hide_track_in_display (*i, false);
5338 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5340 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5341 // this will hide the mixer strip
5342 set_selected_mixer_strip (*tv);
5345 _routes->hide_track_in_display (*tv);
5350 Editor::sync_track_view_list_and_routes ()
5352 track_views = TrackViewList (_routes->views ());
5354 _summary->set_background_dirty();
5355 _group_tabs->set_dirty ();
5357 return false; // do not call again (until needed)
5361 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5363 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5368 /** Find a RouteTimeAxisView by the ID of its route */
5370 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5372 RouteTimeAxisView* v;
5374 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5375 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5376 if(v->route()->id() == id) {
5386 Editor::fit_route_group (RouteGroup *g)
5388 TrackViewList ts = axis_views_from_routes (g->route_list ());
5393 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5395 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5398 _session->cancel_audition ();
5402 if (_session->is_auditioning()) {
5403 _session->cancel_audition ();
5404 if (r == last_audition_region) {
5409 _session->audition_region (r);
5410 last_audition_region = r;
5415 Editor::hide_a_region (boost::shared_ptr<Region> r)
5417 r->set_hidden (true);
5421 Editor::show_a_region (boost::shared_ptr<Region> r)
5423 r->set_hidden (false);
5427 Editor::audition_region_from_region_list ()
5429 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5433 Editor::hide_region_from_region_list ()
5435 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5439 Editor::show_region_in_region_list ()
5441 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5445 Editor::step_edit_status_change (bool yn)
5448 start_step_editing ();
5450 stop_step_editing ();
5455 Editor::start_step_editing ()
5457 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5461 Editor::stop_step_editing ()
5463 step_edit_connection.disconnect ();
5467 Editor::check_step_edit ()
5469 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5470 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5472 mtv->check_step_edit ();
5476 return true; // do it again, till we stop
5480 Editor::scroll_press (Direction dir)
5482 ++_scroll_callbacks;
5484 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5485 /* delay the first auto-repeat */
5491 scroll_backward (1);
5499 scroll_up_one_track ();
5503 scroll_down_one_track ();
5507 /* do hacky auto-repeat */
5508 if (!_scroll_connection.connected ()) {
5510 _scroll_connection = Glib::signal_timeout().connect (
5511 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5514 _scroll_callbacks = 0;
5521 Editor::scroll_release ()
5523 _scroll_connection.disconnect ();
5526 /** Queue a change for the Editor viewport x origin to follow the playhead */
5528 Editor::reset_x_origin_to_follow_playhead ()
5530 framepos_t const frame = playhead_cursor->current_frame ();
5532 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5534 if (_session->transport_speed() < 0) {
5536 if (frame > (current_page_samples() / 2)) {
5537 center_screen (frame-(current_page_samples()/2));
5539 center_screen (current_page_samples()/2);
5546 if (frame < leftmost_frame) {
5548 if (_session->transport_rolling()) {
5549 /* rolling; end up with the playhead at the right of the page */
5550 l = frame - current_page_samples ();
5552 /* not rolling: end up with the playhead 1/4 of the way along the page */
5553 l = frame - current_page_samples() / 4;
5557 if (_session->transport_rolling()) {
5558 /* rolling: end up with the playhead on the left of the page */
5561 /* not rolling: end up with the playhead 3/4 of the way along the page */
5562 l = frame - 3 * current_page_samples() / 4;
5570 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5576 Editor::super_rapid_screen_update ()
5578 if (!_session || !_session->engine().running()) {
5582 /* METERING / MIXER STRIPS */
5584 /* update track meters, if required */
5585 if (contents().is_mapped() && meters_running) {
5586 RouteTimeAxisView* rtv;
5587 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5588 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5589 rtv->fast_update ();
5594 /* and any current mixer strip */
5595 if (current_mixer_strip) {
5596 current_mixer_strip->fast_update ();
5599 /* PLAYHEAD AND VIEWPORT */
5601 framepos_t const frame = _session->audible_frame();
5603 /* There are a few reasons why we might not update the playhead / viewport stuff:
5605 * 1. we don't update things when there's a pending locate request, otherwise
5606 * when the editor requests a locate there is a chance that this method
5607 * will move the playhead before the locate request is processed, causing
5609 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5610 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5613 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5615 last_update_frame = frame;
5617 if (!_dragging_playhead) {
5618 playhead_cursor->set_position (frame);
5621 if (!_stationary_playhead) {
5623 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5624 /* We only do this if we aren't already
5625 handling a visual change (ie if
5626 pending_visual_change.being_handled is
5627 false) so that these requests don't stack
5628 up there are too many of them to handle in
5631 reset_x_origin_to_follow_playhead ();
5636 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5637 framepos_t const frame = playhead_cursor->current_frame ();
5638 double target = ((double)frame - (double)current_page_samples()/2.0);
5639 if (target <= 0.0) {
5642 // compare to EditorCursor::set_position()
5643 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5644 double const new_pos = sample_to_pixel_unrounded (target);
5645 if (rint (new_pos) != rint (old_pos)) {
5646 reset_x_origin (pixel_to_sample (floor (new_pos)));
5657 Editor::session_going_away ()
5659 _have_idled = false;
5661 _session_connections.drop_connections ();
5663 super_rapid_screen_update_connection.disconnect ();
5665 selection->clear ();
5666 cut_buffer->clear ();
5668 clicked_regionview = 0;
5669 clicked_axisview = 0;
5670 clicked_routeview = 0;
5671 entered_regionview = 0;
5673 last_update_frame = 0;
5676 playhead_cursor->hide ();
5678 /* rip everything out of the list displays */
5682 _route_groups->clear ();
5684 /* do this first so that deleting a track doesn't reset cms to null
5685 and thus cause a leak.
5688 if (current_mixer_strip) {
5689 if (current_mixer_strip->get_parent() != 0) {
5690 global_hpacker.remove (*current_mixer_strip);
5692 delete current_mixer_strip;
5693 current_mixer_strip = 0;
5696 /* delete all trackviews */
5698 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5701 track_views.clear ();
5703 nudge_clock->set_session (0);
5705 editor_list_button.set_active(false);
5706 editor_list_button.set_sensitive(false);
5708 /* clear tempo/meter rulers */
5709 remove_metric_marks ();
5711 clear_marker_display ();
5713 stop_step_editing ();
5717 /* get rid of any existing editor mixer strip */
5719 WindowTitle title(Glib::get_application_name());
5720 title += _("Editor");
5722 own_window()->set_title (title.get_string());
5725 SessionHandlePtr::session_going_away ();
5729 Editor::trigger_script (int i)
5731 LuaInstance::instance()-> call_action (i);
5735 Editor::set_script_action_name (int i, const std::string& n)
5737 string const a = string_compose (X_("script-action-%1"), i + 1);
5738 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5741 act->set_label (string_compose (_("Unset #%1"), i + 1));
5742 act->set_tooltip (_("no action bound"));
5743 act->set_sensitive (false);
5746 act->set_tooltip (n);
5747 act->set_sensitive (true);
5749 KeyEditor::UpdateBindings ();
5753 Editor::show_editor_list (bool yn)
5756 _the_notebook.show ();
5758 _the_notebook.hide ();
5763 Editor::change_region_layering_order (bool from_context_menu)
5765 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5767 if (!clicked_routeview) {
5768 if (layering_order_editor) {
5769 layering_order_editor->hide ();
5774 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5780 boost::shared_ptr<Playlist> pl = track->playlist();
5786 if (layering_order_editor == 0) {
5787 layering_order_editor = new RegionLayeringOrderEditor (*this);
5790 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5791 layering_order_editor->maybe_present ();
5795 Editor::update_region_layering_order_editor ()
5797 if (layering_order_editor && layering_order_editor->is_visible ()) {
5798 change_region_layering_order (true);
5803 Editor::setup_fade_images ()
5805 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5806 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5807 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5808 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5809 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5811 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5812 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5813 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5814 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5815 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5817 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5818 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5819 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5820 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5821 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5823 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5824 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5825 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5826 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5827 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5831 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5833 Editor::action_menu_item (std::string const & name)
5835 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5838 return *manage (a->create_menu_item ());
5842 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5844 EventBox* b = manage (new EventBox);
5845 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5846 Label* l = manage (new Label (name));
5850 _the_notebook.append_page (widget, *b);
5854 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5856 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5857 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5860 if (ev->type == GDK_2BUTTON_PRESS) {
5862 /* double-click on a notebook tab shrinks or expands the notebook */
5864 if (_notebook_shrunk) {
5865 if (pre_notebook_shrink_pane_width) {
5866 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5868 _notebook_shrunk = false;
5870 pre_notebook_shrink_pane_width = edit_pane.get_position();
5872 /* this expands the LHS of the edit pane to cover the notebook
5873 PAGE but leaves the tabs visible.
5875 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5876 _notebook_shrunk = true;
5884 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5886 using namespace Menu_Helpers;
5888 MenuList& items = _control_point_context_menu.items ();
5891 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5892 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5893 if (!can_remove_control_point (item)) {
5894 items.back().set_sensitive (false);
5897 _control_point_context_menu.popup (event->button.button, event->button.time);
5901 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5903 using namespace Menu_Helpers;
5905 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5910 /* We need to get the selection here and pass it to the operations, since
5911 popping up the menu will cause a region leave event which clears
5912 entered_regionview. */
5914 MidiRegionView& mrv = note->region_view();
5915 const RegionSelection rs = get_regions_from_selection_and_entered ();
5916 const uint32_t sel_size = mrv.selection_size ();
5918 MenuList& items = _note_context_menu.items();
5922 items.push_back(MenuElem(_("Delete"),
5923 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5926 items.push_back(MenuElem(_("Edit..."),
5927 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5928 if (sel_size != 1) {
5929 items.back().set_sensitive (false);
5932 items.push_back(MenuElem(_("Transpose..."),
5933 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5936 items.push_back(MenuElem(_("Legatize"),
5937 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5939 items.back().set_sensitive (false);
5942 items.push_back(MenuElem(_("Quantize..."),
5943 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5945 items.push_back(MenuElem(_("Remove Overlap"),
5946 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5948 items.back().set_sensitive (false);
5951 items.push_back(MenuElem(_("Transform..."),
5952 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5954 _note_context_menu.popup (event->button.button, event->button.time);
5958 Editor::zoom_vertical_modifier_released()
5960 _stepping_axis_view = 0;
5964 Editor::ui_parameter_changed (string parameter)
5966 if (parameter == "icon-set") {
5967 while (!_cursor_stack.empty()) {
5968 _cursor_stack.pop_back();
5970 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5971 _cursor_stack.push_back(_cursors->grabber);
5972 } else if (parameter == "draggable-playhead") {
5973 if (_verbose_cursor) {
5974 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5980 Editor::use_own_window (bool and_fill_it)
5982 bool new_window = !own_window();
5984 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5986 if (win && new_window) {
5987 win->set_name ("EditorWindow");
5989 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5991 // win->signal_realize().connect (*this, &Editor::on_realize);
5992 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
5993 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
5994 win->set_data ("ardour-bindings", bindings);
5999 DisplaySuspender ds;
6000 contents().show_all ();
6002 /* XXX: this is a bit unfortunate; it would probably
6003 be nicer if we could just call show () above rather
6004 than needing the show_all ()
6007 /* re-hide stuff if necessary */
6008 editor_list_button_toggled ();
6009 parameter_changed ("show-summary");
6010 parameter_changed ("show-group-tabs");
6011 parameter_changed ("show-zoom-tools");
6013 /* now reset all audio_time_axis heights, because widgets might need
6019 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6020 tv = (static_cast<TimeAxisView*>(*i));
6021 tv->reset_height ();
6024 if (current_mixer_strip) {
6025 current_mixer_strip->hide_things ();
6026 current_mixer_strip->parameter_changed ("mixer-element-visibility");