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->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1369 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1370 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1371 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1372 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1373 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1374 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1376 playhead_cursor->show ();
1378 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1379 Config->map_parameters (pc);
1380 _session->config.map_parameters (pc);
1382 restore_ruler_visibility ();
1383 //tempo_map_changed (PropertyChange (0));
1384 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1386 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1387 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1390 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1391 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1394 switch (_snap_type) {
1395 case SnapToRegionStart:
1396 case SnapToRegionEnd:
1397 case SnapToRegionSync:
1398 case SnapToRegionBoundary:
1399 build_region_boundary_cache ();
1406 /* register for undo history */
1407 _session->register_with_memento_command_factory(id(), this);
1408 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1410 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1412 LuaInstance::instance()->set_session(_session);
1414 start_updating_meters ();
1418 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1420 if (a->get_name() == "RegionMenu") {
1421 /* When the main menu's region menu is opened, we setup the actions so that they look right
1422 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1423 so we resensitize all region actions when the entered regionview or the region selection
1424 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1425 happens after the region context menu is opened. So we set a flag here, too.
1429 sensitize_the_right_region_actions ();
1430 _last_region_menu_was_main = true;
1435 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1437 using namespace Menu_Helpers;
1439 void (Editor::*emf)(FadeShape);
1440 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1443 images = &_xfade_in_images;
1444 emf = &Editor::set_fade_in_shape;
1446 images = &_xfade_out_images;
1447 emf = &Editor::set_fade_out_shape;
1452 _("Linear (for highly correlated material)"),
1453 *(*images)[FadeLinear],
1454 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1458 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1462 _("Constant power"),
1463 *(*images)[FadeConstantPower],
1464 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1467 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1472 *(*images)[FadeSymmetric],
1473 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1477 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1482 *(*images)[FadeSlow],
1483 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1486 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1491 *(*images)[FadeFast],
1492 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1495 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1498 /** Pop up a context menu for when the user clicks on a start crossfade */
1500 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1502 using namespace Menu_Helpers;
1503 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1508 MenuList& items (xfade_in_context_menu.items());
1511 if (arv->audio_region()->fade_in_active()) {
1512 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1514 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1517 items.push_back (SeparatorElem());
1518 fill_xfade_menu (items, true);
1520 xfade_in_context_menu.popup (button, time);
1523 /** Pop up a context menu for when the user clicks on an end crossfade */
1525 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1527 using namespace Menu_Helpers;
1528 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1533 MenuList& items (xfade_out_context_menu.items());
1536 if (arv->audio_region()->fade_out_active()) {
1537 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1539 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1542 items.push_back (SeparatorElem());
1543 fill_xfade_menu (items, false);
1545 xfade_out_context_menu.popup (button, time);
1549 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1551 using namespace Menu_Helpers;
1552 Menu* (Editor::*build_menu_function)();
1555 switch (item_type) {
1557 case RegionViewName:
1558 case RegionViewNameHighlight:
1559 case LeftFrameHandle:
1560 case RightFrameHandle:
1561 if (with_selection) {
1562 build_menu_function = &Editor::build_track_selection_context_menu;
1564 build_menu_function = &Editor::build_track_region_context_menu;
1569 if (with_selection) {
1570 build_menu_function = &Editor::build_track_selection_context_menu;
1572 build_menu_function = &Editor::build_track_context_menu;
1577 if (clicked_routeview->track()) {
1578 build_menu_function = &Editor::build_track_context_menu;
1580 build_menu_function = &Editor::build_track_bus_context_menu;
1585 /* probably shouldn't happen but if it does, we don't care */
1589 menu = (this->*build_menu_function)();
1590 menu->set_name ("ArdourContextMenu");
1592 /* now handle specific situations */
1594 switch (item_type) {
1596 case RegionViewName:
1597 case RegionViewNameHighlight:
1598 case LeftFrameHandle:
1599 case RightFrameHandle:
1600 if (!with_selection) {
1601 if (region_edit_menu_split_item) {
1602 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1603 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1605 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1608 if (region_edit_menu_split_multichannel_item) {
1609 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1610 region_edit_menu_split_multichannel_item->set_sensitive (true);
1612 region_edit_menu_split_multichannel_item->set_sensitive (false);
1625 /* probably shouldn't happen but if it does, we don't care */
1629 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1631 /* Bounce to disk */
1633 using namespace Menu_Helpers;
1634 MenuList& edit_items = menu->items();
1636 edit_items.push_back (SeparatorElem());
1638 switch (clicked_routeview->audio_track()->freeze_state()) {
1639 case AudioTrack::NoFreeze:
1640 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1643 case AudioTrack::Frozen:
1644 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1647 case AudioTrack::UnFrozen:
1648 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1654 if (item_type == StreamItem && clicked_routeview) {
1655 clicked_routeview->build_underlay_menu(menu);
1658 /* When the region menu is opened, we setup the actions so that they look right
1661 sensitize_the_right_region_actions ();
1662 _last_region_menu_was_main = false;
1664 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1665 menu->popup (button, time);
1669 Editor::build_track_context_menu ()
1671 using namespace Menu_Helpers;
1673 MenuList& edit_items = track_context_menu.items();
1676 add_dstream_context_items (edit_items);
1677 return &track_context_menu;
1681 Editor::build_track_bus_context_menu ()
1683 using namespace Menu_Helpers;
1685 MenuList& edit_items = track_context_menu.items();
1688 add_bus_context_items (edit_items);
1689 return &track_context_menu;
1693 Editor::build_track_region_context_menu ()
1695 using namespace Menu_Helpers;
1696 MenuList& edit_items = track_region_context_menu.items();
1699 /* we've just cleared the track region context menu, so the menu that these
1700 two items were on will have disappeared; stop them dangling.
1702 region_edit_menu_split_item = 0;
1703 region_edit_menu_split_multichannel_item = 0;
1705 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1708 boost::shared_ptr<Track> tr;
1709 boost::shared_ptr<Playlist> pl;
1711 if ((tr = rtv->track())) {
1712 add_region_context_items (edit_items, tr);
1716 add_dstream_context_items (edit_items);
1718 return &track_region_context_menu;
1722 Editor::loudness_analyze_region_selection ()
1727 Selection& s (PublicEditor::instance ().get_selection ());
1728 RegionSelection ars = s.regions;
1729 ARDOUR::AnalysisGraph ag (_session);
1730 framecnt_t total_work = 0;
1732 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1733 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1737 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1740 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1741 total_work += arv->region ()->length ();
1744 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1746 ag.set_total_frames (total_work);
1747 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1750 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1751 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1755 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1759 ag.analyze_region (ar);
1762 if (!ag.canceled ()) {
1763 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1769 Editor::loudness_analyze_range_selection ()
1774 Selection& s (PublicEditor::instance ().get_selection ());
1775 TimeSelection ts = s.time;
1776 ARDOUR::AnalysisGraph ag (_session);
1777 framecnt_t total_work = 0;
1779 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1780 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1784 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1788 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1789 total_work += j->length ();
1793 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1795 ag.set_total_frames (total_work);
1796 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1799 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1800 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1804 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1808 ag.analyze_range (rui->route (), pl, ts);
1811 if (!ag.canceled ()) {
1812 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1818 Editor::spectral_analyze_region_selection ()
1820 if (analysis_window == 0) {
1821 analysis_window = new AnalysisWindow();
1824 analysis_window->set_session(_session);
1826 analysis_window->show_all();
1829 analysis_window->set_regionmode();
1830 analysis_window->analyze();
1832 analysis_window->present();
1836 Editor::spectral_analyze_range_selection()
1838 if (analysis_window == 0) {
1839 analysis_window = new AnalysisWindow();
1842 analysis_window->set_session(_session);
1844 analysis_window->show_all();
1847 analysis_window->set_rangemode();
1848 analysis_window->analyze();
1850 analysis_window->present();
1854 Editor::build_track_selection_context_menu ()
1856 using namespace Menu_Helpers;
1857 MenuList& edit_items = track_selection_context_menu.items();
1858 edit_items.clear ();
1860 add_selection_context_items (edit_items);
1861 // edit_items.push_back (SeparatorElem());
1862 // add_dstream_context_items (edit_items);
1864 return &track_selection_context_menu;
1868 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1870 using namespace Menu_Helpers;
1872 /* OK, stick the region submenu at the top of the list, and then add
1876 RegionSelection rs = get_regions_from_selection_and_entered ();
1878 string::size_type pos = 0;
1879 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1881 /* we have to hack up the region name because "_" has a special
1882 meaning for menu titles.
1885 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1886 menu_item_name.replace (pos, 1, "__");
1890 if (_popup_region_menu_item == 0) {
1891 _popup_region_menu_item = new MenuItem (menu_item_name);
1892 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1893 _popup_region_menu_item->show ();
1895 _popup_region_menu_item->set_label (menu_item_name);
1898 /* No latering allowed in later is higher layering model */
1899 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1900 if (act && Config->get_layer_model() == LaterHigher) {
1901 act->set_sensitive (false);
1903 act->set_sensitive (true);
1906 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1908 edit_items.push_back (*_popup_region_menu_item);
1909 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1910 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1912 edit_items.push_back (SeparatorElem());
1915 /** Add context menu items relevant to selection ranges.
1916 * @param edit_items List to add the items to.
1919 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1921 using namespace Menu_Helpers;
1923 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1924 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1926 edit_items.push_back (SeparatorElem());
1927 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1929 edit_items.push_back (SeparatorElem());
1930 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1931 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1933 edit_items.push_back (SeparatorElem());
1935 edit_items.push_back (
1937 _("Move Range Start to Previous Region Boundary"),
1938 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1942 edit_items.push_back (
1944 _("Move Range Start to Next Region Boundary"),
1945 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1949 edit_items.push_back (
1951 _("Move Range End to Previous Region Boundary"),
1952 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1956 edit_items.push_back (
1958 _("Move Range End to Next Region Boundary"),
1959 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1963 edit_items.push_back (SeparatorElem());
1964 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1965 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1967 edit_items.push_back (SeparatorElem());
1968 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1970 edit_items.push_back (SeparatorElem());
1971 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1972 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1973 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1975 edit_items.push_back (SeparatorElem());
1976 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1978 edit_items.push_back (SeparatorElem());
1979 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1980 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1982 edit_items.push_back (SeparatorElem());
1983 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1984 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1985 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1986 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1987 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1988 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1989 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1995 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1997 using namespace Menu_Helpers;
2001 Menu *play_menu = manage (new Menu);
2002 MenuList& play_items = play_menu->items();
2003 play_menu->set_name ("ArdourContextMenu");
2005 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2006 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2007 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2008 play_items.push_back (SeparatorElem());
2009 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2011 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2015 Menu *select_menu = manage (new Menu);
2016 MenuList& select_items = select_menu->items();
2017 select_menu->set_name ("ArdourContextMenu");
2019 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2020 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2021 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2022 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2023 select_items.push_back (SeparatorElem());
2024 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2025 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2026 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2027 select_items.push_back (SeparatorElem());
2028 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2029 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2030 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2031 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2032 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2033 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2034 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2036 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2040 Menu *cutnpaste_menu = manage (new Menu);
2041 MenuList& cutnpaste_items = cutnpaste_menu->items();
2042 cutnpaste_menu->set_name ("ArdourContextMenu");
2044 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2045 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2046 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2048 cutnpaste_items.push_back (SeparatorElem());
2050 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2051 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2053 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2055 /* Adding new material */
2057 edit_items.push_back (SeparatorElem());
2058 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2059 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2063 Menu *nudge_menu = manage (new Menu());
2064 MenuList& nudge_items = nudge_menu->items();
2065 nudge_menu->set_name ("ArdourContextMenu");
2067 edit_items.push_back (SeparatorElem());
2068 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2069 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2070 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2071 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2073 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2077 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2079 using namespace Menu_Helpers;
2083 Menu *play_menu = manage (new Menu);
2084 MenuList& play_items = play_menu->items();
2085 play_menu->set_name ("ArdourContextMenu");
2087 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2088 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2089 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2093 Menu *select_menu = manage (new Menu);
2094 MenuList& select_items = select_menu->items();
2095 select_menu->set_name ("ArdourContextMenu");
2097 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2098 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2099 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2100 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2101 select_items.push_back (SeparatorElem());
2102 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2103 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2104 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2105 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2107 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2111 Menu *cutnpaste_menu = manage (new Menu);
2112 MenuList& cutnpaste_items = cutnpaste_menu->items();
2113 cutnpaste_menu->set_name ("ArdourContextMenu");
2115 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2116 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2117 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2119 Menu *nudge_menu = manage (new Menu());
2120 MenuList& nudge_items = nudge_menu->items();
2121 nudge_menu->set_name ("ArdourContextMenu");
2123 edit_items.push_back (SeparatorElem());
2124 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2125 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2126 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2127 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2129 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2133 Editor::snap_type() const
2139 Editor::snap_mode() const
2145 Editor::set_snap_to (SnapType st)
2147 unsigned int snap_ind = (unsigned int)st;
2149 if (internal_editing()) {
2150 internal_snap_type = st;
2152 pre_internal_snap_type = st;
2157 if (snap_ind > snap_type_strings.size() - 1) {
2159 _snap_type = (SnapType)snap_ind;
2162 string str = snap_type_strings[snap_ind];
2164 if (str != snap_type_selector.get_text()) {
2165 snap_type_selector.set_text (str);
2170 switch (_snap_type) {
2171 case SnapToBeatDiv128:
2172 case SnapToBeatDiv64:
2173 case SnapToBeatDiv32:
2174 case SnapToBeatDiv28:
2175 case SnapToBeatDiv24:
2176 case SnapToBeatDiv20:
2177 case SnapToBeatDiv16:
2178 case SnapToBeatDiv14:
2179 case SnapToBeatDiv12:
2180 case SnapToBeatDiv10:
2181 case SnapToBeatDiv8:
2182 case SnapToBeatDiv7:
2183 case SnapToBeatDiv6:
2184 case SnapToBeatDiv5:
2185 case SnapToBeatDiv4:
2186 case SnapToBeatDiv3:
2187 case SnapToBeatDiv2: {
2188 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2189 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2191 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2192 current_bbt_points_begin, current_bbt_points_end);
2193 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2194 current_bbt_points_begin, current_bbt_points_end);
2195 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2199 case SnapToRegionStart:
2200 case SnapToRegionEnd:
2201 case SnapToRegionSync:
2202 case SnapToRegionBoundary:
2203 build_region_boundary_cache ();
2211 redisplay_tempo (false);
2213 SnapChanged (); /* EMIT SIGNAL */
2217 Editor::set_snap_mode (SnapMode mode)
2219 string str = snap_mode_strings[(int)mode];
2221 if (internal_editing()) {
2222 internal_snap_mode = mode;
2224 pre_internal_snap_mode = mode;
2229 if (str != snap_mode_selector.get_text ()) {
2230 snap_mode_selector.set_text (str);
2237 Editor::set_edit_point_preference (EditPoint ep, bool force)
2239 bool changed = (_edit_point != ep);
2242 if (Profile->get_mixbus())
2243 if (ep == EditAtSelectedMarker)
2244 ep = EditAtPlayhead;
2246 string str = edit_point_strings[(int)ep];
2247 if (str != edit_point_selector.get_text ()) {
2248 edit_point_selector.set_text (str);
2251 update_all_enter_cursors();
2253 if (!force && !changed) {
2257 const char* action=NULL;
2259 switch (_edit_point) {
2260 case EditAtPlayhead:
2261 action = "edit-at-playhead";
2263 case EditAtSelectedMarker:
2264 action = "edit-at-marker";
2267 action = "edit-at-mouse";
2271 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2273 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2277 bool in_track_canvas;
2279 if (!mouse_frame (foo, in_track_canvas)) {
2280 in_track_canvas = false;
2283 reset_canvas_action_sensitivity (in_track_canvas);
2289 Editor::set_state (const XMLNode& node, int version)
2291 XMLProperty const * prop;
2293 PBD::Unwinder<bool> nsi (no_save_instant, true);
2295 Tabbable::set_state (node, version);
2297 if (_session && (prop = node.property ("playhead"))) {
2299 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2301 playhead_cursor->set_position (pos);
2303 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2304 playhead_cursor->set_position (0);
2307 playhead_cursor->set_position (0);
2310 if ((prop = node.property ("mixer-width"))) {
2311 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2314 if ((prop = node.property ("zoom-focus"))) {
2315 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2318 if ((prop = node.property ("zoom"))) {
2319 /* older versions of ardour used floating point samples_per_pixel */
2320 double f = PBD::atof (prop->value());
2321 reset_zoom (llrintf (f));
2323 reset_zoom (samples_per_pixel);
2326 if ((prop = node.property ("visible-track-count"))) {
2327 set_visible_track_count (PBD::atoi (prop->value()));
2330 if ((prop = node.property ("snap-to"))) {
2331 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2334 if ((prop = node.property ("snap-mode"))) {
2335 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2338 if ((prop = node.property ("internal-snap-to"))) {
2339 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2342 if ((prop = node.property ("internal-snap-mode"))) {
2343 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2346 if ((prop = node.property ("pre-internal-snap-to"))) {
2347 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2350 if ((prop = node.property ("pre-internal-snap-mode"))) {
2351 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2354 if ((prop = node.property ("mouse-mode"))) {
2355 MouseMode m = str2mousemode(prop->value());
2356 set_mouse_mode (m, true);
2358 set_mouse_mode (MouseObject, true);
2361 if ((prop = node.property ("left-frame")) != 0) {
2363 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2367 reset_x_origin (pos);
2371 if ((prop = node.property ("y-origin")) != 0) {
2372 reset_y_origin (atof (prop->value ()));
2375 if ((prop = node.property ("join-object-range"))) {
2376 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2377 bool yn = string_is_affirmative (prop->value());
2379 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2380 tact->set_active (!yn);
2381 tact->set_active (yn);
2383 set_mouse_mode(mouse_mode, true);
2386 if ((prop = node.property ("edit-point"))) {
2387 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2390 if ((prop = node.property ("show-measures"))) {
2391 bool yn = string_is_affirmative (prop->value());
2392 _show_measures = yn;
2395 if ((prop = node.property ("follow-playhead"))) {
2396 bool yn = string_is_affirmative (prop->value());
2397 set_follow_playhead (yn);
2400 if ((prop = node.property ("stationary-playhead"))) {
2401 bool yn = string_is_affirmative (prop->value());
2402 set_stationary_playhead (yn);
2405 if ((prop = node.property ("region-list-sort-type"))) {
2406 RegionListSortType st;
2407 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2410 if ((prop = node.property ("show-editor-mixer"))) {
2412 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2415 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2416 bool yn = string_is_affirmative (prop->value());
2418 /* do it twice to force the change */
2420 tact->set_active (!yn);
2421 tact->set_active (yn);
2424 if ((prop = node.property ("show-editor-list"))) {
2426 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2429 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2430 bool yn = string_is_affirmative (prop->value());
2432 /* do it twice to force the change */
2434 tact->set_active (!yn);
2435 tact->set_active (yn);
2438 if ((prop = node.property (X_("editor-list-page")))) {
2439 _the_notebook.set_current_page (atoi (prop->value ()));
2442 if ((prop = node.property (X_("show-marker-lines")))) {
2443 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2445 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2446 bool yn = string_is_affirmative (prop->value ());
2448 tact->set_active (!yn);
2449 tact->set_active (yn);
2452 XMLNodeList children = node.children ();
2453 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2454 selection->set_state (**i, Stateful::current_state_version);
2455 _regions->set_state (**i);
2458 if ((prop = node.property ("maximised"))) {
2459 bool yn = string_is_affirmative (prop->value());
2460 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2462 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2463 bool fs = tact && tact->get_active();
2465 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2469 if ((prop = node.property ("nudge-clock-value"))) {
2471 sscanf (prop->value().c_str(), "%" PRId64, &f);
2472 nudge_clock->set (f);
2474 nudge_clock->set_mode (AudioClock::Timecode);
2475 nudge_clock->set (_session->frame_rate() * 5, true);
2480 * Not all properties may have been in XML, but
2481 * those that are linked to a private variable may need changing
2486 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2488 yn = _show_measures;
2489 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2490 /* do it twice to force the change */
2491 tact->set_active (!yn);
2492 tact->set_active (yn);
2495 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2496 yn = _follow_playhead;
2498 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2499 if (tact->get_active() != yn) {
2500 tact->set_active (yn);
2504 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2505 yn = _stationary_playhead;
2507 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2508 if (tact->get_active() != yn) {
2509 tact->set_active (yn);
2514 return LuaInstance::instance()->set_state(node);
2518 Editor::get_state ()
2520 XMLNode* node = new XMLNode (X_("Editor"));
2523 id().print (buf, sizeof (buf));
2524 node->add_property ("id", buf);
2526 node->add_child_nocopy (Tabbable::get_state());
2528 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2529 node->add_property("edit-horizontal-pane-pos", string(buf));
2530 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2531 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2532 node->add_property("edit-vertical-pane-pos", string(buf));
2534 maybe_add_mixer_strip_width (*node);
2536 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2538 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2539 node->add_property ("zoom", buf);
2540 node->add_property ("snap-to", enum_2_string (_snap_type));
2541 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2542 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2543 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2544 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2545 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2546 node->add_property ("edit-point", enum_2_string (_edit_point));
2547 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2548 node->add_property ("visible-track-count", buf);
2550 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2551 node->add_property ("playhead", buf);
2552 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2553 node->add_property ("left-frame", buf);
2554 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2555 node->add_property ("y-origin", buf);
2557 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2558 node->add_property ("maximised", _maximised ? "yes" : "no");
2559 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2560 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2561 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2562 node->add_property ("mouse-mode", enum2str(mouse_mode));
2563 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2565 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2567 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2568 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2571 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2573 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2574 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2577 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2578 node->add_property (X_("editor-list-page"), buf);
2580 if (button_bindings) {
2581 XMLNode* bb = new XMLNode (X_("Buttons"));
2582 button_bindings->save (*bb);
2583 node->add_child_nocopy (*bb);
2586 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2588 node->add_child_nocopy (selection->get_state ());
2589 node->add_child_nocopy (_regions->get_state ());
2591 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2592 node->add_property ("nudge-clock-value", buf);
2594 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2595 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2600 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2601 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2603 * @return pair: TimeAxisView that y is over, layer index.
2605 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2606 * in stacked or expanded region display mode, otherwise 0.
2608 std::pair<TimeAxisView *, double>
2609 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2611 if (!trackview_relative_offset) {
2612 y -= _trackview_group->canvas_origin().y;
2616 return std::make_pair ( (TimeAxisView *) 0, 0);
2619 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2621 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2628 return std::make_pair ( (TimeAxisView *) 0, 0);
2631 /** Snap a position to the grid, if appropriate, taking into account current
2632 * grid settings and also the state of any snap modifier keys that may be pressed.
2633 * @param start Position to snap.
2634 * @param event Event to get current key modifier information from, or 0.
2637 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2639 if (!_session || !event) {
2643 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2644 if (_snap_mode == SnapOff) {
2645 snap_to_internal (start, direction, for_mark);
2648 if (_snap_mode != SnapOff) {
2649 snap_to_internal (start, direction, for_mark);
2650 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2651 /* SnapOff, but we pressed the snap_delta modifier */
2652 snap_to_internal (start, direction, for_mark);
2658 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2660 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2664 snap_to_internal (start, direction, for_mark, ensure_snap);
2668 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2670 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2671 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2673 switch (_snap_type) {
2674 case SnapToTimecodeFrame:
2675 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2676 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2677 /* start is already on a whole timecode frame, do nothing */
2678 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2679 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2681 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2685 case SnapToTimecodeSeconds:
2686 if (_session->config.get_timecode_offset_negative()) {
2687 start += _session->config.get_timecode_offset ();
2689 start -= _session->config.get_timecode_offset ();
2691 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2692 (start % one_timecode_second == 0)) {
2693 /* start is already on a whole second, do nothing */
2694 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2695 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2697 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2700 if (_session->config.get_timecode_offset_negative()) {
2701 start -= _session->config.get_timecode_offset ();
2703 start += _session->config.get_timecode_offset ();
2707 case SnapToTimecodeMinutes:
2708 if (_session->config.get_timecode_offset_negative()) {
2709 start += _session->config.get_timecode_offset ();
2711 start -= _session->config.get_timecode_offset ();
2713 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2714 (start % one_timecode_minute == 0)) {
2715 /* start is already on a whole minute, do nothing */
2716 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2717 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2719 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2721 if (_session->config.get_timecode_offset_negative()) {
2722 start -= _session->config.get_timecode_offset ();
2724 start += _session->config.get_timecode_offset ();
2728 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2729 abort(); /*NOTREACHED*/
2734 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2736 const framepos_t one_second = _session->frame_rate();
2737 const framepos_t one_minute = _session->frame_rate() * 60;
2738 framepos_t presnap = start;
2742 switch (_snap_type) {
2743 case SnapToTimecodeFrame:
2744 case SnapToTimecodeSeconds:
2745 case SnapToTimecodeMinutes:
2746 return timecode_snap_to_internal (start, direction, for_mark);
2749 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2750 start % (one_second/75) == 0) {
2751 /* start is already on a whole CD frame, do nothing */
2752 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2753 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2755 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2760 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2761 start % one_second == 0) {
2762 /* start is already on a whole second, do nothing */
2763 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2764 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2766 start = (framepos_t) floor ((double) start / one_second) * one_second;
2771 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2772 start % one_minute == 0) {
2773 /* start is already on a whole minute, do nothing */
2774 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2775 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2777 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2782 start = _session->tempo_map().round_to_bar (start, direction);
2786 start = _session->tempo_map().round_to_beat (start, direction);
2789 case SnapToBeatDiv128:
2790 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2792 case SnapToBeatDiv64:
2793 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2795 case SnapToBeatDiv32:
2796 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2798 case SnapToBeatDiv28:
2799 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2801 case SnapToBeatDiv24:
2802 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2804 case SnapToBeatDiv20:
2805 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2807 case SnapToBeatDiv16:
2808 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2810 case SnapToBeatDiv14:
2811 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2813 case SnapToBeatDiv12:
2814 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2816 case SnapToBeatDiv10:
2817 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2819 case SnapToBeatDiv8:
2820 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2822 case SnapToBeatDiv7:
2823 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2825 case SnapToBeatDiv6:
2826 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2828 case SnapToBeatDiv5:
2829 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2831 case SnapToBeatDiv4:
2832 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2834 case SnapToBeatDiv3:
2835 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2837 case SnapToBeatDiv2:
2838 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2846 _session->locations()->marks_either_side (start, before, after);
2848 if (before == max_framepos && after == max_framepos) {
2849 /* No marks to snap to, so just don't snap */
2851 } else if (before == max_framepos) {
2853 } else if (after == max_framepos) {
2855 } else if (before != max_framepos && after != max_framepos) {
2856 /* have before and after */
2857 if ((start - before) < (after - start)) {
2866 case SnapToRegionStart:
2867 case SnapToRegionEnd:
2868 case SnapToRegionSync:
2869 case SnapToRegionBoundary:
2870 if (!region_boundary_cache.empty()) {
2872 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2873 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2875 if (direction > 0) {
2876 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2878 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2881 if (next != region_boundary_cache.begin ()) {
2886 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2887 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2889 if (start > (p + n) / 2) {
2898 switch (_snap_mode) {
2908 if (presnap > start) {
2909 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2913 } else if (presnap < start) {
2914 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2920 /* handled at entry */
2928 Editor::setup_toolbar ()
2930 HBox* mode_box = manage(new HBox);
2931 mode_box->set_border_width (2);
2932 mode_box->set_spacing(2);
2934 HBox* mouse_mode_box = manage (new HBox);
2935 HBox* mouse_mode_hbox = manage (new HBox);
2936 VBox* mouse_mode_vbox = manage (new VBox);
2937 Alignment* mouse_mode_align = manage (new Alignment);
2939 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2940 mouse_mode_size_group->add_widget (smart_mode_button);
2941 mouse_mode_size_group->add_widget (mouse_move_button);
2942 mouse_mode_size_group->add_widget (mouse_cut_button);
2943 mouse_mode_size_group->add_widget (mouse_select_button);
2944 mouse_mode_size_group->add_widget (mouse_timefx_button);
2945 mouse_mode_size_group->add_widget (mouse_audition_button);
2946 mouse_mode_size_group->add_widget (mouse_draw_button);
2947 mouse_mode_size_group->add_widget (mouse_content_button);
2949 mouse_mode_size_group->add_widget (zoom_in_button);
2950 mouse_mode_size_group->add_widget (zoom_out_button);
2951 mouse_mode_size_group->add_widget (zoom_preset_selector);
2952 mouse_mode_size_group->add_widget (zoom_out_full_button);
2953 mouse_mode_size_group->add_widget (zoom_focus_selector);
2955 mouse_mode_size_group->add_widget (tav_shrink_button);
2956 mouse_mode_size_group->add_widget (tav_expand_button);
2957 mouse_mode_size_group->add_widget (visible_tracks_selector);
2959 mouse_mode_size_group->add_widget (snap_type_selector);
2960 mouse_mode_size_group->add_widget (snap_mode_selector);
2962 mouse_mode_size_group->add_widget (edit_point_selector);
2963 mouse_mode_size_group->add_widget (edit_mode_selector);
2965 mouse_mode_size_group->add_widget (*nudge_clock);
2966 mouse_mode_size_group->add_widget (nudge_forward_button);
2967 mouse_mode_size_group->add_widget (nudge_backward_button);
2969 mouse_mode_hbox->set_spacing (2);
2971 if (!ARDOUR::Profile->get_trx()) {
2972 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2975 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2976 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2978 if (!ARDOUR::Profile->get_mixbus()) {
2979 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2982 if (!ARDOUR::Profile->get_trx()) {
2983 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2984 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2985 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2986 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2989 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2991 mouse_mode_align->add (*mouse_mode_vbox);
2992 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2994 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2996 edit_mode_selector.set_name ("mouse mode button");
2998 if (!ARDOUR::Profile->get_trx()) {
2999 mode_box->pack_start (edit_mode_selector, false, false);
3002 mode_box->pack_start (*mouse_mode_box, false, false);
3006 _zoom_box.set_spacing (2);
3007 _zoom_box.set_border_width (2);
3011 zoom_preset_selector.set_name ("zoom button");
3012 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3013 zoom_preset_selector.set_size_request (42, -1);
3015 zoom_in_button.set_name ("zoom button");
3016 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3017 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3018 zoom_in_button.set_related_action (act);
3020 zoom_out_button.set_name ("zoom button");
3021 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3022 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3023 zoom_out_button.set_related_action (act);
3025 zoom_out_full_button.set_name ("zoom button");
3026 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3027 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3028 zoom_out_full_button.set_related_action (act);
3030 zoom_focus_selector.set_name ("zoom button");
3032 if (ARDOUR::Profile->get_mixbus()) {
3033 _zoom_box.pack_start (zoom_preset_selector, false, false);
3034 } else if (ARDOUR::Profile->get_trx()) {
3035 mode_box->pack_start (zoom_out_button, false, false);
3036 mode_box->pack_start (zoom_in_button, false, false);
3038 _zoom_box.pack_start (zoom_out_button, false, false);
3039 _zoom_box.pack_start (zoom_in_button, false, false);
3040 _zoom_box.pack_start (zoom_out_full_button, false, false);
3041 _zoom_box.pack_start (zoom_focus_selector, false, false);
3044 /* Track zoom buttons */
3045 visible_tracks_selector.set_name ("zoom button");
3046 if (Profile->get_mixbus()) {
3047 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3048 visible_tracks_selector.set_size_request (42, -1);
3050 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3053 tav_expand_button.set_name ("zoom button");
3054 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3055 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3056 tav_expand_button.set_related_action (act);
3058 tav_shrink_button.set_name ("zoom button");
3059 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3060 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3061 tav_shrink_button.set_related_action (act);
3063 if (ARDOUR::Profile->get_mixbus()) {
3064 _zoom_box.pack_start (visible_tracks_selector);
3065 } else if (ARDOUR::Profile->get_trx()) {
3066 _zoom_box.pack_start (tav_shrink_button);
3067 _zoom_box.pack_start (tav_expand_button);
3069 _zoom_box.pack_start (visible_tracks_selector);
3070 _zoom_box.pack_start (tav_shrink_button);
3071 _zoom_box.pack_start (tav_expand_button);
3074 snap_box.set_spacing (2);
3075 snap_box.set_border_width (2);
3077 snap_type_selector.set_name ("mouse mode button");
3079 snap_mode_selector.set_name ("mouse mode button");
3081 edit_point_selector.set_name ("mouse mode button");
3083 snap_box.pack_start (snap_mode_selector, false, false);
3084 snap_box.pack_start (snap_type_selector, false, false);
3085 snap_box.pack_start (edit_point_selector, false, false);
3089 HBox *nudge_box = manage (new HBox);
3090 nudge_box->set_spacing (2);
3091 nudge_box->set_border_width (2);
3093 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3094 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3096 nudge_box->pack_start (nudge_backward_button, false, false);
3097 nudge_box->pack_start (nudge_forward_button, false, false);
3098 nudge_box->pack_start (*nudge_clock, false, false);
3101 /* Pack everything in... */
3103 HBox* hbox = manage (new HBox);
3104 hbox->set_spacing(2);
3106 toolbar_hbox.set_spacing (2);
3107 toolbar_hbox.set_border_width (1);
3109 toolbar_hbox.pack_start (*mode_box, false, false);
3110 if (!ARDOUR::Profile->get_trx()) {
3111 toolbar_hbox.pack_start (_zoom_box, false, false);
3112 toolbar_hbox.pack_start (*hbox, false, false);
3115 if (!ARDOUR::Profile->get_trx()) {
3116 hbox->pack_start (snap_box, false, false);
3117 hbox->pack_start (*nudge_box, false, false);
3122 toolbar_base.set_name ("ToolBarBase");
3123 toolbar_base.add (toolbar_hbox);
3125 _toolbar_viewport.add (toolbar_base);
3126 /* stick to the required height but allow width to vary if there's not enough room */
3127 _toolbar_viewport.set_size_request (1, -1);
3129 toolbar_frame.set_shadow_type (SHADOW_OUT);
3130 toolbar_frame.set_name ("BaseFrame");
3131 toolbar_frame.add (_toolbar_viewport);
3135 Editor::build_edit_point_menu ()
3137 using namespace Menu_Helpers;
3139 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3140 if(!Profile->get_mixbus())
3141 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3142 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3144 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3148 Editor::build_edit_mode_menu ()
3150 using namespace Menu_Helpers;
3152 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3153 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3154 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3155 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3157 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3161 Editor::build_snap_mode_menu ()
3163 using namespace Menu_Helpers;
3165 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3166 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3167 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3169 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3173 Editor::build_snap_type_menu ()
3175 using namespace Menu_Helpers;
3177 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3178 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3179 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3180 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3181 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3182 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3183 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3184 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3185 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3186 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3187 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3188 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3189 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3190 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3191 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3192 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3193 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3194 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3195 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3196 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3197 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3198 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3199 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3200 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3201 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3202 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3203 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3204 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3205 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3206 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3208 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3213 Editor::setup_tooltips ()
3215 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3216 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3217 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3218 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3219 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3220 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3221 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3222 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3223 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3224 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3225 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3226 set_tooltip (zoom_in_button, _("Zoom In"));
3227 set_tooltip (zoom_out_button, _("Zoom Out"));
3228 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3229 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3230 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3231 set_tooltip (tav_expand_button, _("Expand Tracks"));
3232 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3233 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3234 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3235 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3236 set_tooltip (edit_point_selector, _("Edit Point"));
3237 set_tooltip (edit_mode_selector, _("Edit Mode"));
3238 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3242 Editor::convert_drop_to_paths (
3243 vector<string>& paths,
3244 const RefPtr<Gdk::DragContext>& /*context*/,
3247 const SelectionData& data,
3251 if (_session == 0) {
3255 vector<string> uris = data.get_uris();
3259 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3260 are actually URI lists. So do it by hand.
3263 if (data.get_target() != "text/plain") {
3267 /* Parse the "uri-list" format that Nautilus provides,
3268 where each pathname is delimited by \r\n.
3270 THERE MAY BE NO NULL TERMINATING CHAR!!!
3273 string txt = data.get_text();
3277 p = (char *) malloc (txt.length() + 1);
3278 txt.copy (p, txt.length(), 0);
3279 p[txt.length()] = '\0';
3285 while (g_ascii_isspace (*p))
3289 while (*q && (*q != '\n') && (*q != '\r')) {
3296 while (q > p && g_ascii_isspace (*q))
3301 uris.push_back (string (p, q - p + 1));
3305 p = strchr (p, '\n');
3317 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3318 if ((*i).substr (0,7) == "file://") {
3319 paths.push_back (Glib::filename_from_uri (*i));
3327 Editor::new_tempo_section ()
3332 Editor::map_transport_state ()
3334 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3336 if (_session && _session->transport_stopped()) {
3337 have_pending_keyboard_selection = false;
3340 update_loop_range_view ();
3346 Editor::begin_selection_op_history ()
3348 selection_op_cmd_depth = 0;
3349 selection_op_history_it = 0;
3351 while(!selection_op_history.empty()) {
3352 delete selection_op_history.front();
3353 selection_op_history.pop_front();
3356 selection_undo_action->set_sensitive (false);
3357 selection_redo_action->set_sensitive (false);
3358 selection_op_history.push_front (&_selection_memento->get_state ());
3362 Editor::begin_reversible_selection_op (string name)
3365 //cerr << name << endl;
3366 /* begin/commit pairs can be nested */
3367 selection_op_cmd_depth++;
3372 Editor::commit_reversible_selection_op ()
3375 if (selection_op_cmd_depth == 1) {
3377 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3379 The user has undone some selection ops and then made a new one,
3380 making anything earlier in the list invalid.
3383 list<XMLNode *>::iterator it = selection_op_history.begin();
3384 list<XMLNode *>::iterator e_it = it;
3385 advance (e_it, selection_op_history_it);
3387 for ( ; it != e_it; ++it) {
3390 selection_op_history.erase (selection_op_history.begin(), e_it);
3393 selection_op_history.push_front (&_selection_memento->get_state ());
3394 selection_op_history_it = 0;
3396 selection_undo_action->set_sensitive (true);
3397 selection_redo_action->set_sensitive (false);
3400 if (selection_op_cmd_depth > 0) {
3401 selection_op_cmd_depth--;
3407 Editor::undo_selection_op ()
3410 selection_op_history_it++;
3412 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3413 if (n == selection_op_history_it) {
3414 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3415 selection_redo_action->set_sensitive (true);
3419 /* is there an earlier entry? */
3420 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3421 selection_undo_action->set_sensitive (false);
3427 Editor::redo_selection_op ()
3430 if (selection_op_history_it > 0) {
3431 selection_op_history_it--;
3434 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3435 if (n == selection_op_history_it) {
3436 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3437 selection_undo_action->set_sensitive (true);
3442 if (selection_op_history_it == 0) {
3443 selection_redo_action->set_sensitive (false);
3449 Editor::begin_reversible_command (string name)
3452 before.push_back (&_selection_memento->get_state ());
3453 _session->begin_reversible_command (name);
3458 Editor::begin_reversible_command (GQuark q)
3461 before.push_back (&_selection_memento->get_state ());
3462 _session->begin_reversible_command (q);
3467 Editor::abort_reversible_command ()
3470 while(!before.empty()) {
3471 delete before.front();
3474 _session->abort_reversible_command ();
3479 Editor::commit_reversible_command ()
3482 if (before.size() == 1) {
3483 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3484 redo_action->set_sensitive(false);
3485 undo_action->set_sensitive(true);
3486 begin_selection_op_history ();
3489 if (before.empty()) {
3490 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3495 _session->commit_reversible_command ();
3500 Editor::history_changed ()
3504 if (undo_action && _session) {
3505 if (_session->undo_depth() == 0) {
3506 label = S_("Command|Undo");
3508 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3510 undo_action->property_label() = label;
3513 if (redo_action && _session) {
3514 if (_session->redo_depth() == 0) {
3516 redo_action->set_sensitive (false);
3518 label = string_compose(_("Redo (%1)"), _session->next_redo());
3519 redo_action->set_sensitive (true);
3521 redo_action->property_label() = label;
3526 Editor::duplicate_range (bool with_dialog)
3530 RegionSelection rs = get_regions_from_selection_and_entered ();
3532 if ( selection->time.length() == 0 && rs.empty()) {
3538 ArdourDialog win (_("Duplicate"));
3539 Label label (_("Number of duplications:"));
3540 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3541 SpinButton spinner (adjustment, 0.0, 1);
3544 win.get_vbox()->set_spacing (12);
3545 win.get_vbox()->pack_start (hbox);
3546 hbox.set_border_width (6);
3547 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3549 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3550 place, visually. so do this by hand.
3553 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3554 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3555 spinner.grab_focus();
3561 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3562 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3563 win.set_default_response (RESPONSE_ACCEPT);
3565 spinner.grab_focus ();
3567 switch (win.run ()) {
3568 case RESPONSE_ACCEPT:
3574 times = adjustment.get_value();
3577 if ((current_mouse_mode() == Editing::MouseRange)) {
3578 if (selection->time.length()) {
3579 duplicate_selection (times);
3581 } else if (get_smart_mode()) {
3582 if (selection->time.length()) {
3583 duplicate_selection (times);
3585 duplicate_some_regions (rs, times);
3587 duplicate_some_regions (rs, times);
3592 Editor::set_edit_mode (EditMode m)
3594 Config->set_edit_mode (m);
3598 Editor::cycle_edit_mode ()
3600 switch (Config->get_edit_mode()) {
3602 Config->set_edit_mode (Ripple);
3606 Config->set_edit_mode (Lock);
3609 Config->set_edit_mode (Slide);
3615 Editor::edit_mode_selection_done ( EditMode m )
3617 Config->set_edit_mode ( m );
3621 Editor::snap_type_selection_done (SnapType snaptype)
3623 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3625 ract->set_active ();
3630 Editor::snap_mode_selection_done (SnapMode mode)
3632 RefPtr<RadioAction> ract = snap_mode_action (mode);
3635 ract->set_active (true);
3640 Editor::cycle_edit_point (bool with_marker)
3642 if(Profile->get_mixbus())
3643 with_marker = false;
3645 switch (_edit_point) {
3647 set_edit_point_preference (EditAtPlayhead);
3649 case EditAtPlayhead:
3651 set_edit_point_preference (EditAtSelectedMarker);
3653 set_edit_point_preference (EditAtMouse);
3656 case EditAtSelectedMarker:
3657 set_edit_point_preference (EditAtMouse);
3663 Editor::edit_point_selection_done (EditPoint ep)
3665 set_edit_point_preference ( ep );
3669 Editor::build_zoom_focus_menu ()
3671 using namespace Menu_Helpers;
3673 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3674 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3675 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3676 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3677 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3678 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3680 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3684 Editor::zoom_focus_selection_done ( ZoomFocus f )
3686 RefPtr<RadioAction> ract = zoom_focus_action (f);
3688 ract->set_active ();
3693 Editor::build_track_count_menu ()
3695 using namespace Menu_Helpers;
3697 if (!Profile->get_mixbus()) {
3698 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3699 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3700 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3701 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3702 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3703 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3704 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3705 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3706 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3707 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3708 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3709 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3710 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3712 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3713 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3714 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3715 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3716 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3717 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3718 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3719 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3720 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3721 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3723 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3724 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3725 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3726 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3727 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3728 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3729 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3730 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3731 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3732 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3733 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3738 Editor::set_zoom_preset (int64_t ms)
3741 temporal_zoom_session();
3745 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3746 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3750 Editor::set_visible_track_count (int32_t n)
3752 _visible_track_count = n;
3754 /* if the canvas hasn't really been allocated any size yet, just
3755 record the desired number of visible tracks and return. when canvas
3756 allocation happens, we will get called again and then we can do the
3760 if (_visible_canvas_height <= 1) {
3766 DisplaySuspender ds;
3768 if (_visible_track_count > 0) {
3769 h = trackviews_height() / _visible_track_count;
3770 std::ostringstream s;
3771 s << _visible_track_count;
3773 } else if (_visible_track_count == 0) {
3775 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3776 if ((*i)->marked_for_display()) {
3780 h = trackviews_height() / n;
3783 /* negative value means that the visible track count has
3784 been overridden by explicit track height changes.
3786 visible_tracks_selector.set_text (X_("*"));
3790 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3791 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3794 if (str != visible_tracks_selector.get_text()) {
3795 visible_tracks_selector.set_text (str);
3800 Editor::override_visible_track_count ()
3802 _visible_track_count = -1;
3803 visible_tracks_selector.set_text ( _("*") );
3807 Editor::edit_controls_button_release (GdkEventButton* ev)
3809 if (Keyboard::is_context_menu_event (ev)) {
3810 ARDOUR_UI::instance()->add_route ();
3811 } else if (ev->button == 1) {
3812 selection->clear_tracks ();
3819 Editor::mouse_select_button_release (GdkEventButton* ev)
3821 /* this handles just right-clicks */
3823 if (ev->button != 3) {
3831 Editor::set_zoom_focus (ZoomFocus f)
3833 string str = zoom_focus_strings[(int)f];
3835 if (str != zoom_focus_selector.get_text()) {
3836 zoom_focus_selector.set_text (str);
3839 if (zoom_focus != f) {
3846 Editor::cycle_zoom_focus ()
3848 switch (zoom_focus) {
3850 set_zoom_focus (ZoomFocusRight);
3852 case ZoomFocusRight:
3853 set_zoom_focus (ZoomFocusCenter);
3855 case ZoomFocusCenter:
3856 set_zoom_focus (ZoomFocusPlayhead);
3858 case ZoomFocusPlayhead:
3859 set_zoom_focus (ZoomFocusMouse);
3861 case ZoomFocusMouse:
3862 set_zoom_focus (ZoomFocusEdit);
3865 set_zoom_focus (ZoomFocusLeft);
3871 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3873 /* recover or initialize pane positions. do this here rather than earlier because
3874 we don't want the positions to change the child allocations, which they seem to do.
3878 XMLProperty const * prop;
3880 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3889 XMLNode* geometry = find_named_node (*node, "geometry");
3891 if (which == static_cast<Paned*> (&edit_pane)) {
3893 if (done & Horizontal) {
3897 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3898 _notebook_shrunk = string_is_affirmative (prop->value ());
3901 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3902 /* initial allocation is 90% to canvas, 10% to notebook */
3903 pos = (int) floor (alloc.get_width() * 0.90f);
3904 snprintf (buf, sizeof(buf), "%d", pos);
3906 pos = atoi (prop->value());
3909 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3910 edit_pane.set_position (pos);
3913 done = (Pane) (done | Horizontal);
3915 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3917 if (done & Vertical) {
3921 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3922 /* initial allocation is 90% to canvas, 10% to summary */
3923 pos = (int) floor (alloc.get_height() * 0.90f);
3924 snprintf (buf, sizeof(buf), "%d", pos);
3927 pos = atoi (prop->value());
3930 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3931 editor_summary_pane.set_position (pos);
3934 done = (Pane) (done | Vertical);
3939 Editor::set_show_measures (bool yn)
3941 if (_show_measures != yn) {
3944 if ((_show_measures = yn) == true) {
3946 tempo_lines->show();
3949 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3950 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3952 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3953 draw_measures (begin, end);
3961 Editor::toggle_follow_playhead ()
3963 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3965 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3966 set_follow_playhead (tact->get_active());
3970 /** @param yn true to follow playhead, otherwise false.
3971 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3974 Editor::set_follow_playhead (bool yn, bool catch_up)
3976 if (_follow_playhead != yn) {
3977 if ((_follow_playhead = yn) == true && catch_up) {
3979 reset_x_origin_to_follow_playhead ();
3986 Editor::toggle_stationary_playhead ()
3988 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3990 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3991 set_stationary_playhead (tact->get_active());
3996 Editor::set_stationary_playhead (bool yn)
3998 if (_stationary_playhead != yn) {
3999 if ((_stationary_playhead = yn) == true) {
4001 // FIXME need a 3.0 equivalent of this 2.X call
4002 // update_current_screen ();
4009 Editor::playlist_selector () const
4011 return *_playlist_selector;
4015 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4017 if (paste_count == 0) {
4018 /* don't bother calculating an offset that will be zero anyway */
4022 /* calculate basic unsnapped multi-paste offset */
4023 framecnt_t offset = paste_count * duration;
4025 /* snap offset so pos + offset is aligned to the grid */
4026 framepos_t offset_pos = pos + offset;
4027 snap_to(offset_pos, RoundUpMaybe);
4028 offset = offset_pos - pos;
4034 Editor::get_grid_beat_divisions(framepos_t position)
4036 switch (_snap_type) {
4037 case SnapToBeatDiv128: return 128;
4038 case SnapToBeatDiv64: return 64;
4039 case SnapToBeatDiv32: return 32;
4040 case SnapToBeatDiv28: return 28;
4041 case SnapToBeatDiv24: return 24;
4042 case SnapToBeatDiv20: return 20;
4043 case SnapToBeatDiv16: return 16;
4044 case SnapToBeatDiv14: return 14;
4045 case SnapToBeatDiv12: return 12;
4046 case SnapToBeatDiv10: return 10;
4047 case SnapToBeatDiv8: return 8;
4048 case SnapToBeatDiv7: return 7;
4049 case SnapToBeatDiv6: return 6;
4050 case SnapToBeatDiv5: return 5;
4051 case SnapToBeatDiv4: return 4;
4052 case SnapToBeatDiv3: return 3;
4053 case SnapToBeatDiv2: return 2;
4060 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4064 const unsigned divisions = get_grid_beat_divisions(position);
4066 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4069 switch (_snap_type) {
4071 return Evoral::Beats(1.0);
4074 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4082 return Evoral::Beats();
4086 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4090 ret = nudge_clock->current_duration (pos);
4091 next = ret + 1; /* XXXX fix me */
4097 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4099 ArdourDialog dialog (_("Playlist Deletion"));
4100 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4101 "If it is kept, its audio files will not be cleaned.\n"
4102 "If it is deleted, audio files used by it alone will be cleaned."),
4105 dialog.set_position (WIN_POS_CENTER);
4106 dialog.get_vbox()->pack_start (label);
4110 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4111 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4112 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4113 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4114 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4116 // by default gtk uses the left most button
4117 keep->grab_focus ();
4119 switch (dialog.run ()) {
4121 /* keep this and all remaining ones */
4126 /* delete this and all others */
4130 case RESPONSE_ACCEPT:
4131 /* delete the playlist */
4135 case RESPONSE_REJECT:
4136 /* keep the playlist */
4148 Editor::audio_region_selection_covers (framepos_t where)
4150 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4151 if ((*a)->region()->covers (where)) {
4160 Editor::prepare_for_cleanup ()
4162 cut_buffer->clear_regions ();
4163 cut_buffer->clear_playlists ();
4165 selection->clear_regions ();
4166 selection->clear_playlists ();
4168 _regions->suspend_redisplay ();
4172 Editor::finish_cleanup ()
4174 _regions->resume_redisplay ();
4178 Editor::transport_loop_location()
4181 return _session->locations()->auto_loop_location();
4188 Editor::transport_punch_location()
4191 return _session->locations()->auto_punch_location();
4198 Editor::control_layout_scroll (GdkEventScroll* ev)
4200 /* Just forward to the normal canvas scroll method. The coordinate
4201 systems are different but since the canvas is always larger than the
4202 track headers, and aligned with the trackview area, this will work.
4204 In the not too distant future this layout is going away anyway and
4205 headers will be on the canvas.
4207 return canvas_scroll_event (ev, false);
4211 Editor::session_state_saved (string)
4214 _snapshots->redisplay ();
4218 Editor::maximise_editing_space ()
4224 Gtk::Window* toplevel = current_toplevel();
4227 toplevel->fullscreen ();
4233 Editor::restore_editing_space ()
4239 Gtk::Window* toplevel = current_toplevel();
4242 toplevel->unfullscreen();
4248 * Make new playlists for a given track and also any others that belong
4249 * to the same active route group with the `select' property.
4254 Editor::new_playlists (TimeAxisView* v)
4256 begin_reversible_command (_("new playlists"));
4257 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4258 _session->playlists->get (playlists);
4259 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4260 commit_reversible_command ();
4264 * Use a copy of the current playlist for a given track and also any others that belong
4265 * to the same active route group with the `select' property.
4270 Editor::copy_playlists (TimeAxisView* v)
4272 begin_reversible_command (_("copy playlists"));
4273 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4274 _session->playlists->get (playlists);
4275 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4276 commit_reversible_command ();
4279 /** Clear the current playlist for a given track and also any others that belong
4280 * to the same active route group with the `select' property.
4285 Editor::clear_playlists (TimeAxisView* v)
4287 begin_reversible_command (_("clear playlists"));
4288 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4289 _session->playlists->get (playlists);
4290 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4291 commit_reversible_command ();
4295 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4297 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4301 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4303 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4307 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4309 atv.clear_playlist ();
4313 Editor::get_y_origin () const
4315 return vertical_adjustment.get_value ();
4318 /** Queue up a change to the viewport x origin.
4319 * @param frame New x origin.
4322 Editor::reset_x_origin (framepos_t frame)
4324 pending_visual_change.add (VisualChange::TimeOrigin);
4325 pending_visual_change.time_origin = frame;
4326 ensure_visual_change_idle_handler ();
4330 Editor::reset_y_origin (double y)
4332 pending_visual_change.add (VisualChange::YOrigin);
4333 pending_visual_change.y_origin = y;
4334 ensure_visual_change_idle_handler ();
4338 Editor::reset_zoom (framecnt_t spp)
4340 if (spp == samples_per_pixel) {
4344 pending_visual_change.add (VisualChange::ZoomLevel);
4345 pending_visual_change.samples_per_pixel = spp;
4346 ensure_visual_change_idle_handler ();
4350 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4352 reset_x_origin (frame);
4355 if (!no_save_visual) {
4356 undo_visual_stack.push_back (current_visual_state(false));
4360 Editor::VisualState::VisualState (bool with_tracks)
4361 : gui_state (with_tracks ? new GUIObjectState : 0)
4365 Editor::VisualState::~VisualState ()
4370 Editor::VisualState*
4371 Editor::current_visual_state (bool with_tracks)
4373 VisualState* vs = new VisualState (with_tracks);
4374 vs->y_position = vertical_adjustment.get_value();
4375 vs->samples_per_pixel = samples_per_pixel;
4376 vs->leftmost_frame = leftmost_frame;
4377 vs->zoom_focus = zoom_focus;
4380 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4387 Editor::undo_visual_state ()
4389 if (undo_visual_stack.empty()) {
4393 VisualState* vs = undo_visual_stack.back();
4394 undo_visual_stack.pop_back();
4397 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4400 use_visual_state (*vs);
4405 Editor::redo_visual_state ()
4407 if (redo_visual_stack.empty()) {
4411 VisualState* vs = redo_visual_stack.back();
4412 redo_visual_stack.pop_back();
4414 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4415 // why do we check here?
4416 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4419 use_visual_state (*vs);
4424 Editor::swap_visual_state ()
4426 if (undo_visual_stack.empty()) {
4427 redo_visual_state ();
4429 undo_visual_state ();
4434 Editor::use_visual_state (VisualState& vs)
4436 PBD::Unwinder<bool> nsv (no_save_visual, true);
4437 DisplaySuspender ds;
4439 vertical_adjustment.set_value (vs.y_position);
4441 set_zoom_focus (vs.zoom_focus);
4442 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4445 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4447 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4448 (*i)->clear_property_cache();
4449 (*i)->reset_visual_state ();
4453 _routes->update_visibility ();
4456 /** This is the core function that controls the zoom level of the canvas. It is called
4457 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4458 * @param spp new number of samples per pixel
4461 Editor::set_samples_per_pixel (framecnt_t spp)
4467 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4468 const framecnt_t lots_of_pixels = 4000;
4470 /* if the zoom level is greater than what you'd get trying to display 3
4471 * days of audio on a really big screen, then it's too big.
4474 if (spp * lots_of_pixels > three_days) {
4478 samples_per_pixel = spp;
4481 tempo_lines->tempo_map_changed();
4484 bool const showing_time_selection = selection->time.length() > 0;
4486 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4487 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4488 (*i)->reshow_selection (selection->time);
4492 ZoomChanged (); /* EMIT_SIGNAL */
4494 ArdourCanvas::GtkCanvasViewport* c;
4496 c = get_track_canvas();
4498 c->canvas()->zoomed ();
4501 if (playhead_cursor) {
4502 playhead_cursor->set_position (playhead_cursor->current_frame ());
4505 refresh_location_display();
4506 _summary->set_overlays_dirty ();
4508 update_marker_labels ();
4514 Editor::queue_visual_videotimeline_update ()
4517 * pending_visual_change.add (VisualChange::VideoTimeline);
4518 * or maybe even more specific: which videotimeline-image
4519 * currently it calls update_video_timeline() to update
4520 * _all outdated_ images on the video-timeline.
4521 * see 'exposeimg()' in video_image_frame.cc
4523 ensure_visual_change_idle_handler ();
4527 Editor::ensure_visual_change_idle_handler ()
4529 if (pending_visual_change.idle_handler_id < 0) {
4530 // see comment in add_to_idle_resize above.
4531 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4532 pending_visual_change.being_handled = false;
4537 Editor::_idle_visual_changer (void* arg)
4539 return static_cast<Editor*>(arg)->idle_visual_changer ();
4543 Editor::idle_visual_changer ()
4545 /* set_horizontal_position() below (and maybe other calls) call
4546 gtk_main_iteration(), so it's possible that a signal will be handled
4547 half-way through this method. If this signal wants an
4548 idle_visual_changer we must schedule another one after this one, so
4549 mark the idle_handler_id as -1 here to allow that. Also make a note
4550 that we are doing the visual change, so that changes in response to
4551 super-rapid-screen-update can be dropped if we are still processing
4555 pending_visual_change.idle_handler_id = -1;
4556 pending_visual_change.being_handled = true;
4558 VisualChange vc = pending_visual_change;
4560 pending_visual_change.pending = (VisualChange::Type) 0;
4562 visual_changer (vc);
4564 pending_visual_change.being_handled = false;
4566 return 0; /* this is always a one-shot call */
4570 Editor::visual_changer (const VisualChange& vc)
4572 double const last_time_origin = horizontal_position ();
4574 if (vc.pending & VisualChange::ZoomLevel) {
4575 set_samples_per_pixel (vc.samples_per_pixel);
4577 compute_fixed_ruler_scale ();
4579 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4580 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4582 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4583 current_bbt_points_begin, current_bbt_points_end);
4584 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4585 current_bbt_points_begin, current_bbt_points_end);
4586 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4588 update_video_timeline();
4591 if (vc.pending & VisualChange::TimeOrigin) {
4592 set_horizontal_position (vc.time_origin / samples_per_pixel);
4595 if (vc.pending & VisualChange::YOrigin) {
4596 vertical_adjustment.set_value (vc.y_origin);
4599 if (last_time_origin == horizontal_position ()) {
4600 /* changed signal not emitted */
4601 update_fixed_rulers ();
4602 redisplay_tempo (true);
4605 if (!(vc.pending & VisualChange::ZoomLevel)) {
4606 update_video_timeline();
4609 _summary->set_overlays_dirty ();
4612 struct EditorOrderTimeAxisSorter {
4613 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4614 return a->order () < b->order ();
4619 Editor::sort_track_selection (TrackViewList& sel)
4621 EditorOrderTimeAxisSorter cmp;
4626 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4629 framepos_t where = 0;
4630 EditPoint ep = _edit_point;
4632 if (Profile->get_mixbus())
4633 if (ep == EditAtSelectedMarker)
4634 ep = EditAtPlayhead;
4636 if (from_outside_canvas && (ep == EditAtMouse)) {
4637 ep = EditAtPlayhead;
4638 } else if (from_context_menu && (ep == EditAtMouse)) {
4639 return canvas_event_sample (&context_click_event, 0, 0);
4642 if (entered_marker) {
4643 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4644 return entered_marker->position();
4647 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4648 ep = EditAtSelectedMarker;
4651 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4652 ep = EditAtPlayhead;
4656 case EditAtPlayhead:
4657 if (_dragging_playhead) {
4658 where = *_control_scroll_target;
4660 where = _session->audible_frame();
4662 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4665 case EditAtSelectedMarker:
4666 if (!selection->markers.empty()) {
4668 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4671 where = loc->start();
4675 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4683 if (!mouse_frame (where, ignored)) {
4684 /* XXX not right but what can we do ? */
4688 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4696 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4698 if (!_session) return;
4700 begin_reversible_command (cmd);
4704 if ((tll = transport_loop_location()) == 0) {
4705 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4706 XMLNode &before = _session->locations()->get_state();
4707 _session->locations()->add (loc, true);
4708 _session->set_auto_loop_location (loc);
4709 XMLNode &after = _session->locations()->get_state();
4710 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4712 XMLNode &before = tll->get_state();
4713 tll->set_hidden (false, this);
4714 tll->set (start, end);
4715 XMLNode &after = tll->get_state();
4716 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4719 commit_reversible_command ();
4723 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4725 if (!_session) return;
4727 begin_reversible_command (cmd);
4731 if ((tpl = transport_punch_location()) == 0) {
4732 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4733 XMLNode &before = _session->locations()->get_state();
4734 _session->locations()->add (loc, true);
4735 _session->set_auto_punch_location (loc);
4736 XMLNode &after = _session->locations()->get_state();
4737 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4739 XMLNode &before = tpl->get_state();
4740 tpl->set_hidden (false, this);
4741 tpl->set (start, end);
4742 XMLNode &after = tpl->get_state();
4743 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4746 commit_reversible_command ();
4749 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4750 * @param rs List to which found regions are added.
4751 * @param where Time to look at.
4752 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4755 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4757 const TrackViewList* tracks;
4760 tracks = &track_views;
4765 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4767 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4770 boost::shared_ptr<Track> tr;
4771 boost::shared_ptr<Playlist> pl;
4773 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4775 boost::shared_ptr<RegionList> regions = pl->regions_at (
4776 (framepos_t) floor ( (double) where * tr->speed()));
4778 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4779 RegionView* rv = rtv->view()->find_view (*i);
4790 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4792 const TrackViewList* tracks;
4795 tracks = &track_views;
4800 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4801 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4803 boost::shared_ptr<Track> tr;
4804 boost::shared_ptr<Playlist> pl;
4806 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4808 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4809 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4811 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4813 RegionView* rv = rtv->view()->find_view (*i);
4824 /** Get regions using the following method:
4826 * Make a region list using:
4827 * (a) any selected regions
4828 * (b) the intersection of any selected tracks and the edit point(*)
4829 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4831 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4833 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4837 Editor::get_regions_from_selection_and_edit_point ()
4839 RegionSelection regions;
4841 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4842 regions.add (entered_regionview);
4844 regions = selection->regions;
4847 if ( regions.empty() ) {
4848 TrackViewList tracks = selection->tracks;
4850 if (!tracks.empty()) {
4851 /* no region selected or entered, but some selected tracks:
4852 * act on all regions on the selected tracks at the edit point
4854 framepos_t const where = get_preferred_edit_position ();
4855 get_regions_at(regions, where, tracks);
4862 /** Get regions using the following method:
4864 * Make a region list using:
4865 * (a) any selected regions
4866 * (b) the intersection of any selected tracks and the edit point(*)
4867 * (c) if neither exists, then whatever region is under the mouse
4869 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4871 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4874 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4876 RegionSelection regions;
4878 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4879 regions.add (entered_regionview);
4881 regions = selection->regions;
4884 if ( regions.empty() ) {
4885 TrackViewList tracks = selection->tracks;
4887 if (!tracks.empty()) {
4888 /* no region selected or entered, but some selected tracks:
4889 * act on all regions on the selected tracks at the edit point
4891 get_regions_at(regions, pos, tracks);
4898 /** Start with regions that are selected, or the entered regionview if none are selected.
4899 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4900 * of the regions that we started with.
4904 Editor::get_regions_from_selection_and_entered () const
4906 RegionSelection regions = selection->regions;
4908 if (regions.empty() && entered_regionview) {
4909 regions.add (entered_regionview);
4916 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4918 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4919 RouteTimeAxisView* rtav;
4921 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4922 boost::shared_ptr<Playlist> pl;
4923 std::vector<boost::shared_ptr<Region> > results;
4924 boost::shared_ptr<Track> tr;
4926 if ((tr = rtav->track()) == 0) {
4931 if ((pl = (tr->playlist())) != 0) {
4932 boost::shared_ptr<Region> r = pl->region_by_id (id);
4934 RegionView* rv = rtav->view()->find_view (r);
4936 regions.push_back (rv);
4945 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4948 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4949 MidiTimeAxisView* mtav;
4951 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4953 mtav->get_per_region_note_selection (selection);
4960 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4962 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4964 RouteTimeAxisView* tatv;
4966 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4968 boost::shared_ptr<Playlist> pl;
4969 vector<boost::shared_ptr<Region> > results;
4971 boost::shared_ptr<Track> tr;
4973 if ((tr = tatv->track()) == 0) {
4978 if ((pl = (tr->playlist())) != 0) {
4979 if (src_comparison) {
4980 pl->get_source_equivalent_regions (region, results);
4982 pl->get_region_list_equivalent_regions (region, results);
4986 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4987 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4988 regions.push_back (marv);
4997 Editor::show_rhythm_ferret ()
4999 if (rhythm_ferret == 0) {
5000 rhythm_ferret = new RhythmFerret(*this);
5003 rhythm_ferret->set_session (_session);
5004 rhythm_ferret->show ();
5005 rhythm_ferret->present ();
5009 Editor::first_idle ()
5011 MessageDialog* dialog = 0;
5013 if (track_views.size() > 1) {
5014 Timers::TimerSuspender t;
5015 dialog = new MessageDialog (
5016 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5020 ARDOUR_UI::instance()->flush_pending ();
5023 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5027 // first idle adds route children (automation tracks), so we need to redisplay here
5028 _routes->redisplay ();
5032 if (_session->undo_depth() == 0) {
5033 undo_action->set_sensitive(false);
5035 redo_action->set_sensitive(false);
5036 begin_selection_op_history ();
5042 Editor::_idle_resize (gpointer arg)
5044 return ((Editor*)arg)->idle_resize ();
5048 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5050 if (resize_idle_id < 0) {
5051 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5052 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5053 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5055 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5056 _pending_resize_amount = 0;
5059 /* make a note of the smallest resulting height, so that we can clamp the
5060 lower limit at TimeAxisView::hSmall */
5062 int32_t min_resulting = INT32_MAX;
5064 _pending_resize_amount += h;
5065 _pending_resize_view = view;
5067 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5069 if (selection->tracks.contains (_pending_resize_view)) {
5070 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5071 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5075 if (min_resulting < 0) {
5080 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5081 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5085 /** Handle pending resizing of tracks */
5087 Editor::idle_resize ()
5089 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5091 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5092 selection->tracks.contains (_pending_resize_view)) {
5094 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5095 if (*i != _pending_resize_view) {
5096 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5101 _pending_resize_amount = 0;
5102 _group_tabs->set_dirty ();
5103 resize_idle_id = -1;
5111 ENSURE_GUI_THREAD (*this, &Editor::located);
5114 playhead_cursor->set_position (_session->audible_frame ());
5115 if (_follow_playhead && !_pending_initial_locate) {
5116 reset_x_origin_to_follow_playhead ();
5120 _pending_locate_request = false;
5121 _pending_initial_locate = false;
5125 Editor::region_view_added (RegionView * rv)
5127 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5128 if (rv->region ()->id () == (*pr)) {
5129 selection->add (rv);
5130 selection->regions.pending.erase (pr);
5135 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5137 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5138 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5139 if (rv->region()->id () == (*rnote).first) {
5140 mrv->select_notes ((*rnote).second);
5141 selection->pending_midi_note_selection.erase(rnote);
5147 _summary->set_background_dirty ();
5151 Editor::region_view_removed ()
5153 _summary->set_background_dirty ();
5157 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5159 TrackViewList::const_iterator j = track_views.begin ();
5160 while (j != track_views.end()) {
5161 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5162 if (rtv && rtv->route() == r) {
5173 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5177 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5178 TimeAxisView* tv = axis_view_from_route (*i);
5188 Editor::suspend_route_redisplay ()
5191 _routes->suspend_redisplay();
5196 Editor::resume_route_redisplay ()
5199 _routes->redisplay(); // queue redisplay
5200 _routes->resume_redisplay();
5205 Editor::add_routes (RouteList& routes)
5207 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5209 RouteTimeAxisView *rtv;
5210 list<RouteTimeAxisView*> new_views;
5211 TrackViewList new_selection;
5212 bool from_scratch = (track_views.size() == 0);
5214 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5215 boost::shared_ptr<Route> route = (*x);
5217 if (route->is_auditioner() || route->is_monitor()) {
5221 DataType dt = route->input()->default_type();
5223 if (dt == ARDOUR::DataType::AUDIO) {
5224 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5225 rtv->set_route (route);
5226 } else if (dt == ARDOUR::DataType::MIDI) {
5227 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5228 rtv->set_route (route);
5230 throw unknown_type();
5233 new_views.push_back (rtv);
5234 track_views.push_back (rtv);
5235 new_selection.push_back (rtv);
5237 rtv->effective_gain_display ();
5239 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5240 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5243 if (new_views.size() > 0) {
5244 _routes->routes_added (new_views);
5245 _summary->routes_added (new_views);
5248 if (!from_scratch) {
5249 selection->tracks.clear();
5250 selection->add (new_selection);
5251 begin_selection_op_history();
5254 if (show_editor_mixer_when_tracks_arrive) {
5255 show_editor_mixer (true);
5258 editor_list_button.set_sensitive (true);
5262 Editor::timeaxisview_deleted (TimeAxisView *tv)
5264 if (tv == entered_track) {
5268 if (_session && _session->deletion_in_progress()) {
5269 /* the situation is under control */
5273 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5275 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5277 _routes->route_removed (tv);
5279 TimeAxisView::Children c = tv->get_child_list ();
5280 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5281 if (entered_track == i->get()) {
5286 /* remove it from the list of track views */
5288 TrackViewList::iterator i;
5290 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5291 i = track_views.erase (i);
5294 /* update whatever the current mixer strip is displaying, if revelant */
5296 boost::shared_ptr<Route> route;
5299 route = rtav->route ();
5302 if (current_mixer_strip && current_mixer_strip->route() == route) {
5304 TimeAxisView* next_tv;
5306 if (track_views.empty()) {
5308 } else if (i == track_views.end()) {
5309 next_tv = track_views.front();
5316 set_selected_mixer_strip (*next_tv);
5318 /* make the editor mixer strip go away setting the
5319 * button to inactive (which also unticks the menu option)
5322 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5328 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5330 if (apply_to_selection) {
5331 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5333 TrackSelection::iterator j = i;
5336 hide_track_in_display (*i, false);
5341 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5343 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5344 // this will hide the mixer strip
5345 set_selected_mixer_strip (*tv);
5348 _routes->hide_track_in_display (*tv);
5353 Editor::sync_track_view_list_and_routes ()
5355 track_views = TrackViewList (_routes->views ());
5357 _summary->set_background_dirty();
5358 _group_tabs->set_dirty ();
5360 return false; // do not call again (until needed)
5364 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5366 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5371 /** Find a RouteTimeAxisView by the ID of its route */
5373 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5375 RouteTimeAxisView* v;
5377 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5378 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5379 if(v->route()->id() == id) {
5389 Editor::fit_route_group (RouteGroup *g)
5391 TrackViewList ts = axis_views_from_routes (g->route_list ());
5396 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5398 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5401 _session->cancel_audition ();
5405 if (_session->is_auditioning()) {
5406 _session->cancel_audition ();
5407 if (r == last_audition_region) {
5412 _session->audition_region (r);
5413 last_audition_region = r;
5418 Editor::hide_a_region (boost::shared_ptr<Region> r)
5420 r->set_hidden (true);
5424 Editor::show_a_region (boost::shared_ptr<Region> r)
5426 r->set_hidden (false);
5430 Editor::audition_region_from_region_list ()
5432 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5436 Editor::hide_region_from_region_list ()
5438 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5442 Editor::show_region_in_region_list ()
5444 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5448 Editor::step_edit_status_change (bool yn)
5451 start_step_editing ();
5453 stop_step_editing ();
5458 Editor::start_step_editing ()
5460 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5464 Editor::stop_step_editing ()
5466 step_edit_connection.disconnect ();
5470 Editor::check_step_edit ()
5472 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5473 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5475 mtv->check_step_edit ();
5479 return true; // do it again, till we stop
5483 Editor::scroll_press (Direction dir)
5485 ++_scroll_callbacks;
5487 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5488 /* delay the first auto-repeat */
5494 scroll_backward (1);
5502 scroll_up_one_track ();
5506 scroll_down_one_track ();
5510 /* do hacky auto-repeat */
5511 if (!_scroll_connection.connected ()) {
5513 _scroll_connection = Glib::signal_timeout().connect (
5514 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5517 _scroll_callbacks = 0;
5524 Editor::scroll_release ()
5526 _scroll_connection.disconnect ();
5529 /** Queue a change for the Editor viewport x origin to follow the playhead */
5531 Editor::reset_x_origin_to_follow_playhead ()
5533 framepos_t const frame = playhead_cursor->current_frame ();
5535 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5537 if (_session->transport_speed() < 0) {
5539 if (frame > (current_page_samples() / 2)) {
5540 center_screen (frame-(current_page_samples()/2));
5542 center_screen (current_page_samples()/2);
5549 if (frame < leftmost_frame) {
5551 if (_session->transport_rolling()) {
5552 /* rolling; end up with the playhead at the right of the page */
5553 l = frame - current_page_samples ();
5555 /* not rolling: end up with the playhead 1/4 of the way along the page */
5556 l = frame - current_page_samples() / 4;
5560 if (_session->transport_rolling()) {
5561 /* rolling: end up with the playhead on the left of the page */
5564 /* not rolling: end up with the playhead 3/4 of the way along the page */
5565 l = frame - 3 * current_page_samples() / 4;
5573 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5579 Editor::super_rapid_screen_update ()
5581 if (!_session || !_session->engine().running()) {
5585 /* METERING / MIXER STRIPS */
5587 /* update track meters, if required */
5588 if (contents().is_mapped() && meters_running) {
5589 RouteTimeAxisView* rtv;
5590 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5591 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5592 rtv->fast_update ();
5597 /* and any current mixer strip */
5598 if (current_mixer_strip) {
5599 current_mixer_strip->fast_update ();
5602 /* PLAYHEAD AND VIEWPORT */
5604 framepos_t const frame = _session->audible_frame();
5606 /* There are a few reasons why we might not update the playhead / viewport stuff:
5608 * 1. we don't update things when there's a pending locate request, otherwise
5609 * when the editor requests a locate there is a chance that this method
5610 * will move the playhead before the locate request is processed, causing
5612 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5613 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5616 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5618 last_update_frame = frame;
5620 if (!_dragging_playhead) {
5621 playhead_cursor->set_position (frame);
5624 if (!_stationary_playhead) {
5626 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5627 /* We only do this if we aren't already
5628 handling a visual change (ie if
5629 pending_visual_change.being_handled is
5630 false) so that these requests don't stack
5631 up there are too many of them to handle in
5634 reset_x_origin_to_follow_playhead ();
5639 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5640 framepos_t const frame = playhead_cursor->current_frame ();
5641 double target = ((double)frame - (double)current_page_samples()/2.0);
5642 if (target <= 0.0) {
5645 // compare to EditorCursor::set_position()
5646 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5647 double const new_pos = sample_to_pixel_unrounded (target);
5648 if (rint (new_pos) != rint (old_pos)) {
5649 reset_x_origin (pixel_to_sample (floor (new_pos)));
5660 Editor::session_going_away ()
5662 _have_idled = false;
5664 _session_connections.drop_connections ();
5666 super_rapid_screen_update_connection.disconnect ();
5668 selection->clear ();
5669 cut_buffer->clear ();
5671 clicked_regionview = 0;
5672 clicked_axisview = 0;
5673 clicked_routeview = 0;
5674 entered_regionview = 0;
5676 last_update_frame = 0;
5679 playhead_cursor->hide ();
5681 /* rip everything out of the list displays */
5685 _route_groups->clear ();
5687 /* do this first so that deleting a track doesn't reset cms to null
5688 and thus cause a leak.
5691 if (current_mixer_strip) {
5692 if (current_mixer_strip->get_parent() != 0) {
5693 global_hpacker.remove (*current_mixer_strip);
5695 delete current_mixer_strip;
5696 current_mixer_strip = 0;
5699 /* delete all trackviews */
5701 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5704 track_views.clear ();
5706 nudge_clock->set_session (0);
5708 editor_list_button.set_active(false);
5709 editor_list_button.set_sensitive(false);
5711 /* clear tempo/meter rulers */
5712 remove_metric_marks ();
5714 clear_marker_display ();
5716 stop_step_editing ();
5720 /* get rid of any existing editor mixer strip */
5722 WindowTitle title(Glib::get_application_name());
5723 title += _("Editor");
5725 own_window()->set_title (title.get_string());
5728 SessionHandlePtr::session_going_away ();
5732 Editor::trigger_script (int i)
5734 LuaInstance::instance()-> call_action (i);
5738 Editor::set_script_action_name (int i, const std::string& n)
5740 string const a = string_compose (X_("script-action-%1"), i + 1);
5741 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5744 act->set_label (string_compose (_("Unset #%1"), i + 1));
5745 act->set_tooltip (_("no action bound"));
5746 act->set_sensitive (false);
5749 act->set_tooltip (n);
5750 act->set_sensitive (true);
5752 KeyEditor::UpdateBindings ();
5756 Editor::show_editor_list (bool yn)
5759 _the_notebook.show ();
5761 _the_notebook.hide ();
5766 Editor::change_region_layering_order (bool from_context_menu)
5768 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5770 if (!clicked_routeview) {
5771 if (layering_order_editor) {
5772 layering_order_editor->hide ();
5777 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5783 boost::shared_ptr<Playlist> pl = track->playlist();
5789 if (layering_order_editor == 0) {
5790 layering_order_editor = new RegionLayeringOrderEditor (*this);
5793 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5794 layering_order_editor->maybe_present ();
5798 Editor::update_region_layering_order_editor ()
5800 if (layering_order_editor && layering_order_editor->is_visible ()) {
5801 change_region_layering_order (true);
5806 Editor::setup_fade_images ()
5808 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5809 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5810 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5811 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5812 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5814 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5815 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5816 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5817 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5818 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5820 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5821 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5822 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5823 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5824 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5826 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5827 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5828 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5829 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5830 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5834 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5836 Editor::action_menu_item (std::string const & name)
5838 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5841 return *manage (a->create_menu_item ());
5845 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5847 EventBox* b = manage (new EventBox);
5848 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5849 Label* l = manage (new Label (name));
5853 _the_notebook.append_page (widget, *b);
5857 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5859 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5860 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5863 if (ev->type == GDK_2BUTTON_PRESS) {
5865 /* double-click on a notebook tab shrinks or expands the notebook */
5867 if (_notebook_shrunk) {
5868 if (pre_notebook_shrink_pane_width) {
5869 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5871 _notebook_shrunk = false;
5873 pre_notebook_shrink_pane_width = edit_pane.get_position();
5875 /* this expands the LHS of the edit pane to cover the notebook
5876 PAGE but leaves the tabs visible.
5878 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5879 _notebook_shrunk = true;
5887 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5889 using namespace Menu_Helpers;
5891 MenuList& items = _control_point_context_menu.items ();
5894 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5895 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5896 if (!can_remove_control_point (item)) {
5897 items.back().set_sensitive (false);
5900 _control_point_context_menu.popup (event->button.button, event->button.time);
5904 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5906 using namespace Menu_Helpers;
5908 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5913 /* We need to get the selection here and pass it to the operations, since
5914 popping up the menu will cause a region leave event which clears
5915 entered_regionview. */
5917 MidiRegionView& mrv = note->region_view();
5918 const RegionSelection rs = get_regions_from_selection_and_entered ();
5919 const uint32_t sel_size = mrv.selection_size ();
5921 MenuList& items = _note_context_menu.items();
5925 items.push_back(MenuElem(_("Delete"),
5926 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5929 items.push_back(MenuElem(_("Edit..."),
5930 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5931 if (sel_size != 1) {
5932 items.back().set_sensitive (false);
5935 items.push_back(MenuElem(_("Transpose..."),
5936 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5939 items.push_back(MenuElem(_("Legatize"),
5940 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5942 items.back().set_sensitive (false);
5945 items.push_back(MenuElem(_("Quantize..."),
5946 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5948 items.push_back(MenuElem(_("Remove Overlap"),
5949 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5951 items.back().set_sensitive (false);
5954 items.push_back(MenuElem(_("Transform..."),
5955 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5957 _note_context_menu.popup (event->button.button, event->button.time);
5961 Editor::zoom_vertical_modifier_released()
5963 _stepping_axis_view = 0;
5967 Editor::ui_parameter_changed (string parameter)
5969 if (parameter == "icon-set") {
5970 while (!_cursor_stack.empty()) {
5971 _cursor_stack.pop_back();
5973 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5974 _cursor_stack.push_back(_cursors->grabber);
5975 } else if (parameter == "draggable-playhead") {
5976 if (_verbose_cursor) {
5977 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5983 Editor::use_own_window (bool and_fill_it)
5985 bool new_window = !own_window();
5987 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5989 if (win && new_window) {
5990 win->set_name ("EditorWindow");
5992 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5994 // win->signal_realize().connect (*this, &Editor::on_realize);
5995 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
5996 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
5997 win->set_data ("ardour-bindings", bindings);
6002 DisplaySuspender ds;
6003 contents().show_all ();
6005 /* XXX: this is a bit unfortunate; it would probably
6006 be nicer if we could just call show () above rather
6007 than needing the show_all ()
6010 /* re-hide stuff if necessary */
6011 editor_list_button_toggled ();
6012 parameter_changed ("show-summary");
6013 parameter_changed ("show-group-tabs");
6014 parameter_changed ("show-zoom-tools");
6016 /* now reset all audio_time_axis heights, because widgets might need
6022 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6023 tv = (static_cast<TimeAxisView*>(*i));
6024 tv->reset_height ();
6027 if (current_mixer_strip) {
6028 current_mixer_strip->hide_things ();
6029 current_mixer_strip->parameter_changed ("mixer-element-visibility");