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)
440 , current_mixer_strip (0)
441 , show_editor_mixer_when_tracks_arrive (false)
442 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
443 , current_stepping_trackview (0)
444 , last_track_height_step_timestamp (0)
446 , entered_regionview (0)
447 , clear_entered_track (false)
448 , _edit_point (EditAtMouse)
449 , meters_running (false)
451 , _have_idled (false)
452 , resize_idle_id (-1)
453 , _pending_resize_amount (0)
454 , _pending_resize_view (0)
455 , _pending_locate_request (false)
456 , _pending_initial_locate (false)
460 , layering_order_editor (0)
461 , _last_cut_copy_source_track (0)
462 , _region_selection_change_updates_region_list (true)
464 , _following_mixer_selection (false)
465 , _control_point_toggled_on_press (false)
466 , _stepping_axis_view (0)
467 , quantize_dialog (0)
468 , _main_menu_disabler (0)
469 , myactions (X_("editor"))
471 /* we are a singleton */
473 PublicEditor::_instance = this;
477 last_event_time.tv_sec = 0;
478 last_event_time.tv_usec = 0;
480 selection_op_history.clear();
483 snap_type_strings = I18N (_snap_type_strings);
484 snap_mode_strings = I18N (_snap_mode_strings);
485 zoom_focus_strings = I18N (_zoom_focus_strings);
486 edit_mode_strings = I18N (_edit_mode_strings);
487 edit_point_strings = I18N (_edit_point_strings);
488 #ifdef USE_RUBBERBAND
489 rb_opt_strings = I18N (_rb_opt_strings);
493 build_edit_mode_menu();
494 build_zoom_focus_menu();
495 build_track_count_menu();
496 build_snap_mode_menu();
497 build_snap_type_menu();
498 build_edit_point_menu();
500 location_marker_color = UIConfiguration::instance().color ("location marker");
501 location_range_color = UIConfiguration::instance().color ("location range");
502 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
503 location_loop_color = UIConfiguration::instance().color ("location loop");
504 location_punch_color = UIConfiguration::instance().color ("location punch");
506 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
508 TimeAxisView::setup_sizes ();
509 ArdourMarker::setup_sizes (timebar_height);
511 bbt_label.set_name ("EditorRulerLabel");
512 bbt_label.set_size_request (-1, (int)timebar_height);
513 bbt_label.set_alignment (1.0, 0.5);
514 bbt_label.set_padding (5,0);
516 bbt_label.set_no_show_all();
517 minsec_label.set_name ("EditorRulerLabel");
518 minsec_label.set_size_request (-1, (int)timebar_height);
519 minsec_label.set_alignment (1.0, 0.5);
520 minsec_label.set_padding (5,0);
521 minsec_label.hide ();
522 minsec_label.set_no_show_all();
523 timecode_label.set_name ("EditorRulerLabel");
524 timecode_label.set_size_request (-1, (int)timebar_height);
525 timecode_label.set_alignment (1.0, 0.5);
526 timecode_label.set_padding (5,0);
527 timecode_label.hide ();
528 timecode_label.set_no_show_all();
529 samples_label.set_name ("EditorRulerLabel");
530 samples_label.set_size_request (-1, (int)timebar_height);
531 samples_label.set_alignment (1.0, 0.5);
532 samples_label.set_padding (5,0);
533 samples_label.hide ();
534 samples_label.set_no_show_all();
536 tempo_label.set_name ("EditorRulerLabel");
537 tempo_label.set_size_request (-1, (int)timebar_height);
538 tempo_label.set_alignment (1.0, 0.5);
539 tempo_label.set_padding (5,0);
541 tempo_label.set_no_show_all();
543 meter_label.set_name ("EditorRulerLabel");
544 meter_label.set_size_request (-1, (int)timebar_height);
545 meter_label.set_alignment (1.0, 0.5);
546 meter_label.set_padding (5,0);
548 meter_label.set_no_show_all();
550 if (Profile->get_trx()) {
551 mark_label.set_text (_("Markers"));
553 mark_label.set_name ("EditorRulerLabel");
554 mark_label.set_size_request (-1, (int)timebar_height);
555 mark_label.set_alignment (1.0, 0.5);
556 mark_label.set_padding (5,0);
558 mark_label.set_no_show_all();
560 cd_mark_label.set_name ("EditorRulerLabel");
561 cd_mark_label.set_size_request (-1, (int)timebar_height);
562 cd_mark_label.set_alignment (1.0, 0.5);
563 cd_mark_label.set_padding (5,0);
564 cd_mark_label.hide();
565 cd_mark_label.set_no_show_all();
567 videotl_bar_height = 4;
568 videotl_label.set_name ("EditorRulerLabel");
569 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
570 videotl_label.set_alignment (1.0, 0.5);
571 videotl_label.set_padding (5,0);
572 videotl_label.hide();
573 videotl_label.set_no_show_all();
575 range_mark_label.set_name ("EditorRulerLabel");
576 range_mark_label.set_size_request (-1, (int)timebar_height);
577 range_mark_label.set_alignment (1.0, 0.5);
578 range_mark_label.set_padding (5,0);
579 range_mark_label.hide();
580 range_mark_label.set_no_show_all();
582 transport_mark_label.set_name ("EditorRulerLabel");
583 transport_mark_label.set_size_request (-1, (int)timebar_height);
584 transport_mark_label.set_alignment (1.0, 0.5);
585 transport_mark_label.set_padding (5,0);
586 transport_mark_label.hide();
587 transport_mark_label.set_no_show_all();
589 initialize_canvas ();
591 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
593 _summary = new EditorSummary (this);
595 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
596 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
598 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
600 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
601 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
603 edit_controls_vbox.set_spacing (0);
604 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
605 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
607 HBox* h = manage (new HBox);
608 _group_tabs = new EditorGroupTabs (this);
609 if (!ARDOUR::Profile->get_trx()) {
610 h->pack_start (*_group_tabs, PACK_SHRINK);
612 h->pack_start (edit_controls_vbox);
613 controls_layout.add (*h);
615 controls_layout.set_name ("EditControlsBase");
616 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
617 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
618 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
620 _cursors = new MouseCursors;
621 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
622 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
624 /* Push default cursor to ever-present bottom of cursor stack. */
625 push_canvas_cursor(_cursors->grabber);
627 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
629 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
630 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
631 pad_line_1->set_outline_color (0xFF0000FF);
637 edit_packer.set_col_spacings (0);
638 edit_packer.set_row_spacings (0);
639 edit_packer.set_homogeneous (false);
640 edit_packer.set_border_width (0);
641 edit_packer.set_name ("EditorWindow");
643 time_bars_event_box.add (time_bars_vbox);
644 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
645 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
647 /* labels for the time bars */
648 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
650 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
652 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
654 bottom_hbox.set_border_width (2);
655 bottom_hbox.set_spacing (3);
657 _route_groups = new EditorRouteGroups (this);
658 _routes = new EditorRoutes (this);
659 _regions = new EditorRegions (this);
660 _snapshots = new EditorSnapshots (this);
661 _locations = new EditorLocations (this);
663 /* these are static location signals */
665 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
666 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
667 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
669 add_notebook_page (_("Regions"), _regions->widget ());
670 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
671 add_notebook_page (_("Snapshots"), _snapshots->widget ());
672 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
673 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
675 _the_notebook.set_show_tabs (true);
676 _the_notebook.set_scrollable (true);
677 _the_notebook.popup_disable ();
678 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
679 _the_notebook.show_all ();
681 _notebook_shrunk = false;
683 editor_summary_pane.pack1(edit_packer);
685 Button* summary_arrows_left_left = manage (new Button);
686 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
687 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
688 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
690 Button* summary_arrows_left_right = manage (new Button);
691 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
692 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
693 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
695 VBox* summary_arrows_left = manage (new VBox);
696 summary_arrows_left->pack_start (*summary_arrows_left_left);
697 summary_arrows_left->pack_start (*summary_arrows_left_right);
699 Button* summary_arrows_right_up = manage (new Button);
700 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
701 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
702 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
704 Button* summary_arrows_right_down = manage (new Button);
705 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
706 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
707 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
709 VBox* summary_arrows_right = manage (new VBox);
710 summary_arrows_right->pack_start (*summary_arrows_right_up);
711 summary_arrows_right->pack_start (*summary_arrows_right_down);
713 Frame* summary_frame = manage (new Frame);
714 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
716 summary_frame->add (*_summary);
717 summary_frame->show ();
719 _summary_hbox.pack_start (*summary_arrows_left, false, false);
720 _summary_hbox.pack_start (*summary_frame, true, true);
721 _summary_hbox.pack_start (*summary_arrows_right, false, false);
723 if (!ARDOUR::Profile->get_trx()) {
724 editor_summary_pane.pack2 (_summary_hbox);
727 edit_pane.pack1 (editor_summary_pane, true, true);
728 if (!ARDOUR::Profile->get_trx()) {
729 edit_pane.pack2 (_the_notebook, false, true);
732 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
734 /* XXX: editor_summary_pane might need similar to the edit_pane */
736 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
738 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
739 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
741 top_hbox.pack_start (toolbar_frame);
743 HBox *hbox = manage (new HBox);
744 hbox->pack_start (edit_pane, true, true);
746 global_vpacker.pack_start (top_hbox, false, false);
747 global_vpacker.pack_start (*hbox, true, true);
748 global_hpacker.pack_start (global_vpacker, true, true);
750 /* need to show the "contents" widget so that notebook will show if tab is switched to
753 global_hpacker.show ();
755 /* register actions now so that set_state() can find them and set toggles/checks etc */
762 _playlist_selector = new PlaylistSelector();
763 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
765 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
769 nudge_forward_button.set_name ("nudge button");
770 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
772 nudge_backward_button.set_name ("nudge button");
773 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
775 fade_context_menu.set_name ("ArdourContextMenu");
777 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
779 /* allow external control surfaces/protocols to do various things */
781 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
782 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
783 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
784 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
785 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
786 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
787 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
788 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
789 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
790 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
791 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
792 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
793 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
794 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
796 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
797 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
798 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
799 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
800 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
802 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
804 /* problematic: has to return a value and thus cannot be x-thread */
806 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
808 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
809 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
811 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
813 _ignore_region_action = false;
814 _last_region_menu_was_main = false;
815 _popup_region_menu_item = 0;
817 _ignore_follow_edits = false;
819 _show_marker_lines = false;
821 /* Button bindings */
823 button_bindings = new Bindings ("editor-mouse");
825 XMLNode* node = button_settings();
827 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
828 button_bindings->load_operation (**i);
834 /* grab current parameter state */
835 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
836 UIConfiguration::instance().map_parameters (pc);
838 setup_fade_images ();
840 LuaInstance::instance(); // instantiate
841 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &Editor::set_script_action_name));
848 delete button_bindings;
850 delete _route_groups;
851 delete _track_canvas_viewport;
854 delete quantize_dialog;
860 delete _playlist_selector;
862 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
868 Editor::button_settings () const
870 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
871 XMLNode* node = find_named_node (*settings, X_("Buttons"));
874 node = new XMLNode (X_("Buttons"));
881 Editor::get_smart_mode () const
883 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
887 Editor::catch_vanishing_regionview (RegionView *rv)
889 /* note: the selection will take care of the vanishing
890 audioregionview by itself.
893 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
897 if (clicked_regionview == rv) {
898 clicked_regionview = 0;
901 if (entered_regionview == rv) {
902 set_entered_regionview (0);
905 if (!_all_region_actions_sensitized) {
906 sensitize_all_region_actions (true);
911 Editor::set_entered_regionview (RegionView* rv)
913 if (rv == entered_regionview) {
917 if (entered_regionview) {
918 entered_regionview->exited ();
921 entered_regionview = rv;
923 if (entered_regionview != 0) {
924 entered_regionview->entered ();
927 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
928 /* This RegionView entry might have changed what region actions
929 are allowed, so sensitize them all in case a key is pressed.
931 sensitize_all_region_actions (true);
936 Editor::set_entered_track (TimeAxisView* tav)
939 entered_track->exited ();
945 entered_track->entered ();
950 Editor::instant_save ()
952 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
957 _session->add_instant_xml(get_state());
959 Config->add_instant_xml(get_state());
964 Editor::control_vertical_zoom_in_all ()
966 tav_zoom_smooth (false, true);
970 Editor::control_vertical_zoom_out_all ()
972 tav_zoom_smooth (true, true);
976 Editor::control_vertical_zoom_in_selected ()
978 tav_zoom_smooth (false, false);
982 Editor::control_vertical_zoom_out_selected ()
984 tav_zoom_smooth (true, false);
988 Editor::control_view (uint32_t view)
990 goto_visual_state (view);
994 Editor::control_unselect ()
996 selection->clear_tracks ();
1000 Editor::control_select (uint32_t rid, Selection::Operation op)
1002 /* handles the (static) signal from the ControlProtocol class that
1003 * requests setting the selected track to a given RID
1010 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1016 TimeAxisView* tav = axis_view_from_route (r);
1020 case Selection::Add:
1021 selection->add (tav);
1023 case Selection::Toggle:
1024 selection->toggle (tav);
1026 case Selection::Extend:
1028 case Selection::Set:
1029 selection->set (tav);
1033 selection->clear_tracks ();
1038 Editor::control_step_tracks_up ()
1040 scroll_tracks_up_line ();
1044 Editor::control_step_tracks_down ()
1046 scroll_tracks_down_line ();
1050 Editor::control_scroll (float fraction)
1052 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1058 double step = fraction * current_page_samples();
1061 _control_scroll_target is an optional<T>
1063 it acts like a pointer to an framepos_t, with
1064 a operator conversion to boolean to check
1065 that it has a value could possibly use
1066 playhead_cursor->current_frame to store the
1067 value and a boolean in the class to know
1068 when it's out of date
1071 if (!_control_scroll_target) {
1072 _control_scroll_target = _session->transport_frame();
1073 _dragging_playhead = true;
1076 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1077 *_control_scroll_target = 0;
1078 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1079 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1081 *_control_scroll_target += (framepos_t) trunc (step);
1084 /* move visuals, we'll catch up with it later */
1086 playhead_cursor->set_position (*_control_scroll_target);
1087 UpdateAllTransportClocks (*_control_scroll_target);
1089 if (*_control_scroll_target > (current_page_samples() / 2)) {
1090 /* try to center PH in window */
1091 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1097 Now we do a timeout to actually bring the session to the right place
1098 according to the playhead. This is to avoid reading disk buffers on every
1099 call to control_scroll, which is driven by ScrollTimeline and therefore
1100 probably by a control surface wheel which can generate lots of events.
1102 /* cancel the existing timeout */
1104 control_scroll_connection.disconnect ();
1106 /* add the next timeout */
1108 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1112 Editor::deferred_control_scroll (framepos_t /*target*/)
1114 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1115 // reset for next stream
1116 _control_scroll_target = boost::none;
1117 _dragging_playhead = false;
1122 Editor::access_action (std::string action_group, std::string action_item)
1128 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1131 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1139 Editor::on_realize ()
1143 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1144 start_lock_event_timing ();
1149 Editor::start_lock_event_timing ()
1151 /* check if we should lock the GUI every 30 seconds */
1153 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1157 Editor::generic_event_handler (GdkEvent* ev)
1160 case GDK_BUTTON_PRESS:
1161 case GDK_BUTTON_RELEASE:
1162 case GDK_MOTION_NOTIFY:
1164 case GDK_KEY_RELEASE:
1165 if (contents().is_mapped()) {
1166 gettimeofday (&last_event_time, 0);
1170 case GDK_LEAVE_NOTIFY:
1171 switch (ev->crossing.detail) {
1172 case GDK_NOTIFY_UNKNOWN:
1173 case GDK_NOTIFY_INFERIOR:
1174 case GDK_NOTIFY_ANCESTOR:
1176 case GDK_NOTIFY_VIRTUAL:
1177 case GDK_NOTIFY_NONLINEAR:
1178 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1179 /* leaving window, so reset focus, thus ending any and
1180 all text entry operations.
1182 reset_focus (&contents());
1195 Editor::lock_timeout_callback ()
1197 struct timeval now, delta;
1199 gettimeofday (&now, 0);
1201 timersub (&now, &last_event_time, &delta);
1203 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1205 /* don't call again. Returning false will effectively
1206 disconnect us from the timer callback.
1208 unlock() will call start_lock_event_timing() to get things
1218 Editor::map_position_change (framepos_t frame)
1220 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1222 if (_session == 0) {
1226 if (_follow_playhead) {
1227 center_screen (frame);
1230 playhead_cursor->set_position (frame);
1234 Editor::center_screen (framepos_t frame)
1236 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1238 /* if we're off the page, then scroll.
1241 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1242 center_screen_internal (frame, page);
1247 Editor::center_screen_internal (framepos_t frame, float page)
1252 frame -= (framepos_t) page;
1257 reset_x_origin (frame);
1262 Editor::update_title ()
1264 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1266 if (!own_window()) {
1271 bool dirty = _session->dirty();
1273 string session_name;
1275 if (_session->snap_name() != _session->name()) {
1276 session_name = _session->snap_name();
1278 session_name = _session->name();
1282 session_name = "*" + session_name;
1285 WindowTitle title(session_name);
1286 title += S_("Window|Editor");
1287 title += Glib::get_application_name();
1288 own_window()->set_title (title.get_string());
1290 /* ::session_going_away() will have taken care of it */
1295 Editor::set_session (Session *t)
1297 SessionHandlePtr::set_session (t);
1303 _playlist_selector->set_session (_session);
1304 nudge_clock->set_session (_session);
1305 _summary->set_session (_session);
1306 _group_tabs->set_session (_session);
1307 _route_groups->set_session (_session);
1308 _regions->set_session (_session);
1309 _snapshots->set_session (_session);
1310 _routes->set_session (_session);
1311 _locations->set_session (_session);
1313 if (rhythm_ferret) {
1314 rhythm_ferret->set_session (_session);
1317 if (analysis_window) {
1318 analysis_window->set_session (_session);
1322 sfbrowser->set_session (_session);
1325 compute_fixed_ruler_scale ();
1327 /* Make sure we have auto loop and auto punch ranges */
1329 Location* loc = _session->locations()->auto_loop_location();
1331 loc->set_name (_("Loop"));
1334 loc = _session->locations()->auto_punch_location();
1337 loc->set_name (_("Punch"));
1340 refresh_location_display ();
1342 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1343 the selected Marker; this needs the LocationMarker list to be available.
1345 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1346 set_state (*node, Stateful::loading_state_version);
1348 /* catch up with the playhead */
1350 _session->request_locate (playhead_cursor->current_frame ());
1351 _pending_initial_locate = true;
1355 /* These signals can all be emitted by a non-GUI thread. Therefore the
1356 handlers for them must not attempt to directly interact with the GUI,
1357 but use PBD::Signal<T>::connect() which accepts an event loop
1358 ("context") where the handler will be asked to run.
1361 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1362 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1363 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1364 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1365 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1366 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1367 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1368 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1369 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1370 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1371 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1372 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1373 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1375 playhead_cursor->show ();
1377 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1378 Config->map_parameters (pc);
1379 _session->config.map_parameters (pc);
1381 restore_ruler_visibility ();
1382 //tempo_map_changed (PropertyChange (0));
1383 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1385 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1386 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1389 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1390 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1393 switch (_snap_type) {
1394 case SnapToRegionStart:
1395 case SnapToRegionEnd:
1396 case SnapToRegionSync:
1397 case SnapToRegionBoundary:
1398 build_region_boundary_cache ();
1405 /* register for undo history */
1406 _session->register_with_memento_command_factory(id(), this);
1407 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1409 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1411 LuaInstance::instance()->set_session(_session);
1413 start_updating_meters ();
1417 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1419 if (a->get_name() == "RegionMenu") {
1420 /* When the main menu's region menu is opened, we setup the actions so that they look right
1421 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1422 so we resensitize all region actions when the entered regionview or the region selection
1423 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1424 happens after the region context menu is opened. So we set a flag here, too.
1428 sensitize_the_right_region_actions ();
1429 _last_region_menu_was_main = true;
1434 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1436 using namespace Menu_Helpers;
1438 void (Editor::*emf)(FadeShape);
1439 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1442 images = &_xfade_in_images;
1443 emf = &Editor::set_fade_in_shape;
1445 images = &_xfade_out_images;
1446 emf = &Editor::set_fade_out_shape;
1451 _("Linear (for highly correlated material)"),
1452 *(*images)[FadeLinear],
1453 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1457 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1461 _("Constant power"),
1462 *(*images)[FadeConstantPower],
1463 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1466 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1471 *(*images)[FadeSymmetric],
1472 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1476 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1481 *(*images)[FadeSlow],
1482 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1485 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1490 *(*images)[FadeFast],
1491 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1494 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1497 /** Pop up a context menu for when the user clicks on a start crossfade */
1499 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1501 using namespace Menu_Helpers;
1502 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1507 MenuList& items (xfade_in_context_menu.items());
1510 if (arv->audio_region()->fade_in_active()) {
1511 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1513 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1516 items.push_back (SeparatorElem());
1517 fill_xfade_menu (items, true);
1519 xfade_in_context_menu.popup (button, time);
1522 /** Pop up a context menu for when the user clicks on an end crossfade */
1524 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1526 using namespace Menu_Helpers;
1527 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1532 MenuList& items (xfade_out_context_menu.items());
1535 if (arv->audio_region()->fade_out_active()) {
1536 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1538 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1541 items.push_back (SeparatorElem());
1542 fill_xfade_menu (items, false);
1544 xfade_out_context_menu.popup (button, time);
1548 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1550 using namespace Menu_Helpers;
1551 Menu* (Editor::*build_menu_function)();
1554 switch (item_type) {
1556 case RegionViewName:
1557 case RegionViewNameHighlight:
1558 case LeftFrameHandle:
1559 case RightFrameHandle:
1560 if (with_selection) {
1561 build_menu_function = &Editor::build_track_selection_context_menu;
1563 build_menu_function = &Editor::build_track_region_context_menu;
1568 if (with_selection) {
1569 build_menu_function = &Editor::build_track_selection_context_menu;
1571 build_menu_function = &Editor::build_track_context_menu;
1576 if (clicked_routeview->track()) {
1577 build_menu_function = &Editor::build_track_context_menu;
1579 build_menu_function = &Editor::build_track_bus_context_menu;
1584 /* probably shouldn't happen but if it does, we don't care */
1588 menu = (this->*build_menu_function)();
1589 menu->set_name ("ArdourContextMenu");
1591 /* now handle specific situations */
1593 switch (item_type) {
1595 case RegionViewName:
1596 case RegionViewNameHighlight:
1597 case LeftFrameHandle:
1598 case RightFrameHandle:
1599 if (!with_selection) {
1600 if (region_edit_menu_split_item) {
1601 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1602 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1604 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1607 if (region_edit_menu_split_multichannel_item) {
1608 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1609 region_edit_menu_split_multichannel_item->set_sensitive (true);
1611 region_edit_menu_split_multichannel_item->set_sensitive (false);
1624 /* probably shouldn't happen but if it does, we don't care */
1628 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1630 /* Bounce to disk */
1632 using namespace Menu_Helpers;
1633 MenuList& edit_items = menu->items();
1635 edit_items.push_back (SeparatorElem());
1637 switch (clicked_routeview->audio_track()->freeze_state()) {
1638 case AudioTrack::NoFreeze:
1639 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1642 case AudioTrack::Frozen:
1643 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1646 case AudioTrack::UnFrozen:
1647 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1653 if (item_type == StreamItem && clicked_routeview) {
1654 clicked_routeview->build_underlay_menu(menu);
1657 /* When the region menu is opened, we setup the actions so that they look right
1660 sensitize_the_right_region_actions ();
1661 _last_region_menu_was_main = false;
1663 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1664 menu->popup (button, time);
1668 Editor::build_track_context_menu ()
1670 using namespace Menu_Helpers;
1672 MenuList& edit_items = track_context_menu.items();
1675 add_dstream_context_items (edit_items);
1676 return &track_context_menu;
1680 Editor::build_track_bus_context_menu ()
1682 using namespace Menu_Helpers;
1684 MenuList& edit_items = track_context_menu.items();
1687 add_bus_context_items (edit_items);
1688 return &track_context_menu;
1692 Editor::build_track_region_context_menu ()
1694 using namespace Menu_Helpers;
1695 MenuList& edit_items = track_region_context_menu.items();
1698 /* we've just cleared the track region context menu, so the menu that these
1699 two items were on will have disappeared; stop them dangling.
1701 region_edit_menu_split_item = 0;
1702 region_edit_menu_split_multichannel_item = 0;
1704 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1707 boost::shared_ptr<Track> tr;
1708 boost::shared_ptr<Playlist> pl;
1710 if ((tr = rtv->track())) {
1711 add_region_context_items (edit_items, tr);
1715 add_dstream_context_items (edit_items);
1717 return &track_region_context_menu;
1721 Editor::loudness_analyze_region_selection ()
1726 Selection& s (PublicEditor::instance ().get_selection ());
1727 RegionSelection ars = s.regions;
1728 ARDOUR::AnalysisGraph ag (_session);
1729 framecnt_t total_work = 0;
1731 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1732 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1736 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1739 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1740 total_work += arv->region ()->length ();
1743 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1745 ag.set_total_frames (total_work);
1746 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1749 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1750 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1754 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1758 ag.analyze_region (ar);
1761 if (!ag.canceled ()) {
1762 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1768 Editor::loudness_analyze_range_selection ()
1773 Selection& s (PublicEditor::instance ().get_selection ());
1774 TimeSelection ts = s.time;
1775 ARDOUR::AnalysisGraph ag (_session);
1776 framecnt_t total_work = 0;
1778 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1779 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1783 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1787 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1788 total_work += j->length ();
1792 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1794 ag.set_total_frames (total_work);
1795 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1798 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1799 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1803 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1807 ag.analyze_range (rui->route (), pl, ts);
1810 if (!ag.canceled ()) {
1811 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1817 Editor::spectral_analyze_region_selection ()
1819 if (analysis_window == 0) {
1820 analysis_window = new AnalysisWindow();
1823 analysis_window->set_session(_session);
1825 analysis_window->show_all();
1828 analysis_window->set_regionmode();
1829 analysis_window->analyze();
1831 analysis_window->present();
1835 Editor::spectral_analyze_range_selection()
1837 if (analysis_window == 0) {
1838 analysis_window = new AnalysisWindow();
1841 analysis_window->set_session(_session);
1843 analysis_window->show_all();
1846 analysis_window->set_rangemode();
1847 analysis_window->analyze();
1849 analysis_window->present();
1853 Editor::build_track_selection_context_menu ()
1855 using namespace Menu_Helpers;
1856 MenuList& edit_items = track_selection_context_menu.items();
1857 edit_items.clear ();
1859 add_selection_context_items (edit_items);
1860 // edit_items.push_back (SeparatorElem());
1861 // add_dstream_context_items (edit_items);
1863 return &track_selection_context_menu;
1867 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1869 using namespace Menu_Helpers;
1871 /* OK, stick the region submenu at the top of the list, and then add
1875 RegionSelection rs = get_regions_from_selection_and_entered ();
1877 string::size_type pos = 0;
1878 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1880 /* we have to hack up the region name because "_" has a special
1881 meaning for menu titles.
1884 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1885 menu_item_name.replace (pos, 1, "__");
1889 if (_popup_region_menu_item == 0) {
1890 _popup_region_menu_item = new MenuItem (menu_item_name);
1891 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1892 _popup_region_menu_item->show ();
1894 _popup_region_menu_item->set_label (menu_item_name);
1897 /* No latering allowed in later is higher layering model */
1898 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1899 if (act && Config->get_layer_model() == LaterHigher) {
1900 act->set_sensitive (false);
1902 act->set_sensitive (true);
1905 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1907 edit_items.push_back (*_popup_region_menu_item);
1908 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1909 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1911 edit_items.push_back (SeparatorElem());
1914 /** Add context menu items relevant to selection ranges.
1915 * @param edit_items List to add the items to.
1918 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1920 using namespace Menu_Helpers;
1922 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1923 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1925 edit_items.push_back (SeparatorElem());
1926 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1928 edit_items.push_back (SeparatorElem());
1929 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1930 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1932 edit_items.push_back (SeparatorElem());
1934 edit_items.push_back (
1936 _("Move Range Start to Previous Region Boundary"),
1937 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1941 edit_items.push_back (
1943 _("Move Range Start to Next Region Boundary"),
1944 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1948 edit_items.push_back (
1950 _("Move Range End to Previous Region Boundary"),
1951 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1955 edit_items.push_back (
1957 _("Move Range End to Next Region Boundary"),
1958 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1962 edit_items.push_back (SeparatorElem());
1963 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1964 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1966 edit_items.push_back (SeparatorElem());
1967 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1969 edit_items.push_back (SeparatorElem());
1970 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1971 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1972 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1974 edit_items.push_back (SeparatorElem());
1975 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1977 edit_items.push_back (SeparatorElem());
1978 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1979 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1981 edit_items.push_back (SeparatorElem());
1982 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1983 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1984 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1985 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1986 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1987 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1988 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1994 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1996 using namespace Menu_Helpers;
2000 Menu *play_menu = manage (new Menu);
2001 MenuList& play_items = play_menu->items();
2002 play_menu->set_name ("ArdourContextMenu");
2004 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2005 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2006 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2007 play_items.push_back (SeparatorElem());
2008 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2010 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2014 Menu *select_menu = manage (new Menu);
2015 MenuList& select_items = select_menu->items();
2016 select_menu->set_name ("ArdourContextMenu");
2018 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2019 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2020 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2021 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2022 select_items.push_back (SeparatorElem());
2023 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2024 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2025 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2026 select_items.push_back (SeparatorElem());
2027 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2028 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2029 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2030 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2031 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2032 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2033 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2035 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2039 Menu *cutnpaste_menu = manage (new Menu);
2040 MenuList& cutnpaste_items = cutnpaste_menu->items();
2041 cutnpaste_menu->set_name ("ArdourContextMenu");
2043 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2044 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2045 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2047 cutnpaste_items.push_back (SeparatorElem());
2049 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2050 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2052 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2054 /* Adding new material */
2056 edit_items.push_back (SeparatorElem());
2057 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2058 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2062 Menu *nudge_menu = manage (new Menu());
2063 MenuList& nudge_items = nudge_menu->items();
2064 nudge_menu->set_name ("ArdourContextMenu");
2066 edit_items.push_back (SeparatorElem());
2067 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2068 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2069 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2070 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2072 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2076 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2078 using namespace Menu_Helpers;
2082 Menu *play_menu = manage (new Menu);
2083 MenuList& play_items = play_menu->items();
2084 play_menu->set_name ("ArdourContextMenu");
2086 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2087 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2088 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2092 Menu *select_menu = manage (new Menu);
2093 MenuList& select_items = select_menu->items();
2094 select_menu->set_name ("ArdourContextMenu");
2096 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2097 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2098 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2099 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2100 select_items.push_back (SeparatorElem());
2101 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2102 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2103 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2104 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2106 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2110 Menu *cutnpaste_menu = manage (new Menu);
2111 MenuList& cutnpaste_items = cutnpaste_menu->items();
2112 cutnpaste_menu->set_name ("ArdourContextMenu");
2114 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2115 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2116 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2118 Menu *nudge_menu = manage (new Menu());
2119 MenuList& nudge_items = nudge_menu->items();
2120 nudge_menu->set_name ("ArdourContextMenu");
2122 edit_items.push_back (SeparatorElem());
2123 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2124 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2125 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2126 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2128 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2132 Editor::snap_type() const
2138 Editor::snap_mode() const
2144 Editor::set_snap_to (SnapType st)
2146 unsigned int snap_ind = (unsigned int)st;
2148 if (internal_editing()) {
2149 internal_snap_type = st;
2151 pre_internal_snap_type = st;
2156 if (snap_ind > snap_type_strings.size() - 1) {
2158 _snap_type = (SnapType)snap_ind;
2161 string str = snap_type_strings[snap_ind];
2163 if (str != snap_type_selector.get_text()) {
2164 snap_type_selector.set_text (str);
2169 switch (_snap_type) {
2170 case SnapToBeatDiv128:
2171 case SnapToBeatDiv64:
2172 case SnapToBeatDiv32:
2173 case SnapToBeatDiv28:
2174 case SnapToBeatDiv24:
2175 case SnapToBeatDiv20:
2176 case SnapToBeatDiv16:
2177 case SnapToBeatDiv14:
2178 case SnapToBeatDiv12:
2179 case SnapToBeatDiv10:
2180 case SnapToBeatDiv8:
2181 case SnapToBeatDiv7:
2182 case SnapToBeatDiv6:
2183 case SnapToBeatDiv5:
2184 case SnapToBeatDiv4:
2185 case SnapToBeatDiv3:
2186 case SnapToBeatDiv2: {
2187 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2188 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2190 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2191 current_bbt_points_begin, current_bbt_points_end);
2192 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2193 current_bbt_points_begin, current_bbt_points_end);
2194 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2198 case SnapToRegionStart:
2199 case SnapToRegionEnd:
2200 case SnapToRegionSync:
2201 case SnapToRegionBoundary:
2202 build_region_boundary_cache ();
2210 redisplay_tempo (false);
2212 SnapChanged (); /* EMIT SIGNAL */
2216 Editor::set_snap_mode (SnapMode mode)
2218 string str = snap_mode_strings[(int)mode];
2220 if (internal_editing()) {
2221 internal_snap_mode = mode;
2223 pre_internal_snap_mode = mode;
2228 if (str != snap_mode_selector.get_text ()) {
2229 snap_mode_selector.set_text (str);
2236 Editor::set_edit_point_preference (EditPoint ep, bool force)
2238 bool changed = (_edit_point != ep);
2241 if (Profile->get_mixbus())
2242 if (ep == EditAtSelectedMarker)
2243 ep = EditAtPlayhead;
2245 string str = edit_point_strings[(int)ep];
2246 if (str != edit_point_selector.get_text ()) {
2247 edit_point_selector.set_text (str);
2250 update_all_enter_cursors();
2252 if (!force && !changed) {
2256 const char* action=NULL;
2258 switch (_edit_point) {
2259 case EditAtPlayhead:
2260 action = "edit-at-playhead";
2262 case EditAtSelectedMarker:
2263 action = "edit-at-marker";
2266 action = "edit-at-mouse";
2270 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2272 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2276 bool in_track_canvas;
2278 if (!mouse_frame (foo, in_track_canvas)) {
2279 in_track_canvas = false;
2282 reset_canvas_action_sensitivity (in_track_canvas);
2288 Editor::set_state (const XMLNode& node, int version)
2290 XMLProperty const * prop;
2293 Tabbable::set_state (node, version);
2295 if (_session && (prop = node.property ("playhead"))) {
2297 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2299 playhead_cursor->set_position (pos);
2301 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2302 playhead_cursor->set_position (0);
2305 playhead_cursor->set_position (0);
2308 if ((prop = node.property ("mixer-width"))) {
2309 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2312 if ((prop = node.property ("zoom-focus"))) {
2313 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2316 if ((prop = node.property ("zoom"))) {
2317 /* older versions of ardour used floating point samples_per_pixel */
2318 double f = PBD::atof (prop->value());
2319 reset_zoom (llrintf (f));
2321 reset_zoom (samples_per_pixel);
2324 if ((prop = node.property ("visible-track-count"))) {
2325 set_visible_track_count (PBD::atoi (prop->value()));
2328 if ((prop = node.property ("snap-to"))) {
2329 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2332 if ((prop = node.property ("snap-mode"))) {
2333 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2336 if ((prop = node.property ("internal-snap-to"))) {
2337 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2340 if ((prop = node.property ("internal-snap-mode"))) {
2341 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2344 if ((prop = node.property ("pre-internal-snap-to"))) {
2345 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2348 if ((prop = node.property ("pre-internal-snap-mode"))) {
2349 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2352 if ((prop = node.property ("mouse-mode"))) {
2353 MouseMode m = str2mousemode(prop->value());
2354 set_mouse_mode (m, true);
2356 set_mouse_mode (MouseObject, true);
2359 if ((prop = node.property ("left-frame")) != 0) {
2361 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2365 reset_x_origin (pos);
2369 if ((prop = node.property ("y-origin")) != 0) {
2370 reset_y_origin (atof (prop->value ()));
2373 if ((prop = node.property ("join-object-range"))) {
2374 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2375 bool yn = string_is_affirmative (prop->value());
2377 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2378 tact->set_active (!yn);
2379 tact->set_active (yn);
2381 set_mouse_mode(mouse_mode, true);
2384 if ((prop = node.property ("edit-point"))) {
2385 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2388 if ((prop = node.property ("show-measures"))) {
2389 bool yn = string_is_affirmative (prop->value());
2390 _show_measures = yn;
2393 if ((prop = node.property ("follow-playhead"))) {
2394 bool yn = string_is_affirmative (prop->value());
2395 set_follow_playhead (yn);
2398 if ((prop = node.property ("stationary-playhead"))) {
2399 bool yn = string_is_affirmative (prop->value());
2400 set_stationary_playhead (yn);
2403 if ((prop = node.property ("region-list-sort-type"))) {
2404 RegionListSortType st;
2405 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2408 if ((prop = node.property ("show-editor-mixer"))) {
2410 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2413 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2414 bool yn = string_is_affirmative (prop->value());
2416 /* do it twice to force the change */
2418 tact->set_active (!yn);
2419 tact->set_active (yn);
2422 if ((prop = node.property ("show-editor-list"))) {
2424 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2427 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2428 bool yn = string_is_affirmative (prop->value());
2430 /* do it twice to force the change */
2432 tact->set_active (!yn);
2433 tact->set_active (yn);
2436 if ((prop = node.property (X_("editor-list-page")))) {
2437 _the_notebook.set_current_page (atoi (prop->value ()));
2440 if ((prop = node.property (X_("show-marker-lines")))) {
2441 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2443 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2444 bool yn = string_is_affirmative (prop->value ());
2446 tact->set_active (!yn);
2447 tact->set_active (yn);
2450 XMLNodeList children = node.children ();
2451 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2452 selection->set_state (**i, Stateful::current_state_version);
2453 _regions->set_state (**i);
2456 if ((prop = node.property ("maximised"))) {
2457 bool yn = string_is_affirmative (prop->value());
2458 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2460 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2461 bool fs = tact && tact->get_active();
2463 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2467 if ((prop = node.property ("nudge-clock-value"))) {
2469 sscanf (prop->value().c_str(), "%" PRId64, &f);
2470 nudge_clock->set (f);
2472 nudge_clock->set_mode (AudioClock::Timecode);
2473 nudge_clock->set (_session->frame_rate() * 5, true);
2478 * Not all properties may have been in XML, but
2479 * those that are linked to a private variable may need changing
2484 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2486 yn = _show_measures;
2487 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2488 /* do it twice to force the change */
2489 tact->set_active (!yn);
2490 tact->set_active (yn);
2493 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2494 yn = _follow_playhead;
2496 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2497 if (tact->get_active() != yn) {
2498 tact->set_active (yn);
2502 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2503 yn = _stationary_playhead;
2505 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2506 if (tact->get_active() != yn) {
2507 tact->set_active (yn);
2512 return LuaInstance::instance()->set_state(node);
2516 Editor::get_state ()
2518 XMLNode* node = new XMLNode (X_("Editor"));
2521 id().print (buf, sizeof (buf));
2522 node->add_property ("id", buf);
2524 node->add_child_nocopy (Tabbable::get_state());
2526 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2527 node->add_property("edit-horizontal-pane-pos", string(buf));
2528 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2529 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2530 node->add_property("edit-vertical-pane-pos", string(buf));
2532 maybe_add_mixer_strip_width (*node);
2534 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2536 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2537 node->add_property ("zoom", buf);
2538 node->add_property ("snap-to", enum_2_string (_snap_type));
2539 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2540 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2541 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2542 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2543 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2544 node->add_property ("edit-point", enum_2_string (_edit_point));
2545 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2546 node->add_property ("visible-track-count", buf);
2548 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2549 node->add_property ("playhead", buf);
2550 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2551 node->add_property ("left-frame", buf);
2552 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2553 node->add_property ("y-origin", buf);
2555 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2556 node->add_property ("maximised", _maximised ? "yes" : "no");
2557 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2558 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2559 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2560 node->add_property ("mouse-mode", enum2str(mouse_mode));
2561 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2563 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2565 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2566 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2569 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2571 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2572 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2575 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2576 node->add_property (X_("editor-list-page"), buf);
2578 if (button_bindings) {
2579 XMLNode* bb = new XMLNode (X_("Buttons"));
2580 button_bindings->save (*bb);
2581 node->add_child_nocopy (*bb);
2584 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2586 node->add_child_nocopy (selection->get_state ());
2587 node->add_child_nocopy (_regions->get_state ());
2589 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2590 node->add_property ("nudge-clock-value", buf);
2592 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2593 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2598 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2599 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2601 * @return pair: TimeAxisView that y is over, layer index.
2603 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2604 * in stacked or expanded region display mode, otherwise 0.
2606 std::pair<TimeAxisView *, double>
2607 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2609 if (!trackview_relative_offset) {
2610 y -= _trackview_group->canvas_origin().y;
2614 return std::make_pair ( (TimeAxisView *) 0, 0);
2617 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2619 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2626 return std::make_pair ( (TimeAxisView *) 0, 0);
2629 /** Snap a position to the grid, if appropriate, taking into account current
2630 * grid settings and also the state of any snap modifier keys that may be pressed.
2631 * @param start Position to snap.
2632 * @param event Event to get current key modifier information from, or 0.
2635 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2637 if (!_session || !event) {
2641 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2642 if (_snap_mode == SnapOff) {
2643 snap_to_internal (start, direction, for_mark);
2646 if (_snap_mode != SnapOff) {
2647 snap_to_internal (start, direction, for_mark);
2648 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2649 /* SnapOff, but we pressed the snap_delta modifier */
2650 snap_to_internal (start, direction, for_mark);
2656 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2658 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2662 snap_to_internal (start, direction, for_mark, ensure_snap);
2666 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2668 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2669 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2671 switch (_snap_type) {
2672 case SnapToTimecodeFrame:
2673 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2674 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2675 /* start is already on a whole timecode frame, do nothing */
2676 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2677 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2679 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2683 case SnapToTimecodeSeconds:
2684 if (_session->config.get_timecode_offset_negative()) {
2685 start += _session->config.get_timecode_offset ();
2687 start -= _session->config.get_timecode_offset ();
2689 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2690 (start % one_timecode_second == 0)) {
2691 /* start is already on a whole second, do nothing */
2692 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2693 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2695 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2698 if (_session->config.get_timecode_offset_negative()) {
2699 start -= _session->config.get_timecode_offset ();
2701 start += _session->config.get_timecode_offset ();
2705 case SnapToTimecodeMinutes:
2706 if (_session->config.get_timecode_offset_negative()) {
2707 start += _session->config.get_timecode_offset ();
2709 start -= _session->config.get_timecode_offset ();
2711 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2712 (start % one_timecode_minute == 0)) {
2713 /* start is already on a whole minute, do nothing */
2714 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2715 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2717 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2719 if (_session->config.get_timecode_offset_negative()) {
2720 start -= _session->config.get_timecode_offset ();
2722 start += _session->config.get_timecode_offset ();
2726 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2727 abort(); /*NOTREACHED*/
2732 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2734 const framepos_t one_second = _session->frame_rate();
2735 const framepos_t one_minute = _session->frame_rate() * 60;
2736 framepos_t presnap = start;
2740 switch (_snap_type) {
2741 case SnapToTimecodeFrame:
2742 case SnapToTimecodeSeconds:
2743 case SnapToTimecodeMinutes:
2744 return timecode_snap_to_internal (start, direction, for_mark);
2747 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2748 start % (one_second/75) == 0) {
2749 /* start is already on a whole CD frame, do nothing */
2750 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2751 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2753 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2758 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2759 start % one_second == 0) {
2760 /* start is already on a whole second, do nothing */
2761 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2762 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2764 start = (framepos_t) floor ((double) start / one_second) * one_second;
2769 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2770 start % one_minute == 0) {
2771 /* start is already on a whole minute, do nothing */
2772 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2773 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2775 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2780 start = _session->tempo_map().round_to_bar (start, direction);
2784 start = _session->tempo_map().round_to_beat (start, direction);
2787 case SnapToBeatDiv128:
2788 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2790 case SnapToBeatDiv64:
2791 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2793 case SnapToBeatDiv32:
2794 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2796 case SnapToBeatDiv28:
2797 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2799 case SnapToBeatDiv24:
2800 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2802 case SnapToBeatDiv20:
2803 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2805 case SnapToBeatDiv16:
2806 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2808 case SnapToBeatDiv14:
2809 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2811 case SnapToBeatDiv12:
2812 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2814 case SnapToBeatDiv10:
2815 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2817 case SnapToBeatDiv8:
2818 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2820 case SnapToBeatDiv7:
2821 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2823 case SnapToBeatDiv6:
2824 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2826 case SnapToBeatDiv5:
2827 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2829 case SnapToBeatDiv4:
2830 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2832 case SnapToBeatDiv3:
2833 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2835 case SnapToBeatDiv2:
2836 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2844 _session->locations()->marks_either_side (start, before, after);
2846 if (before == max_framepos && after == max_framepos) {
2847 /* No marks to snap to, so just don't snap */
2849 } else if (before == max_framepos) {
2851 } else if (after == max_framepos) {
2853 } else if (before != max_framepos && after != max_framepos) {
2854 /* have before and after */
2855 if ((start - before) < (after - start)) {
2864 case SnapToRegionStart:
2865 case SnapToRegionEnd:
2866 case SnapToRegionSync:
2867 case SnapToRegionBoundary:
2868 if (!region_boundary_cache.empty()) {
2870 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2871 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2873 if (direction > 0) {
2874 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2876 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2879 if (next != region_boundary_cache.begin ()) {
2884 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2885 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2887 if (start > (p + n) / 2) {
2896 switch (_snap_mode) {
2906 if (presnap > start) {
2907 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2911 } else if (presnap < start) {
2912 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2918 /* handled at entry */
2926 Editor::setup_toolbar ()
2928 HBox* mode_box = manage(new HBox);
2929 mode_box->set_border_width (2);
2930 mode_box->set_spacing(2);
2932 HBox* mouse_mode_box = manage (new HBox);
2933 HBox* mouse_mode_hbox = manage (new HBox);
2934 VBox* mouse_mode_vbox = manage (new VBox);
2935 Alignment* mouse_mode_align = manage (new Alignment);
2937 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2938 mouse_mode_size_group->add_widget (smart_mode_button);
2939 mouse_mode_size_group->add_widget (mouse_move_button);
2940 mouse_mode_size_group->add_widget (mouse_cut_button);
2941 mouse_mode_size_group->add_widget (mouse_select_button);
2942 mouse_mode_size_group->add_widget (mouse_timefx_button);
2943 mouse_mode_size_group->add_widget (mouse_audition_button);
2944 mouse_mode_size_group->add_widget (mouse_draw_button);
2945 mouse_mode_size_group->add_widget (mouse_content_button);
2947 mouse_mode_size_group->add_widget (zoom_in_button);
2948 mouse_mode_size_group->add_widget (zoom_out_button);
2949 mouse_mode_size_group->add_widget (zoom_preset_selector);
2950 mouse_mode_size_group->add_widget (zoom_out_full_button);
2951 mouse_mode_size_group->add_widget (zoom_focus_selector);
2953 mouse_mode_size_group->add_widget (tav_shrink_button);
2954 mouse_mode_size_group->add_widget (tav_expand_button);
2955 mouse_mode_size_group->add_widget (visible_tracks_selector);
2957 mouse_mode_size_group->add_widget (snap_type_selector);
2958 mouse_mode_size_group->add_widget (snap_mode_selector);
2960 mouse_mode_size_group->add_widget (edit_point_selector);
2961 mouse_mode_size_group->add_widget (edit_mode_selector);
2963 mouse_mode_size_group->add_widget (*nudge_clock);
2964 mouse_mode_size_group->add_widget (nudge_forward_button);
2965 mouse_mode_size_group->add_widget (nudge_backward_button);
2967 mouse_mode_hbox->set_spacing (2);
2969 if (!ARDOUR::Profile->get_trx()) {
2970 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2973 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2974 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2976 if (!ARDOUR::Profile->get_mixbus()) {
2977 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2980 if (!ARDOUR::Profile->get_trx()) {
2981 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2982 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2983 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2984 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2987 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2989 mouse_mode_align->add (*mouse_mode_vbox);
2990 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2992 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2994 edit_mode_selector.set_name ("mouse mode button");
2996 if (!ARDOUR::Profile->get_trx()) {
2997 mode_box->pack_start (edit_mode_selector, false, false);
3000 mode_box->pack_start (*mouse_mode_box, false, false);
3004 _zoom_box.set_spacing (2);
3005 _zoom_box.set_border_width (2);
3009 zoom_preset_selector.set_name ("zoom button");
3010 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3011 zoom_preset_selector.set_size_request (42, -1);
3013 zoom_in_button.set_name ("zoom button");
3014 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3015 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3016 zoom_in_button.set_related_action (act);
3018 zoom_out_button.set_name ("zoom button");
3019 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3020 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3021 zoom_out_button.set_related_action (act);
3023 zoom_out_full_button.set_name ("zoom button");
3024 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3025 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3026 zoom_out_full_button.set_related_action (act);
3028 zoom_focus_selector.set_name ("zoom button");
3030 if (ARDOUR::Profile->get_mixbus()) {
3031 _zoom_box.pack_start (zoom_preset_selector, false, false);
3032 } else if (ARDOUR::Profile->get_trx()) {
3033 mode_box->pack_start (zoom_out_button, false, false);
3034 mode_box->pack_start (zoom_in_button, false, false);
3036 _zoom_box.pack_start (zoom_out_button, false, false);
3037 _zoom_box.pack_start (zoom_in_button, false, false);
3038 _zoom_box.pack_start (zoom_out_full_button, false, false);
3039 _zoom_box.pack_start (zoom_focus_selector, false, false);
3042 /* Track zoom buttons */
3043 visible_tracks_selector.set_name ("zoom button");
3044 if (Profile->get_mixbus()) {
3045 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3046 visible_tracks_selector.set_size_request (42, -1);
3048 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3051 tav_expand_button.set_name ("zoom button");
3052 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3053 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3054 tav_expand_button.set_related_action (act);
3056 tav_shrink_button.set_name ("zoom button");
3057 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3058 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3059 tav_shrink_button.set_related_action (act);
3061 if (ARDOUR::Profile->get_mixbus()) {
3062 _zoom_box.pack_start (visible_tracks_selector);
3063 } else if (ARDOUR::Profile->get_trx()) {
3064 _zoom_box.pack_start (tav_shrink_button);
3065 _zoom_box.pack_start (tav_expand_button);
3067 _zoom_box.pack_start (visible_tracks_selector);
3068 _zoom_box.pack_start (tav_shrink_button);
3069 _zoom_box.pack_start (tav_expand_button);
3072 snap_box.set_spacing (2);
3073 snap_box.set_border_width (2);
3075 snap_type_selector.set_name ("mouse mode button");
3077 snap_mode_selector.set_name ("mouse mode button");
3079 edit_point_selector.set_name ("mouse mode button");
3081 snap_box.pack_start (snap_mode_selector, false, false);
3082 snap_box.pack_start (snap_type_selector, false, false);
3083 snap_box.pack_start (edit_point_selector, false, false);
3087 HBox *nudge_box = manage (new HBox);
3088 nudge_box->set_spacing (2);
3089 nudge_box->set_border_width (2);
3091 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3092 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3094 nudge_box->pack_start (nudge_backward_button, false, false);
3095 nudge_box->pack_start (nudge_forward_button, false, false);
3096 nudge_box->pack_start (*nudge_clock, false, false);
3099 /* Pack everything in... */
3101 HBox* hbox = manage (new HBox);
3102 hbox->set_spacing(2);
3104 toolbar_hbox.set_spacing (2);
3105 toolbar_hbox.set_border_width (1);
3107 toolbar_hbox.pack_start (*mode_box, false, false);
3108 if (!ARDOUR::Profile->get_trx()) {
3109 toolbar_hbox.pack_start (_zoom_box, false, false);
3110 toolbar_hbox.pack_start (*hbox, false, false);
3113 if (!ARDOUR::Profile->get_trx()) {
3114 hbox->pack_start (snap_box, false, false);
3115 hbox->pack_start (*nudge_box, false, false);
3120 toolbar_base.set_name ("ToolBarBase");
3121 toolbar_base.add (toolbar_hbox);
3123 _toolbar_viewport.add (toolbar_base);
3124 /* stick to the required height but allow width to vary if there's not enough room */
3125 _toolbar_viewport.set_size_request (1, -1);
3127 toolbar_frame.set_shadow_type (SHADOW_OUT);
3128 toolbar_frame.set_name ("BaseFrame");
3129 toolbar_frame.add (_toolbar_viewport);
3133 Editor::build_edit_point_menu ()
3135 using namespace Menu_Helpers;
3137 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3138 if(!Profile->get_mixbus())
3139 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3140 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3142 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3146 Editor::build_edit_mode_menu ()
3148 using namespace Menu_Helpers;
3150 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3151 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3152 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3153 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3155 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3159 Editor::build_snap_mode_menu ()
3161 using namespace Menu_Helpers;
3163 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3164 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3165 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3167 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3171 Editor::build_snap_type_menu ()
3173 using namespace Menu_Helpers;
3175 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3176 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3177 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3178 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3179 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3180 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3181 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3182 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3183 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3184 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3185 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3186 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3187 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3188 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3189 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3190 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3191 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3192 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3193 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3194 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3195 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3196 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3197 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3198 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3199 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3200 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3201 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3202 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3203 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3204 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3206 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3211 Editor::setup_tooltips ()
3213 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3214 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3215 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3216 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3217 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3218 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3219 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3220 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3221 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3222 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3223 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3224 set_tooltip (zoom_in_button, _("Zoom In"));
3225 set_tooltip (zoom_out_button, _("Zoom Out"));
3226 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3227 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3228 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3229 set_tooltip (tav_expand_button, _("Expand Tracks"));
3230 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3231 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3232 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3233 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3234 set_tooltip (edit_point_selector, _("Edit Point"));
3235 set_tooltip (edit_mode_selector, _("Edit Mode"));
3236 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3240 Editor::convert_drop_to_paths (
3241 vector<string>& paths,
3242 const RefPtr<Gdk::DragContext>& /*context*/,
3245 const SelectionData& data,
3249 if (_session == 0) {
3253 vector<string> uris = data.get_uris();
3257 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3258 are actually URI lists. So do it by hand.
3261 if (data.get_target() != "text/plain") {
3265 /* Parse the "uri-list" format that Nautilus provides,
3266 where each pathname is delimited by \r\n.
3268 THERE MAY BE NO NULL TERMINATING CHAR!!!
3271 string txt = data.get_text();
3275 p = (char *) malloc (txt.length() + 1);
3276 txt.copy (p, txt.length(), 0);
3277 p[txt.length()] = '\0';
3283 while (g_ascii_isspace (*p))
3287 while (*q && (*q != '\n') && (*q != '\r')) {
3294 while (q > p && g_ascii_isspace (*q))
3299 uris.push_back (string (p, q - p + 1));
3303 p = strchr (p, '\n');
3315 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3316 if ((*i).substr (0,7) == "file://") {
3317 paths.push_back (Glib::filename_from_uri (*i));
3325 Editor::new_tempo_section ()
3330 Editor::map_transport_state ()
3332 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3334 if (_session && _session->transport_stopped()) {
3335 have_pending_keyboard_selection = false;
3338 update_loop_range_view ();
3344 Editor::begin_selection_op_history ()
3346 selection_op_cmd_depth = 0;
3347 selection_op_history_it = 0;
3349 while(!selection_op_history.empty()) {
3350 delete selection_op_history.front();
3351 selection_op_history.pop_front();
3354 selection_undo_action->set_sensitive (false);
3355 selection_redo_action->set_sensitive (false);
3356 selection_op_history.push_front (&_selection_memento->get_state ());
3360 Editor::begin_reversible_selection_op (string name)
3363 //cerr << name << endl;
3364 /* begin/commit pairs can be nested */
3365 selection_op_cmd_depth++;
3370 Editor::commit_reversible_selection_op ()
3373 if (selection_op_cmd_depth == 1) {
3375 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3377 The user has undone some selection ops and then made a new one,
3378 making anything earlier in the list invalid.
3381 list<XMLNode *>::iterator it = selection_op_history.begin();
3382 list<XMLNode *>::iterator e_it = it;
3383 advance (e_it, selection_op_history_it);
3385 for ( ; it != e_it; ++it) {
3388 selection_op_history.erase (selection_op_history.begin(), e_it);
3391 selection_op_history.push_front (&_selection_memento->get_state ());
3392 selection_op_history_it = 0;
3394 selection_undo_action->set_sensitive (true);
3395 selection_redo_action->set_sensitive (false);
3398 if (selection_op_cmd_depth > 0) {
3399 selection_op_cmd_depth--;
3405 Editor::undo_selection_op ()
3408 selection_op_history_it++;
3410 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3411 if (n == selection_op_history_it) {
3412 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3413 selection_redo_action->set_sensitive (true);
3417 /* is there an earlier entry? */
3418 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3419 selection_undo_action->set_sensitive (false);
3425 Editor::redo_selection_op ()
3428 if (selection_op_history_it > 0) {
3429 selection_op_history_it--;
3432 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3433 if (n == selection_op_history_it) {
3434 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3435 selection_undo_action->set_sensitive (true);
3440 if (selection_op_history_it == 0) {
3441 selection_redo_action->set_sensitive (false);
3447 Editor::begin_reversible_command (string name)
3450 before.push_back (&_selection_memento->get_state ());
3451 _session->begin_reversible_command (name);
3456 Editor::begin_reversible_command (GQuark q)
3459 before.push_back (&_selection_memento->get_state ());
3460 _session->begin_reversible_command (q);
3465 Editor::abort_reversible_command ()
3468 while(!before.empty()) {
3469 delete before.front();
3472 _session->abort_reversible_command ();
3477 Editor::commit_reversible_command ()
3480 if (before.size() == 1) {
3481 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3482 redo_action->set_sensitive(false);
3483 undo_action->set_sensitive(true);
3484 begin_selection_op_history ();
3487 if (before.empty()) {
3488 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3493 _session->commit_reversible_command ();
3498 Editor::history_changed ()
3502 if (undo_action && _session) {
3503 if (_session->undo_depth() == 0) {
3504 label = S_("Command|Undo");
3506 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3508 undo_action->property_label() = label;
3511 if (redo_action && _session) {
3512 if (_session->redo_depth() == 0) {
3514 redo_action->set_sensitive (false);
3516 label = string_compose(_("Redo (%1)"), _session->next_redo());
3517 redo_action->set_sensitive (true);
3519 redo_action->property_label() = label;
3524 Editor::duplicate_range (bool with_dialog)
3528 RegionSelection rs = get_regions_from_selection_and_entered ();
3530 if ( selection->time.length() == 0 && rs.empty()) {
3536 ArdourDialog win (_("Duplicate"));
3537 Label label (_("Number of duplications:"));
3538 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3539 SpinButton spinner (adjustment, 0.0, 1);
3542 win.get_vbox()->set_spacing (12);
3543 win.get_vbox()->pack_start (hbox);
3544 hbox.set_border_width (6);
3545 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3547 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3548 place, visually. so do this by hand.
3551 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3552 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3553 spinner.grab_focus();
3559 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3560 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3561 win.set_default_response (RESPONSE_ACCEPT);
3563 spinner.grab_focus ();
3565 switch (win.run ()) {
3566 case RESPONSE_ACCEPT:
3572 times = adjustment.get_value();
3575 if ((current_mouse_mode() == Editing::MouseRange)) {
3576 if (selection->time.length()) {
3577 duplicate_selection (times);
3579 } else if (get_smart_mode()) {
3580 if (selection->time.length()) {
3581 duplicate_selection (times);
3583 duplicate_some_regions (rs, times);
3585 duplicate_some_regions (rs, times);
3590 Editor::set_edit_mode (EditMode m)
3592 Config->set_edit_mode (m);
3596 Editor::cycle_edit_mode ()
3598 switch (Config->get_edit_mode()) {
3600 Config->set_edit_mode (Ripple);
3604 Config->set_edit_mode (Lock);
3607 Config->set_edit_mode (Slide);
3613 Editor::edit_mode_selection_done ( EditMode m )
3615 Config->set_edit_mode ( m );
3619 Editor::snap_type_selection_done (SnapType snaptype)
3621 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3623 ract->set_active ();
3628 Editor::snap_mode_selection_done (SnapMode mode)
3630 RefPtr<RadioAction> ract = snap_mode_action (mode);
3633 ract->set_active (true);
3638 Editor::cycle_edit_point (bool with_marker)
3640 if(Profile->get_mixbus())
3641 with_marker = false;
3643 switch (_edit_point) {
3645 set_edit_point_preference (EditAtPlayhead);
3647 case EditAtPlayhead:
3649 set_edit_point_preference (EditAtSelectedMarker);
3651 set_edit_point_preference (EditAtMouse);
3654 case EditAtSelectedMarker:
3655 set_edit_point_preference (EditAtMouse);
3661 Editor::edit_point_selection_done (EditPoint ep)
3663 set_edit_point_preference ( ep );
3667 Editor::build_zoom_focus_menu ()
3669 using namespace Menu_Helpers;
3671 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3672 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3673 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3674 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3675 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3676 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3678 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3682 Editor::zoom_focus_selection_done ( ZoomFocus f )
3684 RefPtr<RadioAction> ract = zoom_focus_action (f);
3686 ract->set_active ();
3691 Editor::build_track_count_menu ()
3693 using namespace Menu_Helpers;
3695 if (!Profile->get_mixbus()) {
3696 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3697 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3698 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3699 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3700 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3701 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3702 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3703 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3704 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3705 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3706 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3707 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3708 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3710 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3711 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3712 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3713 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3714 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3715 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3716 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3717 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3718 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3719 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3721 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3722 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3723 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3724 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3725 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3726 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3727 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3728 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3729 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3730 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3731 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3736 Editor::set_zoom_preset (int64_t ms)
3739 temporal_zoom_session();
3743 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3744 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3748 Editor::set_visible_track_count (int32_t n)
3750 _visible_track_count = n;
3752 /* if the canvas hasn't really been allocated any size yet, just
3753 record the desired number of visible tracks and return. when canvas
3754 allocation happens, we will get called again and then we can do the
3758 if (_visible_canvas_height <= 1) {
3764 DisplaySuspender ds;
3766 if (_visible_track_count > 0) {
3767 h = trackviews_height() / _visible_track_count;
3768 std::ostringstream s;
3769 s << _visible_track_count;
3771 } else if (_visible_track_count == 0) {
3773 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3774 if ((*i)->marked_for_display()) {
3778 h = trackviews_height() / n;
3781 /* negative value means that the visible track count has
3782 been overridden by explicit track height changes.
3784 visible_tracks_selector.set_text (X_("*"));
3788 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3789 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3792 if (str != visible_tracks_selector.get_text()) {
3793 visible_tracks_selector.set_text (str);
3798 Editor::override_visible_track_count ()
3800 _visible_track_count = -1;
3801 visible_tracks_selector.set_text ( _("*") );
3805 Editor::edit_controls_button_release (GdkEventButton* ev)
3807 if (Keyboard::is_context_menu_event (ev)) {
3808 ARDOUR_UI::instance()->add_route ();
3809 } else if (ev->button == 1) {
3810 selection->clear_tracks ();
3817 Editor::mouse_select_button_release (GdkEventButton* ev)
3819 /* this handles just right-clicks */
3821 if (ev->button != 3) {
3829 Editor::set_zoom_focus (ZoomFocus f)
3831 string str = zoom_focus_strings[(int)f];
3833 if (str != zoom_focus_selector.get_text()) {
3834 zoom_focus_selector.set_text (str);
3837 if (zoom_focus != f) {
3844 Editor::cycle_zoom_focus ()
3846 switch (zoom_focus) {
3848 set_zoom_focus (ZoomFocusRight);
3850 case ZoomFocusRight:
3851 set_zoom_focus (ZoomFocusCenter);
3853 case ZoomFocusCenter:
3854 set_zoom_focus (ZoomFocusPlayhead);
3856 case ZoomFocusPlayhead:
3857 set_zoom_focus (ZoomFocusMouse);
3859 case ZoomFocusMouse:
3860 set_zoom_focus (ZoomFocusEdit);
3863 set_zoom_focus (ZoomFocusLeft);
3869 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3871 /* recover or initialize pane positions. do this here rather than earlier because
3872 we don't want the positions to change the child allocations, which they seem to do.
3876 XMLProperty const * prop;
3878 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3887 XMLNode* geometry = find_named_node (*node, "geometry");
3889 if (which == static_cast<Paned*> (&edit_pane)) {
3891 if (done & Horizontal) {
3895 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3896 _notebook_shrunk = string_is_affirmative (prop->value ());
3899 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3900 /* initial allocation is 90% to canvas, 10% to notebook */
3901 pos = (int) floor (alloc.get_width() * 0.90f);
3902 snprintf (buf, sizeof(buf), "%d", pos);
3904 pos = atoi (prop->value());
3907 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3908 edit_pane.set_position (pos);
3911 done = (Pane) (done | Horizontal);
3913 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3915 if (done & Vertical) {
3919 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3920 /* initial allocation is 90% to canvas, 10% to summary */
3921 pos = (int) floor (alloc.get_height() * 0.90f);
3922 snprintf (buf, sizeof(buf), "%d", pos);
3925 pos = atoi (prop->value());
3928 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3929 editor_summary_pane.set_position (pos);
3932 done = (Pane) (done | Vertical);
3937 Editor::set_show_measures (bool yn)
3939 if (_show_measures != yn) {
3942 if ((_show_measures = yn) == true) {
3944 tempo_lines->show();
3947 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3948 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3950 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3951 draw_measures (begin, end);
3959 Editor::toggle_follow_playhead ()
3961 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3963 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3964 set_follow_playhead (tact->get_active());
3968 /** @param yn true to follow playhead, otherwise false.
3969 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3972 Editor::set_follow_playhead (bool yn, bool catch_up)
3974 if (_follow_playhead != yn) {
3975 if ((_follow_playhead = yn) == true && catch_up) {
3977 reset_x_origin_to_follow_playhead ();
3984 Editor::toggle_stationary_playhead ()
3986 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3988 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3989 set_stationary_playhead (tact->get_active());
3994 Editor::set_stationary_playhead (bool yn)
3996 if (_stationary_playhead != yn) {
3997 if ((_stationary_playhead = yn) == true) {
3999 // FIXME need a 3.0 equivalent of this 2.X call
4000 // update_current_screen ();
4007 Editor::playlist_selector () const
4009 return *_playlist_selector;
4013 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4015 if (paste_count == 0) {
4016 /* don't bother calculating an offset that will be zero anyway */
4020 /* calculate basic unsnapped multi-paste offset */
4021 framecnt_t offset = paste_count * duration;
4023 /* snap offset so pos + offset is aligned to the grid */
4024 framepos_t offset_pos = pos + offset;
4025 snap_to(offset_pos, RoundUpMaybe);
4026 offset = offset_pos - pos;
4032 Editor::get_grid_beat_divisions(framepos_t position)
4034 switch (_snap_type) {
4035 case SnapToBeatDiv128: return 128;
4036 case SnapToBeatDiv64: return 64;
4037 case SnapToBeatDiv32: return 32;
4038 case SnapToBeatDiv28: return 28;
4039 case SnapToBeatDiv24: return 24;
4040 case SnapToBeatDiv20: return 20;
4041 case SnapToBeatDiv16: return 16;
4042 case SnapToBeatDiv14: return 14;
4043 case SnapToBeatDiv12: return 12;
4044 case SnapToBeatDiv10: return 10;
4045 case SnapToBeatDiv8: return 8;
4046 case SnapToBeatDiv7: return 7;
4047 case SnapToBeatDiv6: return 6;
4048 case SnapToBeatDiv5: return 5;
4049 case SnapToBeatDiv4: return 4;
4050 case SnapToBeatDiv3: return 3;
4051 case SnapToBeatDiv2: return 2;
4058 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4062 const unsigned divisions = get_grid_beat_divisions(position);
4064 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4067 switch (_snap_type) {
4069 return Evoral::Beats(1.0);
4072 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4080 return Evoral::Beats();
4084 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4088 ret = nudge_clock->current_duration (pos);
4089 next = ret + 1; /* XXXX fix me */
4095 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4097 ArdourDialog dialog (_("Playlist Deletion"));
4098 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4099 "If it is kept, its audio files will not be cleaned.\n"
4100 "If it is deleted, audio files used by it alone will be cleaned."),
4103 dialog.set_position (WIN_POS_CENTER);
4104 dialog.get_vbox()->pack_start (label);
4108 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4109 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4110 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4111 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4112 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4114 // by default gtk uses the left most button
4115 keep->grab_focus ();
4117 switch (dialog.run ()) {
4119 /* keep this and all remaining ones */
4124 /* delete this and all others */
4128 case RESPONSE_ACCEPT:
4129 /* delete the playlist */
4133 case RESPONSE_REJECT:
4134 /* keep the playlist */
4146 Editor::audio_region_selection_covers (framepos_t where)
4148 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4149 if ((*a)->region()->covers (where)) {
4158 Editor::prepare_for_cleanup ()
4160 cut_buffer->clear_regions ();
4161 cut_buffer->clear_playlists ();
4163 selection->clear_regions ();
4164 selection->clear_playlists ();
4166 _regions->suspend_redisplay ();
4170 Editor::finish_cleanup ()
4172 _regions->resume_redisplay ();
4176 Editor::transport_loop_location()
4179 return _session->locations()->auto_loop_location();
4186 Editor::transport_punch_location()
4189 return _session->locations()->auto_punch_location();
4196 Editor::control_layout_scroll (GdkEventScroll* ev)
4198 /* Just forward to the normal canvas scroll method. The coordinate
4199 systems are different but since the canvas is always larger than the
4200 track headers, and aligned with the trackview area, this will work.
4202 In the not too distant future this layout is going away anyway and
4203 headers will be on the canvas.
4205 return canvas_scroll_event (ev, false);
4209 Editor::session_state_saved (string)
4212 _snapshots->redisplay ();
4216 Editor::maximise_editing_space ()
4222 Gtk::Window* toplevel = current_toplevel();
4225 toplevel->fullscreen ();
4231 Editor::restore_editing_space ()
4237 Gtk::Window* toplevel = current_toplevel();
4240 toplevel->unfullscreen();
4246 * Make new playlists for a given track and also any others that belong
4247 * to the same active route group with the `select' property.
4252 Editor::new_playlists (TimeAxisView* v)
4254 begin_reversible_command (_("new playlists"));
4255 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4256 _session->playlists->get (playlists);
4257 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4258 commit_reversible_command ();
4262 * Use a copy of the current playlist for a given track and also any others that belong
4263 * to the same active route group with the `select' property.
4268 Editor::copy_playlists (TimeAxisView* v)
4270 begin_reversible_command (_("copy playlists"));
4271 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4272 _session->playlists->get (playlists);
4273 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4274 commit_reversible_command ();
4277 /** Clear the current playlist for a given track and also any others that belong
4278 * to the same active route group with the `select' property.
4283 Editor::clear_playlists (TimeAxisView* v)
4285 begin_reversible_command (_("clear playlists"));
4286 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4287 _session->playlists->get (playlists);
4288 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4289 commit_reversible_command ();
4293 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4295 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4299 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4301 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4305 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4307 atv.clear_playlist ();
4311 Editor::get_y_origin () const
4313 return vertical_adjustment.get_value ();
4316 /** Queue up a change to the viewport x origin.
4317 * @param frame New x origin.
4320 Editor::reset_x_origin (framepos_t frame)
4322 pending_visual_change.add (VisualChange::TimeOrigin);
4323 pending_visual_change.time_origin = frame;
4324 ensure_visual_change_idle_handler ();
4328 Editor::reset_y_origin (double y)
4330 pending_visual_change.add (VisualChange::YOrigin);
4331 pending_visual_change.y_origin = y;
4332 ensure_visual_change_idle_handler ();
4336 Editor::reset_zoom (framecnt_t spp)
4338 if (spp == samples_per_pixel) {
4342 pending_visual_change.add (VisualChange::ZoomLevel);
4343 pending_visual_change.samples_per_pixel = spp;
4344 ensure_visual_change_idle_handler ();
4348 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4350 reset_x_origin (frame);
4353 if (!no_save_visual) {
4354 undo_visual_stack.push_back (current_visual_state(false));
4358 Editor::VisualState::VisualState (bool with_tracks)
4359 : gui_state (with_tracks ? new GUIObjectState : 0)
4363 Editor::VisualState::~VisualState ()
4368 Editor::VisualState*
4369 Editor::current_visual_state (bool with_tracks)
4371 VisualState* vs = new VisualState (with_tracks);
4372 vs->y_position = vertical_adjustment.get_value();
4373 vs->samples_per_pixel = samples_per_pixel;
4374 vs->leftmost_frame = leftmost_frame;
4375 vs->zoom_focus = zoom_focus;
4378 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4385 Editor::undo_visual_state ()
4387 if (undo_visual_stack.empty()) {
4391 VisualState* vs = undo_visual_stack.back();
4392 undo_visual_stack.pop_back();
4395 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4398 use_visual_state (*vs);
4403 Editor::redo_visual_state ()
4405 if (redo_visual_stack.empty()) {
4409 VisualState* vs = redo_visual_stack.back();
4410 redo_visual_stack.pop_back();
4412 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4413 // why do we check here?
4414 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4417 use_visual_state (*vs);
4422 Editor::swap_visual_state ()
4424 if (undo_visual_stack.empty()) {
4425 redo_visual_state ();
4427 undo_visual_state ();
4432 Editor::use_visual_state (VisualState& vs)
4434 PBD::Unwinder<bool> nsv (no_save_visual, true);
4435 DisplaySuspender ds;
4437 vertical_adjustment.set_value (vs.y_position);
4439 set_zoom_focus (vs.zoom_focus);
4440 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4443 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4445 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4446 (*i)->clear_property_cache();
4447 (*i)->reset_visual_state ();
4451 _routes->update_visibility ();
4454 /** This is the core function that controls the zoom level of the canvas. It is called
4455 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4456 * @param spp new number of samples per pixel
4459 Editor::set_samples_per_pixel (framecnt_t spp)
4465 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4466 const framecnt_t lots_of_pixels = 4000;
4468 /* if the zoom level is greater than what you'd get trying to display 3
4469 * days of audio on a really big screen, then it's too big.
4472 if (spp * lots_of_pixels > three_days) {
4476 samples_per_pixel = spp;
4479 tempo_lines->tempo_map_changed();
4482 bool const showing_time_selection = selection->time.length() > 0;
4484 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4485 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4486 (*i)->reshow_selection (selection->time);
4490 ZoomChanged (); /* EMIT_SIGNAL */
4492 ArdourCanvas::GtkCanvasViewport* c;
4494 c = get_track_canvas();
4496 c->canvas()->zoomed ();
4499 if (playhead_cursor) {
4500 playhead_cursor->set_position (playhead_cursor->current_frame ());
4503 refresh_location_display();
4504 _summary->set_overlays_dirty ();
4506 update_marker_labels ();
4512 Editor::queue_visual_videotimeline_update ()
4515 * pending_visual_change.add (VisualChange::VideoTimeline);
4516 * or maybe even more specific: which videotimeline-image
4517 * currently it calls update_video_timeline() to update
4518 * _all outdated_ images on the video-timeline.
4519 * see 'exposeimg()' in video_image_frame.cc
4521 ensure_visual_change_idle_handler ();
4525 Editor::ensure_visual_change_idle_handler ()
4527 if (pending_visual_change.idle_handler_id < 0) {
4528 // see comment in add_to_idle_resize above.
4529 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4530 pending_visual_change.being_handled = false;
4535 Editor::_idle_visual_changer (void* arg)
4537 return static_cast<Editor*>(arg)->idle_visual_changer ();
4541 Editor::idle_visual_changer ()
4543 /* set_horizontal_position() below (and maybe other calls) call
4544 gtk_main_iteration(), so it's possible that a signal will be handled
4545 half-way through this method. If this signal wants an
4546 idle_visual_changer we must schedule another one after this one, so
4547 mark the idle_handler_id as -1 here to allow that. Also make a note
4548 that we are doing the visual change, so that changes in response to
4549 super-rapid-screen-update can be dropped if we are still processing
4553 pending_visual_change.idle_handler_id = -1;
4554 pending_visual_change.being_handled = true;
4556 VisualChange vc = pending_visual_change;
4558 pending_visual_change.pending = (VisualChange::Type) 0;
4560 visual_changer (vc);
4562 pending_visual_change.being_handled = false;
4564 return 0; /* this is always a one-shot call */
4568 Editor::visual_changer (const VisualChange& vc)
4570 double const last_time_origin = horizontal_position ();
4572 if (vc.pending & VisualChange::ZoomLevel) {
4573 set_samples_per_pixel (vc.samples_per_pixel);
4575 compute_fixed_ruler_scale ();
4577 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4578 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4580 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4581 current_bbt_points_begin, current_bbt_points_end);
4582 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4583 current_bbt_points_begin, current_bbt_points_end);
4584 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4586 update_video_timeline();
4589 if (vc.pending & VisualChange::TimeOrigin) {
4590 set_horizontal_position (vc.time_origin / samples_per_pixel);
4593 if (vc.pending & VisualChange::YOrigin) {
4594 vertical_adjustment.set_value (vc.y_origin);
4597 if (last_time_origin == horizontal_position ()) {
4598 /* changed signal not emitted */
4599 update_fixed_rulers ();
4600 redisplay_tempo (true);
4603 if (!(vc.pending & VisualChange::ZoomLevel)) {
4604 update_video_timeline();
4607 _summary->set_overlays_dirty ();
4610 struct EditorOrderTimeAxisSorter {
4611 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4612 return a->order () < b->order ();
4617 Editor::sort_track_selection (TrackViewList& sel)
4619 EditorOrderTimeAxisSorter cmp;
4624 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4627 framepos_t where = 0;
4628 EditPoint ep = _edit_point;
4630 if (Profile->get_mixbus())
4631 if (ep == EditAtSelectedMarker)
4632 ep = EditAtPlayhead;
4634 if (from_outside_canvas && (ep == EditAtMouse)) {
4635 ep = EditAtPlayhead;
4636 } else if (from_context_menu && (ep == EditAtMouse)) {
4637 return canvas_event_sample (&context_click_event, 0, 0);
4640 if (entered_marker) {
4641 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4642 return entered_marker->position();
4645 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4646 ep = EditAtSelectedMarker;
4649 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4650 ep = EditAtPlayhead;
4654 case EditAtPlayhead:
4655 if (_dragging_playhead) {
4656 where = *_control_scroll_target;
4658 where = _session->audible_frame();
4660 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4663 case EditAtSelectedMarker:
4664 if (!selection->markers.empty()) {
4666 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4669 where = loc->start();
4673 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4681 if (!mouse_frame (where, ignored)) {
4682 /* XXX not right but what can we do ? */
4686 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4694 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4696 if (!_session) return;
4698 begin_reversible_command (cmd);
4702 if ((tll = transport_loop_location()) == 0) {
4703 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4704 XMLNode &before = _session->locations()->get_state();
4705 _session->locations()->add (loc, true);
4706 _session->set_auto_loop_location (loc);
4707 XMLNode &after = _session->locations()->get_state();
4708 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4710 XMLNode &before = tll->get_state();
4711 tll->set_hidden (false, this);
4712 tll->set (start, end);
4713 XMLNode &after = tll->get_state();
4714 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4717 commit_reversible_command ();
4721 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4723 if (!_session) return;
4725 begin_reversible_command (cmd);
4729 if ((tpl = transport_punch_location()) == 0) {
4730 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4731 XMLNode &before = _session->locations()->get_state();
4732 _session->locations()->add (loc, true);
4733 _session->set_auto_punch_location (loc);
4734 XMLNode &after = _session->locations()->get_state();
4735 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4737 XMLNode &before = tpl->get_state();
4738 tpl->set_hidden (false, this);
4739 tpl->set (start, end);
4740 XMLNode &after = tpl->get_state();
4741 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4744 commit_reversible_command ();
4747 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4748 * @param rs List to which found regions are added.
4749 * @param where Time to look at.
4750 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4753 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4755 const TrackViewList* tracks;
4758 tracks = &track_views;
4763 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4765 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4768 boost::shared_ptr<Track> tr;
4769 boost::shared_ptr<Playlist> pl;
4771 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4773 boost::shared_ptr<RegionList> regions = pl->regions_at (
4774 (framepos_t) floor ( (double) where * tr->speed()));
4776 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4777 RegionView* rv = rtv->view()->find_view (*i);
4788 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4790 const TrackViewList* tracks;
4793 tracks = &track_views;
4798 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4799 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4801 boost::shared_ptr<Track> tr;
4802 boost::shared_ptr<Playlist> pl;
4804 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4806 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4807 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4809 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4811 RegionView* rv = rtv->view()->find_view (*i);
4822 /** Get regions using the following method:
4824 * Make a region list using:
4825 * (a) any selected regions
4826 * (b) the intersection of any selected tracks and the edit point(*)
4827 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4829 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4831 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4835 Editor::get_regions_from_selection_and_edit_point ()
4837 RegionSelection regions;
4839 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4840 regions.add (entered_regionview);
4842 regions = selection->regions;
4845 if ( regions.empty() ) {
4846 TrackViewList tracks = selection->tracks;
4848 if (!tracks.empty()) {
4849 /* no region selected or entered, but some selected tracks:
4850 * act on all regions on the selected tracks at the edit point
4852 framepos_t const where = get_preferred_edit_position ();
4853 get_regions_at(regions, where, tracks);
4860 /** Get regions using the following method:
4862 * Make a region list using:
4863 * (a) any selected regions
4864 * (b) the intersection of any selected tracks and the edit point(*)
4865 * (c) if neither exists, then whatever region is under the mouse
4867 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4869 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4872 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4874 RegionSelection regions;
4876 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4877 regions.add (entered_regionview);
4879 regions = selection->regions;
4882 if ( regions.empty() ) {
4883 TrackViewList tracks = selection->tracks;
4885 if (!tracks.empty()) {
4886 /* no region selected or entered, but some selected tracks:
4887 * act on all regions on the selected tracks at the edit point
4889 get_regions_at(regions, pos, tracks);
4896 /** Start with regions that are selected, or the entered regionview if none are selected.
4897 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4898 * of the regions that we started with.
4902 Editor::get_regions_from_selection_and_entered () const
4904 RegionSelection regions = selection->regions;
4906 if (regions.empty() && entered_regionview) {
4907 regions.add (entered_regionview);
4914 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4916 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4917 RouteTimeAxisView* rtav;
4919 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4920 boost::shared_ptr<Playlist> pl;
4921 std::vector<boost::shared_ptr<Region> > results;
4922 boost::shared_ptr<Track> tr;
4924 if ((tr = rtav->track()) == 0) {
4929 if ((pl = (tr->playlist())) != 0) {
4930 boost::shared_ptr<Region> r = pl->region_by_id (id);
4932 RegionView* rv = rtav->view()->find_view (r);
4934 regions.push_back (rv);
4943 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4946 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4947 MidiTimeAxisView* mtav;
4949 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4951 mtav->get_per_region_note_selection (selection);
4958 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4960 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4962 RouteTimeAxisView* tatv;
4964 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4966 boost::shared_ptr<Playlist> pl;
4967 vector<boost::shared_ptr<Region> > results;
4969 boost::shared_ptr<Track> tr;
4971 if ((tr = tatv->track()) == 0) {
4976 if ((pl = (tr->playlist())) != 0) {
4977 if (src_comparison) {
4978 pl->get_source_equivalent_regions (region, results);
4980 pl->get_region_list_equivalent_regions (region, results);
4984 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4985 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4986 regions.push_back (marv);
4995 Editor::show_rhythm_ferret ()
4997 if (rhythm_ferret == 0) {
4998 rhythm_ferret = new RhythmFerret(*this);
5001 rhythm_ferret->set_session (_session);
5002 rhythm_ferret->show ();
5003 rhythm_ferret->present ();
5007 Editor::first_idle ()
5009 MessageDialog* dialog = 0;
5011 if (track_views.size() > 1) {
5012 Timers::TimerSuspender t;
5013 dialog = new MessageDialog (
5014 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5018 ARDOUR_UI::instance()->flush_pending ();
5021 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5025 // first idle adds route children (automation tracks), so we need to redisplay here
5026 _routes->redisplay ();
5030 if (_session->undo_depth() == 0) {
5031 undo_action->set_sensitive(false);
5033 redo_action->set_sensitive(false);
5034 begin_selection_op_history ();
5040 Editor::_idle_resize (gpointer arg)
5042 return ((Editor*)arg)->idle_resize ();
5046 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5048 if (resize_idle_id < 0) {
5049 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5050 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5051 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5053 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5054 _pending_resize_amount = 0;
5057 /* make a note of the smallest resulting height, so that we can clamp the
5058 lower limit at TimeAxisView::hSmall */
5060 int32_t min_resulting = INT32_MAX;
5062 _pending_resize_amount += h;
5063 _pending_resize_view = view;
5065 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5067 if (selection->tracks.contains (_pending_resize_view)) {
5068 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5069 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5073 if (min_resulting < 0) {
5078 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5079 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5083 /** Handle pending resizing of tracks */
5085 Editor::idle_resize ()
5087 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5089 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5090 selection->tracks.contains (_pending_resize_view)) {
5092 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5093 if (*i != _pending_resize_view) {
5094 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5099 _pending_resize_amount = 0;
5100 _group_tabs->set_dirty ();
5101 resize_idle_id = -1;
5109 ENSURE_GUI_THREAD (*this, &Editor::located);
5112 playhead_cursor->set_position (_session->audible_frame ());
5113 if (_follow_playhead && !_pending_initial_locate) {
5114 reset_x_origin_to_follow_playhead ();
5118 _pending_locate_request = false;
5119 _pending_initial_locate = false;
5123 Editor::region_view_added (RegionView * rv)
5125 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5126 if (rv->region ()->id () == (*pr)) {
5127 selection->add (rv);
5128 selection->regions.pending.erase (pr);
5133 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5135 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5136 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5137 if (rv->region()->id () == (*rnote).first) {
5138 mrv->select_notes ((*rnote).second);
5139 selection->pending_midi_note_selection.erase(rnote);
5145 _summary->set_background_dirty ();
5149 Editor::region_view_removed ()
5151 _summary->set_background_dirty ();
5155 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5157 TrackViewList::const_iterator j = track_views.begin ();
5158 while (j != track_views.end()) {
5159 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5160 if (rtv && rtv->route() == r) {
5171 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5175 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5176 TimeAxisView* tv = axis_view_from_route (*i);
5186 Editor::suspend_route_redisplay ()
5189 _routes->suspend_redisplay();
5194 Editor::resume_route_redisplay ()
5197 _routes->redisplay(); // queue redisplay
5198 _routes->resume_redisplay();
5203 Editor::add_routes (RouteList& routes)
5205 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5207 RouteTimeAxisView *rtv;
5208 list<RouteTimeAxisView*> new_views;
5209 TrackViewList new_selection;
5210 bool from_scratch = (track_views.size() == 0);
5212 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5213 boost::shared_ptr<Route> route = (*x);
5215 if (route->is_auditioner() || route->is_monitor()) {
5219 DataType dt = route->input()->default_type();
5221 if (dt == ARDOUR::DataType::AUDIO) {
5222 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5223 rtv->set_route (route);
5224 } else if (dt == ARDOUR::DataType::MIDI) {
5225 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5226 rtv->set_route (route);
5228 throw unknown_type();
5231 new_views.push_back (rtv);
5232 track_views.push_back (rtv);
5233 new_selection.push_back (rtv);
5235 rtv->effective_gain_display ();
5237 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5238 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5241 if (new_views.size() > 0) {
5242 _routes->routes_added (new_views);
5243 _summary->routes_added (new_views);
5246 if (!from_scratch) {
5247 selection->tracks.clear();
5248 selection->add (new_selection);
5249 begin_selection_op_history();
5252 if (show_editor_mixer_when_tracks_arrive) {
5253 show_editor_mixer (true);
5256 editor_list_button.set_sensitive (true);
5260 Editor::timeaxisview_deleted (TimeAxisView *tv)
5262 if (tv == entered_track) {
5266 if (_session && _session->deletion_in_progress()) {
5267 /* the situation is under control */
5271 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5273 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5275 _routes->route_removed (tv);
5277 TimeAxisView::Children c = tv->get_child_list ();
5278 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5279 if (entered_track == i->get()) {
5284 /* remove it from the list of track views */
5286 TrackViewList::iterator i;
5288 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5289 i = track_views.erase (i);
5292 /* update whatever the current mixer strip is displaying, if revelant */
5294 boost::shared_ptr<Route> route;
5297 route = rtav->route ();
5300 if (current_mixer_strip && current_mixer_strip->route() == route) {
5302 TimeAxisView* next_tv;
5304 if (track_views.empty()) {
5306 } else if (i == track_views.end()) {
5307 next_tv = track_views.front();
5314 set_selected_mixer_strip (*next_tv);
5316 /* make the editor mixer strip go away setting the
5317 * button to inactive (which also unticks the menu option)
5320 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5326 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5328 if (apply_to_selection) {
5329 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5331 TrackSelection::iterator j = i;
5334 hide_track_in_display (*i, false);
5339 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5341 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5342 // this will hide the mixer strip
5343 set_selected_mixer_strip (*tv);
5346 _routes->hide_track_in_display (*tv);
5351 Editor::sync_track_view_list_and_routes ()
5353 track_views = TrackViewList (_routes->views ());
5355 _summary->set_background_dirty();
5356 _group_tabs->set_dirty ();
5358 return false; // do not call again (until needed)
5362 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5364 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5369 /** Find a RouteTimeAxisView by the ID of its route */
5371 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5373 RouteTimeAxisView* v;
5375 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5376 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5377 if(v->route()->id() == id) {
5387 Editor::fit_route_group (RouteGroup *g)
5389 TrackViewList ts = axis_views_from_routes (g->route_list ());
5394 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5396 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5399 _session->cancel_audition ();
5403 if (_session->is_auditioning()) {
5404 _session->cancel_audition ();
5405 if (r == last_audition_region) {
5410 _session->audition_region (r);
5411 last_audition_region = r;
5416 Editor::hide_a_region (boost::shared_ptr<Region> r)
5418 r->set_hidden (true);
5422 Editor::show_a_region (boost::shared_ptr<Region> r)
5424 r->set_hidden (false);
5428 Editor::audition_region_from_region_list ()
5430 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5434 Editor::hide_region_from_region_list ()
5436 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5440 Editor::show_region_in_region_list ()
5442 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5446 Editor::step_edit_status_change (bool yn)
5449 start_step_editing ();
5451 stop_step_editing ();
5456 Editor::start_step_editing ()
5458 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5462 Editor::stop_step_editing ()
5464 step_edit_connection.disconnect ();
5468 Editor::check_step_edit ()
5470 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5471 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5473 mtv->check_step_edit ();
5477 return true; // do it again, till we stop
5481 Editor::scroll_press (Direction dir)
5483 ++_scroll_callbacks;
5485 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5486 /* delay the first auto-repeat */
5492 scroll_backward (1);
5500 scroll_up_one_track ();
5504 scroll_down_one_track ();
5508 /* do hacky auto-repeat */
5509 if (!_scroll_connection.connected ()) {
5511 _scroll_connection = Glib::signal_timeout().connect (
5512 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5515 _scroll_callbacks = 0;
5522 Editor::scroll_release ()
5524 _scroll_connection.disconnect ();
5527 /** Queue a change for the Editor viewport x origin to follow the playhead */
5529 Editor::reset_x_origin_to_follow_playhead ()
5531 framepos_t const frame = playhead_cursor->current_frame ();
5533 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5535 if (_session->transport_speed() < 0) {
5537 if (frame > (current_page_samples() / 2)) {
5538 center_screen (frame-(current_page_samples()/2));
5540 center_screen (current_page_samples()/2);
5547 if (frame < leftmost_frame) {
5549 if (_session->transport_rolling()) {
5550 /* rolling; end up with the playhead at the right of the page */
5551 l = frame - current_page_samples ();
5553 /* not rolling: end up with the playhead 1/4 of the way along the page */
5554 l = frame - current_page_samples() / 4;
5558 if (_session->transport_rolling()) {
5559 /* rolling: end up with the playhead on the left of the page */
5562 /* not rolling: end up with the playhead 3/4 of the way along the page */
5563 l = frame - 3 * current_page_samples() / 4;
5571 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5577 Editor::super_rapid_screen_update ()
5579 if (!_session || !_session->engine().running()) {
5583 /* METERING / MIXER STRIPS */
5585 /* update track meters, if required */
5586 if (contents().is_mapped() && meters_running) {
5587 RouteTimeAxisView* rtv;
5588 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5589 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5590 rtv->fast_update ();
5595 /* and any current mixer strip */
5596 if (current_mixer_strip) {
5597 current_mixer_strip->fast_update ();
5600 /* PLAYHEAD AND VIEWPORT */
5602 framepos_t const frame = _session->audible_frame();
5604 /* There are a few reasons why we might not update the playhead / viewport stuff:
5606 * 1. we don't update things when there's a pending locate request, otherwise
5607 * when the editor requests a locate there is a chance that this method
5608 * will move the playhead before the locate request is processed, causing
5610 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5611 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5614 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5616 last_update_frame = frame;
5618 if (!_dragging_playhead) {
5619 playhead_cursor->set_position (frame);
5622 if (!_stationary_playhead) {
5624 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5625 /* We only do this if we aren't already
5626 handling a visual change (ie if
5627 pending_visual_change.being_handled is
5628 false) so that these requests don't stack
5629 up there are too many of them to handle in
5632 reset_x_origin_to_follow_playhead ();
5637 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5638 framepos_t const frame = playhead_cursor->current_frame ();
5639 double target = ((double)frame - (double)current_page_samples()/2.0);
5640 if (target <= 0.0) {
5643 // compare to EditorCursor::set_position()
5644 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5645 double const new_pos = sample_to_pixel_unrounded (target);
5646 if (rint (new_pos) != rint (old_pos)) {
5647 reset_x_origin (pixel_to_sample (floor (new_pos)));
5658 Editor::session_going_away ()
5660 _have_idled = false;
5662 _session_connections.drop_connections ();
5664 super_rapid_screen_update_connection.disconnect ();
5666 selection->clear ();
5667 cut_buffer->clear ();
5669 clicked_regionview = 0;
5670 clicked_axisview = 0;
5671 clicked_routeview = 0;
5672 entered_regionview = 0;
5674 last_update_frame = 0;
5677 playhead_cursor->hide ();
5679 /* rip everything out of the list displays */
5683 _route_groups->clear ();
5685 /* do this first so that deleting a track doesn't reset cms to null
5686 and thus cause a leak.
5689 if (current_mixer_strip) {
5690 if (current_mixer_strip->get_parent() != 0) {
5691 global_hpacker.remove (*current_mixer_strip);
5693 delete current_mixer_strip;
5694 current_mixer_strip = 0;
5697 /* delete all trackviews */
5699 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5702 track_views.clear ();
5704 nudge_clock->set_session (0);
5706 editor_list_button.set_active(false);
5707 editor_list_button.set_sensitive(false);
5709 /* clear tempo/meter rulers */
5710 remove_metric_marks ();
5712 clear_marker_display ();
5714 stop_step_editing ();
5718 /* get rid of any existing editor mixer strip */
5720 WindowTitle title(Glib::get_application_name());
5721 title += _("Editor");
5723 own_window()->set_title (title.get_string());
5726 SessionHandlePtr::session_going_away ();
5730 Editor::manage_action_scripts ()
5732 ARDOUR_UI::instance()->lua_script_manager();
5736 Editor::trigger_script (int i)
5738 LuaInstance::instance()-> call_action (i);
5742 Editor::set_script_action_name (int i, const std::string& n)
5744 string const a = string_compose (X_("script-action-%1"), i + 1);
5745 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5748 act->set_label (string_compose (_("Unset #%1"), i + 1));
5749 act->set_tooltip (_("(no action bound"));
5750 act->set_sensitive (false);
5753 act->set_tooltip (n);
5754 act->set_sensitive (true);
5756 KeyEditor::UpdateBindings ();
5760 Editor::show_editor_list (bool yn)
5763 _the_notebook.show ();
5765 _the_notebook.hide ();
5770 Editor::change_region_layering_order (bool from_context_menu)
5772 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5774 if (!clicked_routeview) {
5775 if (layering_order_editor) {
5776 layering_order_editor->hide ();
5781 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5787 boost::shared_ptr<Playlist> pl = track->playlist();
5793 if (layering_order_editor == 0) {
5794 layering_order_editor = new RegionLayeringOrderEditor (*this);
5797 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5798 layering_order_editor->maybe_present ();
5802 Editor::update_region_layering_order_editor ()
5804 if (layering_order_editor && layering_order_editor->is_visible ()) {
5805 change_region_layering_order (true);
5810 Editor::setup_fade_images ()
5812 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5813 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5814 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5815 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5816 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5818 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5819 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5820 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5821 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5822 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5824 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5825 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5826 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5827 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5828 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5830 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5831 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5832 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5833 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5834 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5838 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5840 Editor::action_menu_item (std::string const & name)
5842 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5845 return *manage (a->create_menu_item ());
5849 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5851 EventBox* b = manage (new EventBox);
5852 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5853 Label* l = manage (new Label (name));
5857 _the_notebook.append_page (widget, *b);
5861 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5863 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5864 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5867 if (ev->type == GDK_2BUTTON_PRESS) {
5869 /* double-click on a notebook tab shrinks or expands the notebook */
5871 if (_notebook_shrunk) {
5872 if (pre_notebook_shrink_pane_width) {
5873 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5875 _notebook_shrunk = false;
5877 pre_notebook_shrink_pane_width = edit_pane.get_position();
5879 /* this expands the LHS of the edit pane to cover the notebook
5880 PAGE but leaves the tabs visible.
5882 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5883 _notebook_shrunk = true;
5891 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5893 using namespace Menu_Helpers;
5895 MenuList& items = _control_point_context_menu.items ();
5898 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5899 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5900 if (!can_remove_control_point (item)) {
5901 items.back().set_sensitive (false);
5904 _control_point_context_menu.popup (event->button.button, event->button.time);
5908 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5910 using namespace Menu_Helpers;
5912 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5917 /* We need to get the selection here and pass it to the operations, since
5918 popping up the menu will cause a region leave event which clears
5919 entered_regionview. */
5921 MidiRegionView& mrv = note->region_view();
5922 const RegionSelection rs = get_regions_from_selection_and_entered ();
5923 const uint32_t sel_size = mrv.selection_size ();
5925 MenuList& items = _note_context_menu.items();
5929 items.push_back(MenuElem(_("Delete"),
5930 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5933 items.push_back(MenuElem(_("Edit..."),
5934 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5935 if (sel_size != 1) {
5936 items.back().set_sensitive (false);
5939 items.push_back(MenuElem(_("Transpose..."),
5940 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5943 items.push_back(MenuElem(_("Legatize"),
5944 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5946 items.back().set_sensitive (false);
5949 items.push_back(MenuElem(_("Quantize..."),
5950 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5952 items.push_back(MenuElem(_("Remove Overlap"),
5953 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5955 items.back().set_sensitive (false);
5958 items.push_back(MenuElem(_("Transform..."),
5959 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5961 _note_context_menu.popup (event->button.button, event->button.time);
5965 Editor::zoom_vertical_modifier_released()
5967 _stepping_axis_view = 0;
5971 Editor::ui_parameter_changed (string parameter)
5973 if (parameter == "icon-set") {
5974 while (!_cursor_stack.empty()) {
5975 _cursor_stack.pop_back();
5977 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5978 _cursor_stack.push_back(_cursors->grabber);
5979 } else if (parameter == "draggable-playhead") {
5980 if (_verbose_cursor) {
5981 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5987 Editor::use_own_window (bool and_fill_it)
5989 bool new_window = !own_window();
5991 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5993 if (win && new_window) {
5994 win->set_name ("EditorWindow");
5996 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5998 // win->signal_realize().connect (*this, &Editor::on_realize);
5999 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
6000 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
6001 win->set_data ("ardour-bindings", bindings);
6006 DisplaySuspender ds;
6007 contents().show_all ();
6009 /* XXX: this is a bit unfortunate; it would probably
6010 be nicer if we could just call show () above rather
6011 than needing the show_all ()
6014 /* re-hide stuff if necessary */
6015 editor_list_button_toggled ();
6016 parameter_changed ("show-summary");
6017 parameter_changed ("show-group-tabs");
6018 parameter_changed ("show-zoom-tools");
6020 /* now reset all audio_time_axis heights, because widgets might need
6026 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6027 tv = (static_cast<TimeAxisView*>(*i));
6028 tv->reset_height ();
6031 if (current_mixer_strip) {
6032 current_mixer_strip->hide_things ();
6033 current_mixer_strip->parameter_changed ("mixer-element-visibility");