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 "luainstance.h"
113 #include "midi_region_view.h"
114 #include "midi_time_axis.h"
115 #include "mixer_strip.h"
116 #include "mixer_ui.h"
117 #include "mouse_cursors.h"
118 #include "note_base.h"
119 #include "playlist_selector.h"
120 #include "public_editor.h"
121 #include "quantize_dialog.h"
122 #include "region_layering_order_editor.h"
123 #include "rgb_macros.h"
124 #include "rhythm_ferret.h"
125 #include "selection.h"
126 #include "simple_progress_dialog.h"
128 #include "tempo_lines.h"
129 #include "time_axis_view.h"
131 #include "tooltips.h"
132 #include "ui_config.h"
134 #include "verbose_cursor.h"
139 using namespace ARDOUR;
140 using namespace ARDOUR_UI_UTILS;
143 using namespace Glib;
144 using namespace Gtkmm2ext;
145 using namespace Editing;
147 using PBD::internationalize;
149 using Gtkmm2ext::Keyboard;
151 double Editor::timebar_height = 15.0;
153 static const gchar *_snap_type_strings[] = {
187 static const gchar *_snap_mode_strings[] = {
194 static const gchar *_edit_point_strings[] = {
201 static const gchar *_edit_mode_strings[] = {
209 static const gchar *_zoom_focus_strings[] = {
219 #ifdef USE_RUBBERBAND
220 static const gchar *_rb_opt_strings[] = {
223 N_("Balanced multitimbral mixture"),
224 N_("Unpitched percussion with stable notes"),
225 N_("Crisp monophonic instrumental"),
226 N_("Unpitched solo percussion"),
227 N_("Resample without preserving pitch"),
232 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
235 pane_size_watcher (Paned* pane)
237 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
241 Quartz: impossible to access
243 so stop that by preventing it from ever getting too narrow. 35
244 pixels is basically a rough guess at the tab width.
249 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
251 gint pos = pane->get_position ();
253 if (pos > max_width_of_lhs) {
254 pane->set_position (max_width_of_lhs);
259 : PublicEditor (global_hpacker)
260 , editor_mixer_strip_width (Wide)
261 , constructed (false)
262 , _playlist_selector (0)
263 , no_save_visual (false)
265 , samples_per_pixel (2048)
266 , zoom_focus (ZoomFocusPlayhead)
267 , mouse_mode (MouseObject)
268 , pre_internal_snap_type (SnapToBeat)
269 , pre_internal_snap_mode (SnapOff)
270 , internal_snap_type (SnapToBeat)
271 , internal_snap_mode (SnapOff)
272 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
273 , _notebook_shrunk (false)
274 , location_marker_color (0)
275 , location_range_color (0)
276 , location_loop_color (0)
277 , location_punch_color (0)
278 , location_cd_marker_color (0)
280 , _show_marker_lines (false)
281 , clicked_axisview (0)
282 , clicked_routeview (0)
283 , clicked_regionview (0)
284 , clicked_selection (0)
285 , clicked_control_point (0)
286 , button_release_can_deselect (true)
287 , _mouse_changed_selection (false)
288 , region_edit_menu_split_item (0)
289 , region_edit_menu_split_multichannel_item (0)
290 , track_region_edit_playlist_menu (0)
291 , track_edit_playlist_submenu (0)
292 , track_selection_edit_playlist_submenu (0)
293 , _popup_region_menu_item (0)
295 , _track_canvas_viewport (0)
296 , within_track_canvas (false)
297 , _verbose_cursor (0)
301 , range_marker_group (0)
302 , transport_marker_group (0)
303 , cd_marker_group (0)
304 , _time_markers_group (0)
305 , hv_scroll_group (0)
307 , cursor_scroll_group (0)
308 , no_scroll_group (0)
309 , _trackview_group (0)
310 , _drag_motion_group (0)
311 , _canvas_drop_zone (0)
312 , no_ruler_shown_update (false)
313 , ruler_grabbed_widget (0)
315 , minsec_mark_interval (0)
316 , minsec_mark_modulo (0)
318 , timecode_mark_modulo (0)
319 , timecode_nmarks (0)
320 , _samples_ruler_interval (0)
323 , bbt_bar_helper_on (0)
324 , bbt_accent_modulo (0)
329 , visible_timebars (0)
330 , editor_ruler_menu (0)
334 , range_marker_bar (0)
335 , transport_marker_bar (0)
337 , minsec_label (_("Mins:Secs"))
338 , bbt_label (_("Bars:Beats"))
339 , timecode_label (_("Timecode"))
340 , samples_label (_("Samples"))
341 , tempo_label (_("Tempo"))
342 , meter_label (_("Meter"))
343 , mark_label (_("Location Markers"))
344 , range_mark_label (_("Range Markers"))
345 , transport_mark_label (_("Loop/Punch Ranges"))
346 , cd_mark_label (_("CD Markers"))
347 , videotl_label (_("Video Timeline"))
349 , playhead_cursor (0)
350 , edit_packer (4, 4, true)
351 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
352 , horizontal_adjustment (0.0, 0.0, 1e16)
353 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
354 , controls_layout (unused_adjustment, vertical_adjustment)
355 , _scroll_callbacks (0)
356 , _visible_canvas_width (0)
357 , _visible_canvas_height (0)
358 , _full_canvas_height (0)
359 , edit_controls_left_menu (0)
360 , edit_controls_right_menu (0)
361 , last_update_frame (0)
362 , cut_buffer_start (0)
363 , cut_buffer_length (0)
364 , button_bindings (0)
368 , current_interthread_info (0)
369 , analysis_window (0)
370 , select_new_marker (false)
372 , scrubbing_direction (0)
373 , scrub_reversals (0)
374 , scrub_reverse_distance (0)
375 , have_pending_keyboard_selection (false)
376 , pending_keyboard_selection_start (0)
377 , _snap_type (SnapToBeat)
378 , _snap_mode (SnapOff)
379 , snap_threshold (5.0)
380 , ignore_gui_changes (false)
381 , _drags (new DragManager (this))
383 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
384 , _dragging_playhead (false)
385 , _dragging_edit_point (false)
386 , _show_measures (true)
387 , _follow_playhead (true)
388 , _stationary_playhead (false)
391 , global_rect_group (0)
392 , time_line_group (0)
393 , tempo_or_meter_marker_menu (0)
395 , range_marker_menu (0)
396 , transport_marker_menu (0)
397 , new_transport_marker_menu (0)
399 , marker_menu_item (0)
400 , bbt_beat_subdivision (4)
401 , _visible_track_count (-1)
402 , toolbar_selection_clock_table (2,3)
403 , automation_mode_button (_("mode"))
404 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
405 , selection (new Selection (this))
406 , cut_buffer (new Selection (this))
407 , _selection_memento (new SelectionMemento())
408 , _all_region_actions_sensitized (false)
409 , _ignore_region_action (false)
410 , _last_region_menu_was_main (false)
411 , _ignore_follow_edits (false)
412 , cd_marker_bar_drag_rect (0)
413 , range_bar_drag_rect (0)
414 , transport_bar_drag_rect (0)
415 , transport_bar_range_rect (0)
416 , transport_bar_preroll_rect (0)
417 , transport_bar_postroll_rect (0)
418 , transport_loop_range_rect (0)
419 , transport_punch_range_rect (0)
420 , transport_punchin_line (0)
421 , transport_punchout_line (0)
422 , transport_preroll_rect (0)
423 , transport_postroll_rect (0)
425 , rubberband_rect (0)
431 , autoscroll_horizontal_allowed (false)
432 , autoscroll_vertical_allowed (false)
434 , autoscroll_widget (0)
435 , show_gain_after_trim (false)
436 , selection_op_cmd_depth (0)
437 , selection_op_history_it (0)
439 , current_mixer_strip (0)
440 , show_editor_mixer_when_tracks_arrive (false)
441 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
442 , current_stepping_trackview (0)
443 , last_track_height_step_timestamp (0)
445 , entered_regionview (0)
446 , clear_entered_track (false)
447 , _edit_point (EditAtMouse)
448 , meters_running (false)
450 , _have_idled (false)
451 , resize_idle_id (-1)
452 , _pending_resize_amount (0)
453 , _pending_resize_view (0)
454 , _pending_locate_request (false)
455 , _pending_initial_locate (false)
459 , layering_order_editor (0)
460 , _last_cut_copy_source_track (0)
461 , _region_selection_change_updates_region_list (true)
463 , _following_mixer_selection (false)
464 , _control_point_toggled_on_press (false)
465 , _stepping_axis_view (0)
466 , quantize_dialog (0)
467 , _main_menu_disabler (0)
468 , myactions (X_("editor"))
470 /* we are a singleton */
472 PublicEditor::_instance = this;
476 last_event_time.tv_sec = 0;
477 last_event_time.tv_usec = 0;
479 selection_op_history.clear();
482 snap_type_strings = I18N (_snap_type_strings);
483 snap_mode_strings = I18N (_snap_mode_strings);
484 zoom_focus_strings = I18N (_zoom_focus_strings);
485 edit_mode_strings = I18N (_edit_mode_strings);
486 edit_point_strings = I18N (_edit_point_strings);
487 #ifdef USE_RUBBERBAND
488 rb_opt_strings = I18N (_rb_opt_strings);
492 build_edit_mode_menu();
493 build_zoom_focus_menu();
494 build_track_count_menu();
495 build_snap_mode_menu();
496 build_snap_type_menu();
497 build_edit_point_menu();
499 location_marker_color = UIConfiguration::instance().color ("location marker");
500 location_range_color = UIConfiguration::instance().color ("location range");
501 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
502 location_loop_color = UIConfiguration::instance().color ("location loop");
503 location_punch_color = UIConfiguration::instance().color ("location punch");
505 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
507 TimeAxisView::setup_sizes ();
508 ArdourMarker::setup_sizes (timebar_height);
510 bbt_label.set_name ("EditorRulerLabel");
511 bbt_label.set_size_request (-1, (int)timebar_height);
512 bbt_label.set_alignment (1.0, 0.5);
513 bbt_label.set_padding (5,0);
515 bbt_label.set_no_show_all();
516 minsec_label.set_name ("EditorRulerLabel");
517 minsec_label.set_size_request (-1, (int)timebar_height);
518 minsec_label.set_alignment (1.0, 0.5);
519 minsec_label.set_padding (5,0);
520 minsec_label.hide ();
521 minsec_label.set_no_show_all();
522 timecode_label.set_name ("EditorRulerLabel");
523 timecode_label.set_size_request (-1, (int)timebar_height);
524 timecode_label.set_alignment (1.0, 0.5);
525 timecode_label.set_padding (5,0);
526 timecode_label.hide ();
527 timecode_label.set_no_show_all();
528 samples_label.set_name ("EditorRulerLabel");
529 samples_label.set_size_request (-1, (int)timebar_height);
530 samples_label.set_alignment (1.0, 0.5);
531 samples_label.set_padding (5,0);
532 samples_label.hide ();
533 samples_label.set_no_show_all();
535 tempo_label.set_name ("EditorRulerLabel");
536 tempo_label.set_size_request (-1, (int)timebar_height);
537 tempo_label.set_alignment (1.0, 0.5);
538 tempo_label.set_padding (5,0);
540 tempo_label.set_no_show_all();
542 meter_label.set_name ("EditorRulerLabel");
543 meter_label.set_size_request (-1, (int)timebar_height);
544 meter_label.set_alignment (1.0, 0.5);
545 meter_label.set_padding (5,0);
547 meter_label.set_no_show_all();
549 if (Profile->get_trx()) {
550 mark_label.set_text (_("Markers"));
552 mark_label.set_name ("EditorRulerLabel");
553 mark_label.set_size_request (-1, (int)timebar_height);
554 mark_label.set_alignment (1.0, 0.5);
555 mark_label.set_padding (5,0);
557 mark_label.set_no_show_all();
559 cd_mark_label.set_name ("EditorRulerLabel");
560 cd_mark_label.set_size_request (-1, (int)timebar_height);
561 cd_mark_label.set_alignment (1.0, 0.5);
562 cd_mark_label.set_padding (5,0);
563 cd_mark_label.hide();
564 cd_mark_label.set_no_show_all();
566 videotl_bar_height = 4;
567 videotl_label.set_name ("EditorRulerLabel");
568 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
569 videotl_label.set_alignment (1.0, 0.5);
570 videotl_label.set_padding (5,0);
571 videotl_label.hide();
572 videotl_label.set_no_show_all();
574 range_mark_label.set_name ("EditorRulerLabel");
575 range_mark_label.set_size_request (-1, (int)timebar_height);
576 range_mark_label.set_alignment (1.0, 0.5);
577 range_mark_label.set_padding (5,0);
578 range_mark_label.hide();
579 range_mark_label.set_no_show_all();
581 transport_mark_label.set_name ("EditorRulerLabel");
582 transport_mark_label.set_size_request (-1, (int)timebar_height);
583 transport_mark_label.set_alignment (1.0, 0.5);
584 transport_mark_label.set_padding (5,0);
585 transport_mark_label.hide();
586 transport_mark_label.set_no_show_all();
588 initialize_canvas ();
590 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
592 _summary = new EditorSummary (this);
594 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
595 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
597 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
599 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
600 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
602 edit_controls_vbox.set_spacing (0);
603 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
604 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
606 HBox* h = manage (new HBox);
607 _group_tabs = new EditorGroupTabs (this);
608 if (!ARDOUR::Profile->get_trx()) {
609 h->pack_start (*_group_tabs, PACK_SHRINK);
611 h->pack_start (edit_controls_vbox);
612 controls_layout.add (*h);
614 controls_layout.set_name ("EditControlsBase");
615 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
616 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
617 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
619 _cursors = new MouseCursors;
620 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
621 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
623 /* Push default cursor to ever-present bottom of cursor stack. */
624 push_canvas_cursor(_cursors->grabber);
626 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
628 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
629 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
630 pad_line_1->set_outline_color (0xFF0000FF);
636 edit_packer.set_col_spacings (0);
637 edit_packer.set_row_spacings (0);
638 edit_packer.set_homogeneous (false);
639 edit_packer.set_border_width (0);
640 edit_packer.set_name ("EditorWindow");
642 time_bars_event_box.add (time_bars_vbox);
643 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
644 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
646 /* labels for the time bars */
647 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
649 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
651 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
653 bottom_hbox.set_border_width (2);
654 bottom_hbox.set_spacing (3);
656 _route_groups = new EditorRouteGroups (this);
657 _routes = new EditorRoutes (this);
658 _regions = new EditorRegions (this);
659 _snapshots = new EditorSnapshots (this);
660 _locations = new EditorLocations (this);
662 /* these are static location signals */
664 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
665 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
666 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
668 add_notebook_page (_("Regions"), _regions->widget ());
669 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
670 add_notebook_page (_("Snapshots"), _snapshots->widget ());
671 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
672 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
674 _the_notebook.set_show_tabs (true);
675 _the_notebook.set_scrollable (true);
676 _the_notebook.popup_disable ();
677 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
678 _the_notebook.show_all ();
680 _notebook_shrunk = false;
682 editor_summary_pane.pack1(edit_packer);
684 Button* summary_arrows_left_left = manage (new Button);
685 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
686 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
687 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
689 Button* summary_arrows_left_right = manage (new Button);
690 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
691 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
692 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
694 VBox* summary_arrows_left = manage (new VBox);
695 summary_arrows_left->pack_start (*summary_arrows_left_left);
696 summary_arrows_left->pack_start (*summary_arrows_left_right);
698 Button* summary_arrows_right_up = manage (new Button);
699 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
700 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
701 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
703 Button* summary_arrows_right_down = manage (new Button);
704 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
705 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
706 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
708 VBox* summary_arrows_right = manage (new VBox);
709 summary_arrows_right->pack_start (*summary_arrows_right_up);
710 summary_arrows_right->pack_start (*summary_arrows_right_down);
712 Frame* summary_frame = manage (new Frame);
713 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
715 summary_frame->add (*_summary);
716 summary_frame->show ();
718 _summary_hbox.pack_start (*summary_arrows_left, false, false);
719 _summary_hbox.pack_start (*summary_frame, true, true);
720 _summary_hbox.pack_start (*summary_arrows_right, false, false);
722 if (!ARDOUR::Profile->get_trx()) {
723 editor_summary_pane.pack2 (_summary_hbox);
726 edit_pane.pack1 (editor_summary_pane, true, true);
727 if (!ARDOUR::Profile->get_trx()) {
728 edit_pane.pack2 (_the_notebook, false, true);
731 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
733 /* XXX: editor_summary_pane might need similar to the edit_pane */
735 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
737 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
738 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
740 top_hbox.pack_start (toolbar_frame);
742 HBox *hbox = manage (new HBox);
743 hbox->pack_start (edit_pane, true, true);
745 global_vpacker.pack_start (top_hbox, false, false);
746 global_vpacker.pack_start (*hbox, true, true);
747 global_hpacker.pack_start (global_vpacker, true, true);
749 /* need to show the "contents" widget so that notebook will show if tab is switched to
752 global_hpacker.show ();
754 /* register actions now so that set_state() can find them and set toggles/checks etc */
761 _playlist_selector = new PlaylistSelector();
762 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
764 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
768 nudge_forward_button.set_name ("nudge button");
769 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
771 nudge_backward_button.set_name ("nudge button");
772 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
774 fade_context_menu.set_name ("ArdourContextMenu");
776 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
778 /* allow external control surfaces/protocols to do various things */
780 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
781 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
782 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
783 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
784 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
785 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
786 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
787 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
788 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
789 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
790 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
791 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
792 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
793 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
795 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
796 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
797 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
798 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
799 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
801 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
803 /* problematic: has to return a value and thus cannot be x-thread */
805 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
807 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
808 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
810 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
812 _ignore_region_action = false;
813 _last_region_menu_was_main = false;
814 _popup_region_menu_item = 0;
816 _ignore_follow_edits = false;
818 _show_marker_lines = false;
820 /* Button bindings */
822 button_bindings = new Bindings ("editor-mouse");
824 XMLNode* node = button_settings();
826 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
827 button_bindings->load_operation (**i);
833 /* grab current parameter state */
834 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
835 UIConfiguration::instance().map_parameters (pc);
837 setup_fade_images ();
839 LuaInstance::instance(); // instantiate
840 LuaInstance::instance()->ActionChanged.connect (sigc::mem_fun (*this, &Editor::set_script_action_name));
847 delete button_bindings;
849 delete _route_groups;
850 delete _track_canvas_viewport;
853 delete quantize_dialog;
859 delete _playlist_selector;
861 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
867 Editor::button_settings () const
869 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
870 XMLNode* node = find_named_node (*settings, X_("Buttons"));
873 node = new XMLNode (X_("Buttons"));
880 Editor::get_smart_mode () const
882 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
886 Editor::catch_vanishing_regionview (RegionView *rv)
888 /* note: the selection will take care of the vanishing
889 audioregionview by itself.
892 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
896 if (clicked_regionview == rv) {
897 clicked_regionview = 0;
900 if (entered_regionview == rv) {
901 set_entered_regionview (0);
904 if (!_all_region_actions_sensitized) {
905 sensitize_all_region_actions (true);
910 Editor::set_entered_regionview (RegionView* rv)
912 if (rv == entered_regionview) {
916 if (entered_regionview) {
917 entered_regionview->exited ();
920 entered_regionview = rv;
922 if (entered_regionview != 0) {
923 entered_regionview->entered ();
926 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
927 /* This RegionView entry might have changed what region actions
928 are allowed, so sensitize them all in case a key is pressed.
930 sensitize_all_region_actions (true);
935 Editor::set_entered_track (TimeAxisView* tav)
938 entered_track->exited ();
944 entered_track->entered ();
949 Editor::instant_save ()
951 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
956 _session->add_instant_xml(get_state());
958 Config->add_instant_xml(get_state());
963 Editor::control_vertical_zoom_in_all ()
965 tav_zoom_smooth (false, true);
969 Editor::control_vertical_zoom_out_all ()
971 tav_zoom_smooth (true, true);
975 Editor::control_vertical_zoom_in_selected ()
977 tav_zoom_smooth (false, false);
981 Editor::control_vertical_zoom_out_selected ()
983 tav_zoom_smooth (true, false);
987 Editor::control_view (uint32_t view)
989 goto_visual_state (view);
993 Editor::control_unselect ()
995 selection->clear_tracks ();
999 Editor::control_select (uint32_t rid, Selection::Operation op)
1001 /* handles the (static) signal from the ControlProtocol class that
1002 * requests setting the selected track to a given RID
1009 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1015 TimeAxisView* tav = axis_view_from_route (r);
1019 case Selection::Add:
1020 selection->add (tav);
1022 case Selection::Toggle:
1023 selection->toggle (tav);
1025 case Selection::Extend:
1027 case Selection::Set:
1028 selection->set (tav);
1032 selection->clear_tracks ();
1037 Editor::control_step_tracks_up ()
1039 scroll_tracks_up_line ();
1043 Editor::control_step_tracks_down ()
1045 scroll_tracks_down_line ();
1049 Editor::control_scroll (float fraction)
1051 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1057 double step = fraction * current_page_samples();
1060 _control_scroll_target is an optional<T>
1062 it acts like a pointer to an framepos_t, with
1063 a operator conversion to boolean to check
1064 that it has a value could possibly use
1065 playhead_cursor->current_frame to store the
1066 value and a boolean in the class to know
1067 when it's out of date
1070 if (!_control_scroll_target) {
1071 _control_scroll_target = _session->transport_frame();
1072 _dragging_playhead = true;
1075 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1076 *_control_scroll_target = 0;
1077 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1078 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1080 *_control_scroll_target += (framepos_t) trunc (step);
1083 /* move visuals, we'll catch up with it later */
1085 playhead_cursor->set_position (*_control_scroll_target);
1086 UpdateAllTransportClocks (*_control_scroll_target);
1088 if (*_control_scroll_target > (current_page_samples() / 2)) {
1089 /* try to center PH in window */
1090 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1096 Now we do a timeout to actually bring the session to the right place
1097 according to the playhead. This is to avoid reading disk buffers on every
1098 call to control_scroll, which is driven by ScrollTimeline and therefore
1099 probably by a control surface wheel which can generate lots of events.
1101 /* cancel the existing timeout */
1103 control_scroll_connection.disconnect ();
1105 /* add the next timeout */
1107 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1111 Editor::deferred_control_scroll (framepos_t /*target*/)
1113 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1114 // reset for next stream
1115 _control_scroll_target = boost::none;
1116 _dragging_playhead = false;
1121 Editor::access_action (std::string action_group, std::string action_item)
1127 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1130 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1138 Editor::on_realize ()
1142 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1143 start_lock_event_timing ();
1148 Editor::start_lock_event_timing ()
1150 /* check if we should lock the GUI every 30 seconds */
1152 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1156 Editor::generic_event_handler (GdkEvent* ev)
1159 case GDK_BUTTON_PRESS:
1160 case GDK_BUTTON_RELEASE:
1161 case GDK_MOTION_NOTIFY:
1163 case GDK_KEY_RELEASE:
1164 if (contents().is_mapped()) {
1165 gettimeofday (&last_event_time, 0);
1169 case GDK_LEAVE_NOTIFY:
1170 switch (ev->crossing.detail) {
1171 case GDK_NOTIFY_UNKNOWN:
1172 case GDK_NOTIFY_INFERIOR:
1173 case GDK_NOTIFY_ANCESTOR:
1175 case GDK_NOTIFY_VIRTUAL:
1176 case GDK_NOTIFY_NONLINEAR:
1177 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1178 /* leaving window, so reset focus, thus ending any and
1179 all text entry operations.
1194 Editor::lock_timeout_callback ()
1196 struct timeval now, delta;
1198 gettimeofday (&now, 0);
1200 timersub (&now, &last_event_time, &delta);
1202 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1204 /* don't call again. Returning false will effectively
1205 disconnect us from the timer callback.
1207 unlock() will call start_lock_event_timing() to get things
1217 Editor::map_position_change (framepos_t frame)
1219 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1221 if (_session == 0) {
1225 if (_follow_playhead) {
1226 center_screen (frame);
1229 playhead_cursor->set_position (frame);
1233 Editor::center_screen (framepos_t frame)
1235 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1237 /* if we're off the page, then scroll.
1240 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1241 center_screen_internal (frame, page);
1246 Editor::center_screen_internal (framepos_t frame, float page)
1251 frame -= (framepos_t) page;
1256 reset_x_origin (frame);
1261 Editor::update_title ()
1263 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1265 if (!own_window()) {
1270 bool dirty = _session->dirty();
1272 string session_name;
1274 if (_session->snap_name() != _session->name()) {
1275 session_name = _session->snap_name();
1277 session_name = _session->name();
1281 session_name = "*" + session_name;
1284 WindowTitle title(session_name);
1285 title += S_("Window|Editor");
1286 title += Glib::get_application_name();
1287 own_window()->set_title (title.get_string());
1289 /* ::session_going_away() will have taken care of it */
1294 Editor::set_session (Session *t)
1296 SessionHandlePtr::set_session (t);
1302 _playlist_selector->set_session (_session);
1303 nudge_clock->set_session (_session);
1304 _summary->set_session (_session);
1305 _group_tabs->set_session (_session);
1306 _route_groups->set_session (_session);
1307 _regions->set_session (_session);
1308 _snapshots->set_session (_session);
1309 _routes->set_session (_session);
1310 _locations->set_session (_session);
1312 if (rhythm_ferret) {
1313 rhythm_ferret->set_session (_session);
1316 if (analysis_window) {
1317 analysis_window->set_session (_session);
1321 sfbrowser->set_session (_session);
1324 compute_fixed_ruler_scale ();
1326 /* Make sure we have auto loop and auto punch ranges */
1328 Location* loc = _session->locations()->auto_loop_location();
1330 loc->set_name (_("Loop"));
1333 loc = _session->locations()->auto_punch_location();
1336 loc->set_name (_("Punch"));
1339 refresh_location_display ();
1341 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1342 the selected Marker; this needs the LocationMarker list to be available.
1344 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1345 set_state (*node, Stateful::loading_state_version);
1347 /* catch up with the playhead */
1349 _session->request_locate (playhead_cursor->current_frame ());
1350 _pending_initial_locate = true;
1354 /* These signals can all be emitted by a non-GUI thread. Therefore the
1355 handlers for them must not attempt to directly interact with the GUI,
1356 but use PBD::Signal<T>::connect() which accepts an event loop
1357 ("context") where the handler will be asked to run.
1360 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1361 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1362 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1363 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1364 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1365 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1366 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1367 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1368 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1369 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1370 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1371 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1372 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1374 playhead_cursor->show ();
1376 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1377 Config->map_parameters (pc);
1378 _session->config.map_parameters (pc);
1380 restore_ruler_visibility ();
1381 //tempo_map_changed (PropertyChange (0));
1382 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1384 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1385 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1388 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1389 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1392 switch (_snap_type) {
1393 case SnapToRegionStart:
1394 case SnapToRegionEnd:
1395 case SnapToRegionSync:
1396 case SnapToRegionBoundary:
1397 build_region_boundary_cache ();
1404 /* register for undo history */
1405 _session->register_with_memento_command_factory(id(), this);
1406 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1408 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1410 LuaInstance::instance()->set_session(_session);
1412 start_updating_meters ();
1416 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1418 if (a->get_name() == "RegionMenu") {
1419 /* When the main menu's region menu is opened, we setup the actions so that they look right
1420 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1421 so we resensitize all region actions when the entered regionview or the region selection
1422 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1423 happens after the region context menu is opened. So we set a flag here, too.
1427 sensitize_the_right_region_actions ();
1428 _last_region_menu_was_main = true;
1433 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1435 using namespace Menu_Helpers;
1437 void (Editor::*emf)(FadeShape);
1438 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1441 images = &_xfade_in_images;
1442 emf = &Editor::set_fade_in_shape;
1444 images = &_xfade_out_images;
1445 emf = &Editor::set_fade_out_shape;
1450 _("Linear (for highly correlated material)"),
1451 *(*images)[FadeLinear],
1452 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1456 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1460 _("Constant power"),
1461 *(*images)[FadeConstantPower],
1462 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1465 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1470 *(*images)[FadeSymmetric],
1471 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1475 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1480 *(*images)[FadeSlow],
1481 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1484 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1489 *(*images)[FadeFast],
1490 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1493 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1496 /** Pop up a context menu for when the user clicks on a start crossfade */
1498 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1500 using namespace Menu_Helpers;
1501 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1506 MenuList& items (xfade_in_context_menu.items());
1509 if (arv->audio_region()->fade_in_active()) {
1510 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1512 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1515 items.push_back (SeparatorElem());
1516 fill_xfade_menu (items, true);
1518 xfade_in_context_menu.popup (button, time);
1521 /** Pop up a context menu for when the user clicks on an end crossfade */
1523 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1525 using namespace Menu_Helpers;
1526 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1531 MenuList& items (xfade_out_context_menu.items());
1534 if (arv->audio_region()->fade_out_active()) {
1535 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1537 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1540 items.push_back (SeparatorElem());
1541 fill_xfade_menu (items, false);
1543 xfade_out_context_menu.popup (button, time);
1547 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1549 using namespace Menu_Helpers;
1550 Menu* (Editor::*build_menu_function)();
1553 switch (item_type) {
1555 case RegionViewName:
1556 case RegionViewNameHighlight:
1557 case LeftFrameHandle:
1558 case RightFrameHandle:
1559 if (with_selection) {
1560 build_menu_function = &Editor::build_track_selection_context_menu;
1562 build_menu_function = &Editor::build_track_region_context_menu;
1567 if (with_selection) {
1568 build_menu_function = &Editor::build_track_selection_context_menu;
1570 build_menu_function = &Editor::build_track_context_menu;
1575 if (clicked_routeview->track()) {
1576 build_menu_function = &Editor::build_track_context_menu;
1578 build_menu_function = &Editor::build_track_bus_context_menu;
1583 /* probably shouldn't happen but if it does, we don't care */
1587 menu = (this->*build_menu_function)();
1588 menu->set_name ("ArdourContextMenu");
1590 /* now handle specific situations */
1592 switch (item_type) {
1594 case RegionViewName:
1595 case RegionViewNameHighlight:
1596 case LeftFrameHandle:
1597 case RightFrameHandle:
1598 if (!with_selection) {
1599 if (region_edit_menu_split_item) {
1600 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1601 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1603 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1606 if (region_edit_menu_split_multichannel_item) {
1607 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1608 region_edit_menu_split_multichannel_item->set_sensitive (true);
1610 region_edit_menu_split_multichannel_item->set_sensitive (false);
1623 /* probably shouldn't happen but if it does, we don't care */
1627 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1629 /* Bounce to disk */
1631 using namespace Menu_Helpers;
1632 MenuList& edit_items = menu->items();
1634 edit_items.push_back (SeparatorElem());
1636 switch (clicked_routeview->audio_track()->freeze_state()) {
1637 case AudioTrack::NoFreeze:
1638 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1641 case AudioTrack::Frozen:
1642 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1645 case AudioTrack::UnFrozen:
1646 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1652 if (item_type == StreamItem && clicked_routeview) {
1653 clicked_routeview->build_underlay_menu(menu);
1656 /* When the region menu is opened, we setup the actions so that they look right
1659 sensitize_the_right_region_actions ();
1660 _last_region_menu_was_main = false;
1662 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1663 menu->popup (button, time);
1667 Editor::build_track_context_menu ()
1669 using namespace Menu_Helpers;
1671 MenuList& edit_items = track_context_menu.items();
1674 add_dstream_context_items (edit_items);
1675 return &track_context_menu;
1679 Editor::build_track_bus_context_menu ()
1681 using namespace Menu_Helpers;
1683 MenuList& edit_items = track_context_menu.items();
1686 add_bus_context_items (edit_items);
1687 return &track_context_menu;
1691 Editor::build_track_region_context_menu ()
1693 using namespace Menu_Helpers;
1694 MenuList& edit_items = track_region_context_menu.items();
1697 /* we've just cleared the track region context menu, so the menu that these
1698 two items were on will have disappeared; stop them dangling.
1700 region_edit_menu_split_item = 0;
1701 region_edit_menu_split_multichannel_item = 0;
1703 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1706 boost::shared_ptr<Track> tr;
1707 boost::shared_ptr<Playlist> pl;
1709 if ((tr = rtv->track())) {
1710 add_region_context_items (edit_items, tr);
1714 add_dstream_context_items (edit_items);
1716 return &track_region_context_menu;
1720 Editor::loudness_analyze_region_selection ()
1725 Selection& s (PublicEditor::instance ().get_selection ());
1726 RegionSelection ars = s.regions;
1727 ARDOUR::AnalysisGraph ag (_session);
1728 framecnt_t total_work = 0;
1730 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1731 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1735 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1738 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1739 total_work += arv->region ()->length ();
1742 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1744 ag.set_total_frames (total_work);
1745 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1748 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1749 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1753 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1757 ag.analyze_region (ar);
1760 if (!ag.canceled ()) {
1761 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1767 Editor::loudness_analyze_range_selection ()
1772 Selection& s (PublicEditor::instance ().get_selection ());
1773 TimeSelection ts = s.time;
1774 ARDOUR::AnalysisGraph ag (_session);
1775 framecnt_t total_work = 0;
1777 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1778 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1782 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1786 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1787 total_work += j->length ();
1791 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1793 ag.set_total_frames (total_work);
1794 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1797 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1798 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1802 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1806 ag.analyze_range (rui->route (), pl, ts);
1809 if (!ag.canceled ()) {
1810 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1816 Editor::spectral_analyze_region_selection ()
1818 if (analysis_window == 0) {
1819 analysis_window = new AnalysisWindow();
1822 analysis_window->set_session(_session);
1824 analysis_window->show_all();
1827 analysis_window->set_regionmode();
1828 analysis_window->analyze();
1830 analysis_window->present();
1834 Editor::spectral_analyze_range_selection()
1836 if (analysis_window == 0) {
1837 analysis_window = new AnalysisWindow();
1840 analysis_window->set_session(_session);
1842 analysis_window->show_all();
1845 analysis_window->set_rangemode();
1846 analysis_window->analyze();
1848 analysis_window->present();
1852 Editor::build_track_selection_context_menu ()
1854 using namespace Menu_Helpers;
1855 MenuList& edit_items = track_selection_context_menu.items();
1856 edit_items.clear ();
1858 add_selection_context_items (edit_items);
1859 // edit_items.push_back (SeparatorElem());
1860 // add_dstream_context_items (edit_items);
1862 return &track_selection_context_menu;
1866 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1868 using namespace Menu_Helpers;
1870 /* OK, stick the region submenu at the top of the list, and then add
1874 RegionSelection rs = get_regions_from_selection_and_entered ();
1876 string::size_type pos = 0;
1877 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1879 /* we have to hack up the region name because "_" has a special
1880 meaning for menu titles.
1883 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1884 menu_item_name.replace (pos, 1, "__");
1888 if (_popup_region_menu_item == 0) {
1889 _popup_region_menu_item = new MenuItem (menu_item_name);
1890 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1891 _popup_region_menu_item->show ();
1893 _popup_region_menu_item->set_label (menu_item_name);
1896 /* No latering allowed in later is higher layering model */
1897 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1898 if (act && Config->get_layer_model() == LaterHigher) {
1899 act->set_sensitive (false);
1901 act->set_sensitive (true);
1904 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1906 edit_items.push_back (*_popup_region_menu_item);
1907 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1908 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1910 edit_items.push_back (SeparatorElem());
1913 /** Add context menu items relevant to selection ranges.
1914 * @param edit_items List to add the items to.
1917 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1919 using namespace Menu_Helpers;
1921 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1922 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1924 edit_items.push_back (SeparatorElem());
1925 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1927 edit_items.push_back (SeparatorElem());
1928 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1929 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1931 edit_items.push_back (SeparatorElem());
1933 edit_items.push_back (
1935 _("Move Range Start to Previous Region Boundary"),
1936 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1940 edit_items.push_back (
1942 _("Move Range Start to Next Region Boundary"),
1943 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1947 edit_items.push_back (
1949 _("Move Range End to Previous Region Boundary"),
1950 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1954 edit_items.push_back (
1956 _("Move Range End to Next Region Boundary"),
1957 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1961 edit_items.push_back (SeparatorElem());
1962 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1963 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1965 edit_items.push_back (SeparatorElem());
1966 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1968 edit_items.push_back (SeparatorElem());
1969 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1970 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1971 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1973 edit_items.push_back (SeparatorElem());
1974 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1976 edit_items.push_back (SeparatorElem());
1977 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1978 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1980 edit_items.push_back (SeparatorElem());
1981 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1982 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1983 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1984 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1985 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1986 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1987 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1993 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1995 using namespace Menu_Helpers;
1999 Menu *play_menu = manage (new Menu);
2000 MenuList& play_items = play_menu->items();
2001 play_menu->set_name ("ArdourContextMenu");
2003 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2004 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2005 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
2006 play_items.push_back (SeparatorElem());
2007 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
2009 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2013 Menu *select_menu = manage (new Menu);
2014 MenuList& select_items = select_menu->items();
2015 select_menu->set_name ("ArdourContextMenu");
2017 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2018 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2019 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2020 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2021 select_items.push_back (SeparatorElem());
2022 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2023 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2024 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2025 select_items.push_back (SeparatorElem());
2026 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2027 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2028 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2029 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2030 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2031 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2032 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2034 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2038 Menu *cutnpaste_menu = manage (new Menu);
2039 MenuList& cutnpaste_items = cutnpaste_menu->items();
2040 cutnpaste_menu->set_name ("ArdourContextMenu");
2042 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2043 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2044 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2046 cutnpaste_items.push_back (SeparatorElem());
2048 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2049 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2051 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2053 /* Adding new material */
2055 edit_items.push_back (SeparatorElem());
2056 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2057 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2061 Menu *nudge_menu = manage (new Menu());
2062 MenuList& nudge_items = nudge_menu->items();
2063 nudge_menu->set_name ("ArdourContextMenu");
2065 edit_items.push_back (SeparatorElem());
2066 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2067 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2068 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2069 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2071 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2075 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2077 using namespace Menu_Helpers;
2081 Menu *play_menu = manage (new Menu);
2082 MenuList& play_items = play_menu->items();
2083 play_menu->set_name ("ArdourContextMenu");
2085 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2086 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2087 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2091 Menu *select_menu = manage (new Menu);
2092 MenuList& select_items = select_menu->items();
2093 select_menu->set_name ("ArdourContextMenu");
2095 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2096 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2097 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2098 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2099 select_items.push_back (SeparatorElem());
2100 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2101 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2102 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2103 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2105 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2109 Menu *cutnpaste_menu = manage (new Menu);
2110 MenuList& cutnpaste_items = cutnpaste_menu->items();
2111 cutnpaste_menu->set_name ("ArdourContextMenu");
2113 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2114 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2115 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2117 Menu *nudge_menu = manage (new Menu());
2118 MenuList& nudge_items = nudge_menu->items();
2119 nudge_menu->set_name ("ArdourContextMenu");
2121 edit_items.push_back (SeparatorElem());
2122 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2123 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2124 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2125 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2127 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2131 Editor::snap_type() const
2137 Editor::snap_mode() const
2143 Editor::set_snap_to (SnapType st)
2145 unsigned int snap_ind = (unsigned int)st;
2147 if (internal_editing()) {
2148 internal_snap_type = st;
2150 pre_internal_snap_type = st;
2155 if (snap_ind > snap_type_strings.size() - 1) {
2157 _snap_type = (SnapType)snap_ind;
2160 string str = snap_type_strings[snap_ind];
2162 if (str != snap_type_selector.get_text()) {
2163 snap_type_selector.set_text (str);
2168 switch (_snap_type) {
2169 case SnapToBeatDiv128:
2170 case SnapToBeatDiv64:
2171 case SnapToBeatDiv32:
2172 case SnapToBeatDiv28:
2173 case SnapToBeatDiv24:
2174 case SnapToBeatDiv20:
2175 case SnapToBeatDiv16:
2176 case SnapToBeatDiv14:
2177 case SnapToBeatDiv12:
2178 case SnapToBeatDiv10:
2179 case SnapToBeatDiv8:
2180 case SnapToBeatDiv7:
2181 case SnapToBeatDiv6:
2182 case SnapToBeatDiv5:
2183 case SnapToBeatDiv4:
2184 case SnapToBeatDiv3:
2185 case SnapToBeatDiv2: {
2186 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2187 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2189 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2190 current_bbt_points_begin, current_bbt_points_end);
2191 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2192 current_bbt_points_begin, current_bbt_points_end);
2193 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2197 case SnapToRegionStart:
2198 case SnapToRegionEnd:
2199 case SnapToRegionSync:
2200 case SnapToRegionBoundary:
2201 build_region_boundary_cache ();
2209 redisplay_tempo (false);
2211 SnapChanged (); /* EMIT SIGNAL */
2215 Editor::set_snap_mode (SnapMode mode)
2217 string str = snap_mode_strings[(int)mode];
2219 if (internal_editing()) {
2220 internal_snap_mode = mode;
2222 pre_internal_snap_mode = mode;
2227 if (str != snap_mode_selector.get_text ()) {
2228 snap_mode_selector.set_text (str);
2235 Editor::set_edit_point_preference (EditPoint ep, bool force)
2237 bool changed = (_edit_point != ep);
2240 if (Profile->get_mixbus())
2241 if (ep == EditAtSelectedMarker)
2242 ep = EditAtPlayhead;
2244 string str = edit_point_strings[(int)ep];
2245 if (str != edit_point_selector.get_text ()) {
2246 edit_point_selector.set_text (str);
2249 update_all_enter_cursors();
2251 if (!force && !changed) {
2255 const char* action=NULL;
2257 switch (_edit_point) {
2258 case EditAtPlayhead:
2259 action = "edit-at-playhead";
2261 case EditAtSelectedMarker:
2262 action = "edit-at-marker";
2265 action = "edit-at-mouse";
2269 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2271 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2275 bool in_track_canvas;
2277 if (!mouse_frame (foo, in_track_canvas)) {
2278 in_track_canvas = false;
2281 reset_canvas_action_sensitivity (in_track_canvas);
2287 Editor::set_state (const XMLNode& node, int version)
2289 const XMLProperty* prop;
2292 Tabbable::set_state (node, version);
2294 if (_session && (prop = node.property ("playhead"))) {
2296 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2298 playhead_cursor->set_position (pos);
2300 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2301 playhead_cursor->set_position (0);
2304 playhead_cursor->set_position (0);
2307 if ((prop = node.property ("mixer-width"))) {
2308 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2311 if ((prop = node.property ("zoom-focus"))) {
2312 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2315 if ((prop = node.property ("zoom"))) {
2316 /* older versions of ardour used floating point samples_per_pixel */
2317 double f = PBD::atof (prop->value());
2318 reset_zoom (llrintf (f));
2320 reset_zoom (samples_per_pixel);
2323 if ((prop = node.property ("visible-track-count"))) {
2324 set_visible_track_count (PBD::atoi (prop->value()));
2327 if ((prop = node.property ("snap-to"))) {
2328 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2331 if ((prop = node.property ("snap-mode"))) {
2332 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2335 if ((prop = node.property ("internal-snap-to"))) {
2336 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2339 if ((prop = node.property ("internal-snap-mode"))) {
2340 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2343 if ((prop = node.property ("pre-internal-snap-to"))) {
2344 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2347 if ((prop = node.property ("pre-internal-snap-mode"))) {
2348 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2351 if ((prop = node.property ("mouse-mode"))) {
2352 MouseMode m = str2mousemode(prop->value());
2353 set_mouse_mode (m, true);
2355 set_mouse_mode (MouseObject, true);
2358 if ((prop = node.property ("left-frame")) != 0) {
2360 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2364 reset_x_origin (pos);
2368 if ((prop = node.property ("y-origin")) != 0) {
2369 reset_y_origin (atof (prop->value ()));
2372 if ((prop = node.property ("join-object-range"))) {
2373 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2374 bool yn = string_is_affirmative (prop->value());
2376 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2377 tact->set_active (!yn);
2378 tact->set_active (yn);
2380 set_mouse_mode(mouse_mode, true);
2383 if ((prop = node.property ("edit-point"))) {
2384 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2387 if ((prop = node.property ("show-measures"))) {
2388 bool yn = string_is_affirmative (prop->value());
2389 _show_measures = yn;
2392 if ((prop = node.property ("follow-playhead"))) {
2393 bool yn = string_is_affirmative (prop->value());
2394 set_follow_playhead (yn);
2397 if ((prop = node.property ("stationary-playhead"))) {
2398 bool yn = string_is_affirmative (prop->value());
2399 set_stationary_playhead (yn);
2402 if ((prop = node.property ("region-list-sort-type"))) {
2403 RegionListSortType st;
2404 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2407 if ((prop = node.property ("show-editor-mixer"))) {
2409 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2412 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2413 bool yn = string_is_affirmative (prop->value());
2415 /* do it twice to force the change */
2417 tact->set_active (!yn);
2418 tact->set_active (yn);
2421 if ((prop = node.property ("show-editor-list"))) {
2423 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2426 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2427 bool yn = string_is_affirmative (prop->value());
2429 /* do it twice to force the change */
2431 tact->set_active (!yn);
2432 tact->set_active (yn);
2435 if ((prop = node.property (X_("editor-list-page")))) {
2436 _the_notebook.set_current_page (atoi (prop->value ()));
2439 if ((prop = node.property (X_("show-marker-lines")))) {
2440 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2442 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2443 bool yn = string_is_affirmative (prop->value ());
2445 tact->set_active (!yn);
2446 tact->set_active (yn);
2449 XMLNodeList children = node.children ();
2450 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2451 selection->set_state (**i, Stateful::current_state_version);
2452 _regions->set_state (**i);
2455 if ((prop = node.property ("maximised"))) {
2456 bool yn = string_is_affirmative (prop->value());
2457 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2459 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2460 bool fs = tact && tact->get_active();
2462 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2466 if ((prop = node.property ("nudge-clock-value"))) {
2468 sscanf (prop->value().c_str(), "%" PRId64, &f);
2469 nudge_clock->set (f);
2471 nudge_clock->set_mode (AudioClock::Timecode);
2472 nudge_clock->set (_session->frame_rate() * 5, true);
2477 * Not all properties may have been in XML, but
2478 * those that are linked to a private variable may need changing
2483 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2485 yn = _show_measures;
2486 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2487 /* do it twice to force the change */
2488 tact->set_active (!yn);
2489 tact->set_active (yn);
2492 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2493 yn = _follow_playhead;
2495 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2496 if (tact->get_active() != yn) {
2497 tact->set_active (yn);
2501 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2502 yn = _stationary_playhead;
2504 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2505 if (tact->get_active() != yn) {
2506 tact->set_active (yn);
2511 return LuaInstance::instance()->set_state(node);
2515 Editor::get_state ()
2517 XMLNode* node = new XMLNode (X_("Editor"));
2520 id().print (buf, sizeof (buf));
2521 node->add_property ("id", buf);
2523 node->add_child_nocopy (Tabbable::get_state());
2525 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2526 node->add_property("edit-horizontal-pane-pos", string(buf));
2527 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2528 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2529 node->add_property("edit-vertical-pane-pos", string(buf));
2531 maybe_add_mixer_strip_width (*node);
2533 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2535 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2536 node->add_property ("zoom", buf);
2537 node->add_property ("snap-to", enum_2_string (_snap_type));
2538 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2539 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2540 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2541 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2542 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2543 node->add_property ("edit-point", enum_2_string (_edit_point));
2544 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2545 node->add_property ("visible-track-count", buf);
2547 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2548 node->add_property ("playhead", buf);
2549 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2550 node->add_property ("left-frame", buf);
2551 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2552 node->add_property ("y-origin", buf);
2554 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2555 node->add_property ("maximised", _maximised ? "yes" : "no");
2556 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2557 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2558 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2559 node->add_property ("mouse-mode", enum2str(mouse_mode));
2560 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2562 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2564 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2565 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2568 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2570 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2571 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2574 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2575 node->add_property (X_("editor-list-page"), buf);
2577 if (button_bindings) {
2578 XMLNode* bb = new XMLNode (X_("Buttons"));
2579 button_bindings->save (*bb);
2580 node->add_child_nocopy (*bb);
2583 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2585 node->add_child_nocopy (selection->get_state ());
2586 node->add_child_nocopy (_regions->get_state ());
2588 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2589 node->add_property ("nudge-clock-value", buf);
2591 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2592 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2597 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2598 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2600 * @return pair: TimeAxisView that y is over, layer index.
2602 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2603 * in stacked or expanded region display mode, otherwise 0.
2605 std::pair<TimeAxisView *, double>
2606 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2608 if (!trackview_relative_offset) {
2609 y -= _trackview_group->canvas_origin().y;
2613 return std::make_pair ( (TimeAxisView *) 0, 0);
2616 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2618 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2625 return std::make_pair ( (TimeAxisView *) 0, 0);
2628 /** Snap a position to the grid, if appropriate, taking into account current
2629 * grid settings and also the state of any snap modifier keys that may be pressed.
2630 * @param start Position to snap.
2631 * @param event Event to get current key modifier information from, or 0.
2634 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2636 if (!_session || !event) {
2640 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2641 if (_snap_mode == SnapOff) {
2642 snap_to_internal (start, direction, for_mark);
2645 if (_snap_mode != SnapOff) {
2646 snap_to_internal (start, direction, for_mark);
2647 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2648 /* SnapOff, but we pressed the snap_delta modifier */
2649 snap_to_internal (start, direction, for_mark);
2655 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2657 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2661 snap_to_internal (start, direction, for_mark, ensure_snap);
2665 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2667 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2668 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2670 switch (_snap_type) {
2671 case SnapToTimecodeFrame:
2672 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2673 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2674 /* start is already on a whole timecode frame, do nothing */
2675 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2676 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2678 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2682 case SnapToTimecodeSeconds:
2683 if (_session->config.get_timecode_offset_negative()) {
2684 start += _session->config.get_timecode_offset ();
2686 start -= _session->config.get_timecode_offset ();
2688 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2689 (start % one_timecode_second == 0)) {
2690 /* start is already on a whole second, do nothing */
2691 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2692 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2694 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2697 if (_session->config.get_timecode_offset_negative()) {
2698 start -= _session->config.get_timecode_offset ();
2700 start += _session->config.get_timecode_offset ();
2704 case SnapToTimecodeMinutes:
2705 if (_session->config.get_timecode_offset_negative()) {
2706 start += _session->config.get_timecode_offset ();
2708 start -= _session->config.get_timecode_offset ();
2710 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2711 (start % one_timecode_minute == 0)) {
2712 /* start is already on a whole minute, do nothing */
2713 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2714 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2716 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2718 if (_session->config.get_timecode_offset_negative()) {
2719 start -= _session->config.get_timecode_offset ();
2721 start += _session->config.get_timecode_offset ();
2725 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2726 abort(); /*NOTREACHED*/
2731 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2733 const framepos_t one_second = _session->frame_rate();
2734 const framepos_t one_minute = _session->frame_rate() * 60;
2735 framepos_t presnap = start;
2739 switch (_snap_type) {
2740 case SnapToTimecodeFrame:
2741 case SnapToTimecodeSeconds:
2742 case SnapToTimecodeMinutes:
2743 return timecode_snap_to_internal (start, direction, for_mark);
2746 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2747 start % (one_second/75) == 0) {
2748 /* start is already on a whole CD frame, do nothing */
2749 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2750 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2752 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2757 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2758 start % one_second == 0) {
2759 /* start is already on a whole second, do nothing */
2760 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2761 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2763 start = (framepos_t) floor ((double) start / one_second) * one_second;
2768 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2769 start % one_minute == 0) {
2770 /* start is already on a whole minute, do nothing */
2771 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2772 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2774 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2779 start = _session->tempo_map().round_to_bar (start, direction);
2783 start = _session->tempo_map().round_to_beat (start, direction);
2786 case SnapToBeatDiv128:
2787 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2789 case SnapToBeatDiv64:
2790 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2792 case SnapToBeatDiv32:
2793 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2795 case SnapToBeatDiv28:
2796 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2798 case SnapToBeatDiv24:
2799 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2801 case SnapToBeatDiv20:
2802 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2804 case SnapToBeatDiv16:
2805 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2807 case SnapToBeatDiv14:
2808 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2810 case SnapToBeatDiv12:
2811 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2813 case SnapToBeatDiv10:
2814 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2816 case SnapToBeatDiv8:
2817 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2819 case SnapToBeatDiv7:
2820 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2822 case SnapToBeatDiv6:
2823 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2825 case SnapToBeatDiv5:
2826 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2828 case SnapToBeatDiv4:
2829 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2831 case SnapToBeatDiv3:
2832 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2834 case SnapToBeatDiv2:
2835 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2843 _session->locations()->marks_either_side (start, before, after);
2845 if (before == max_framepos && after == max_framepos) {
2846 /* No marks to snap to, so just don't snap */
2848 } else if (before == max_framepos) {
2850 } else if (after == max_framepos) {
2852 } else if (before != max_framepos && after != max_framepos) {
2853 /* have before and after */
2854 if ((start - before) < (after - start)) {
2863 case SnapToRegionStart:
2864 case SnapToRegionEnd:
2865 case SnapToRegionSync:
2866 case SnapToRegionBoundary:
2867 if (!region_boundary_cache.empty()) {
2869 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2870 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2872 if (direction > 0) {
2873 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2875 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2878 if (next != region_boundary_cache.begin ()) {
2883 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2884 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2886 if (start > (p + n) / 2) {
2895 switch (_snap_mode) {
2905 if (presnap > start) {
2906 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2910 } else if (presnap < start) {
2911 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2917 /* handled at entry */
2925 Editor::setup_toolbar ()
2927 HBox* mode_box = manage(new HBox);
2928 mode_box->set_border_width (2);
2929 mode_box->set_spacing(2);
2931 HBox* mouse_mode_box = manage (new HBox);
2932 HBox* mouse_mode_hbox = manage (new HBox);
2933 VBox* mouse_mode_vbox = manage (new VBox);
2934 Alignment* mouse_mode_align = manage (new Alignment);
2936 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2937 mouse_mode_size_group->add_widget (smart_mode_button);
2938 mouse_mode_size_group->add_widget (mouse_move_button);
2939 mouse_mode_size_group->add_widget (mouse_cut_button);
2940 mouse_mode_size_group->add_widget (mouse_select_button);
2941 mouse_mode_size_group->add_widget (mouse_timefx_button);
2942 mouse_mode_size_group->add_widget (mouse_audition_button);
2943 mouse_mode_size_group->add_widget (mouse_draw_button);
2944 mouse_mode_size_group->add_widget (mouse_content_button);
2946 mouse_mode_size_group->add_widget (zoom_in_button);
2947 mouse_mode_size_group->add_widget (zoom_out_button);
2948 mouse_mode_size_group->add_widget (zoom_preset_selector);
2949 mouse_mode_size_group->add_widget (zoom_out_full_button);
2950 mouse_mode_size_group->add_widget (zoom_focus_selector);
2952 mouse_mode_size_group->add_widget (tav_shrink_button);
2953 mouse_mode_size_group->add_widget (tav_expand_button);
2954 mouse_mode_size_group->add_widget (visible_tracks_selector);
2956 mouse_mode_size_group->add_widget (snap_type_selector);
2957 mouse_mode_size_group->add_widget (snap_mode_selector);
2959 mouse_mode_size_group->add_widget (edit_point_selector);
2960 mouse_mode_size_group->add_widget (edit_mode_selector);
2962 mouse_mode_size_group->add_widget (*nudge_clock);
2963 mouse_mode_size_group->add_widget (nudge_forward_button);
2964 mouse_mode_size_group->add_widget (nudge_backward_button);
2966 mouse_mode_hbox->set_spacing (2);
2968 if (!ARDOUR::Profile->get_trx()) {
2969 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2972 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2973 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2975 if (!ARDOUR::Profile->get_mixbus()) {
2976 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2979 if (!ARDOUR::Profile->get_trx()) {
2980 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2981 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2982 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2983 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2986 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2988 mouse_mode_align->add (*mouse_mode_vbox);
2989 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2991 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2993 edit_mode_selector.set_name ("mouse mode button");
2995 if (!ARDOUR::Profile->get_trx()) {
2996 mode_box->pack_start (edit_mode_selector, false, false);
2999 mode_box->pack_start (*mouse_mode_box, false, false);
3003 _zoom_box.set_spacing (2);
3004 _zoom_box.set_border_width (2);
3008 zoom_preset_selector.set_name ("zoom button");
3009 zoom_preset_selector.set_image(::get_icon ("time_exp"));
3010 zoom_preset_selector.set_size_request (42, -1);
3012 zoom_in_button.set_name ("zoom button");
3013 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
3014 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
3015 zoom_in_button.set_related_action (act);
3017 zoom_out_button.set_name ("zoom button");
3018 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
3019 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
3020 zoom_out_button.set_related_action (act);
3022 zoom_out_full_button.set_name ("zoom button");
3023 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
3024 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
3025 zoom_out_full_button.set_related_action (act);
3027 zoom_focus_selector.set_name ("zoom button");
3029 if (ARDOUR::Profile->get_mixbus()) {
3030 _zoom_box.pack_start (zoom_preset_selector, false, false);
3031 } else if (ARDOUR::Profile->get_trx()) {
3032 mode_box->pack_start (zoom_out_button, false, false);
3033 mode_box->pack_start (zoom_in_button, false, false);
3035 _zoom_box.pack_start (zoom_out_button, false, false);
3036 _zoom_box.pack_start (zoom_in_button, false, false);
3037 _zoom_box.pack_start (zoom_out_full_button, false, false);
3038 _zoom_box.pack_start (zoom_focus_selector, false, false);
3041 /* Track zoom buttons */
3042 visible_tracks_selector.set_name ("zoom button");
3043 if (Profile->get_mixbus()) {
3044 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
3045 visible_tracks_selector.set_size_request (42, -1);
3047 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3050 tav_expand_button.set_name ("zoom button");
3051 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3052 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3053 tav_expand_button.set_related_action (act);
3055 tav_shrink_button.set_name ("zoom button");
3056 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3057 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3058 tav_shrink_button.set_related_action (act);
3060 if (ARDOUR::Profile->get_mixbus()) {
3061 _zoom_box.pack_start (visible_tracks_selector);
3062 } else if (ARDOUR::Profile->get_trx()) {
3063 _zoom_box.pack_start (tav_shrink_button);
3064 _zoom_box.pack_start (tav_expand_button);
3066 _zoom_box.pack_start (visible_tracks_selector);
3067 _zoom_box.pack_start (tav_shrink_button);
3068 _zoom_box.pack_start (tav_expand_button);
3071 snap_box.set_spacing (2);
3072 snap_box.set_border_width (2);
3074 snap_type_selector.set_name ("mouse mode button");
3076 snap_mode_selector.set_name ("mouse mode button");
3078 edit_point_selector.set_name ("mouse mode button");
3080 snap_box.pack_start (snap_mode_selector, false, false);
3081 snap_box.pack_start (snap_type_selector, false, false);
3082 snap_box.pack_start (edit_point_selector, false, false);
3086 HBox *nudge_box = manage (new HBox);
3087 nudge_box->set_spacing (2);
3088 nudge_box->set_border_width (2);
3090 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3091 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3093 nudge_box->pack_start (nudge_backward_button, false, false);
3094 nudge_box->pack_start (nudge_forward_button, false, false);
3095 nudge_box->pack_start (*nudge_clock, false, false);
3098 /* Pack everything in... */
3100 HBox* hbox = manage (new HBox);
3101 hbox->set_spacing(2);
3103 toolbar_hbox.set_spacing (2);
3104 toolbar_hbox.set_border_width (1);
3106 toolbar_hbox.pack_start (*mode_box, false, false);
3107 if (!ARDOUR::Profile->get_trx()) {
3108 toolbar_hbox.pack_start (_zoom_box, false, false);
3109 toolbar_hbox.pack_start (*hbox, false, false);
3112 if (!ARDOUR::Profile->get_trx()) {
3113 hbox->pack_start (snap_box, false, false);
3114 hbox->pack_start (*nudge_box, false, false);
3119 toolbar_base.set_name ("ToolBarBase");
3120 toolbar_base.add (toolbar_hbox);
3122 _toolbar_viewport.add (toolbar_base);
3123 /* stick to the required height but allow width to vary if there's not enough room */
3124 _toolbar_viewport.set_size_request (1, -1);
3126 toolbar_frame.set_shadow_type (SHADOW_OUT);
3127 toolbar_frame.set_name ("BaseFrame");
3128 toolbar_frame.add (_toolbar_viewport);
3132 Editor::build_edit_point_menu ()
3134 using namespace Menu_Helpers;
3136 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3137 if(!Profile->get_mixbus())
3138 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3139 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3141 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3145 Editor::build_edit_mode_menu ()
3147 using namespace Menu_Helpers;
3149 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3150 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3151 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3152 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3154 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3158 Editor::build_snap_mode_menu ()
3160 using namespace Menu_Helpers;
3162 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3163 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3164 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3166 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3170 Editor::build_snap_type_menu ()
3172 using namespace Menu_Helpers;
3174 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3175 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3176 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3177 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3178 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3179 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3180 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3181 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3182 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3183 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3184 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3185 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3186 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3187 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3188 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3189 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3190 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3191 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3192 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3193 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3194 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3195 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3196 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3197 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3198 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3199 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3200 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3201 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3202 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3203 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3205 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3210 Editor::setup_tooltips ()
3212 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3213 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3214 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3215 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3216 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3217 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3218 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3219 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3220 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3221 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3222 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3223 set_tooltip (zoom_in_button, _("Zoom In"));
3224 set_tooltip (zoom_out_button, _("Zoom Out"));
3225 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3226 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3227 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3228 set_tooltip (tav_expand_button, _("Expand Tracks"));
3229 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3230 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3231 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3232 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3233 set_tooltip (edit_point_selector, _("Edit Point"));
3234 set_tooltip (edit_mode_selector, _("Edit Mode"));
3235 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3239 Editor::convert_drop_to_paths (
3240 vector<string>& paths,
3241 const RefPtr<Gdk::DragContext>& /*context*/,
3244 const SelectionData& data,
3248 if (_session == 0) {
3252 vector<string> uris = data.get_uris();
3256 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3257 are actually URI lists. So do it by hand.
3260 if (data.get_target() != "text/plain") {
3264 /* Parse the "uri-list" format that Nautilus provides,
3265 where each pathname is delimited by \r\n.
3267 THERE MAY BE NO NULL TERMINATING CHAR!!!
3270 string txt = data.get_text();
3274 p = (char *) malloc (txt.length() + 1);
3275 txt.copy (p, txt.length(), 0);
3276 p[txt.length()] = '\0';
3282 while (g_ascii_isspace (*p))
3286 while (*q && (*q != '\n') && (*q != '\r')) {
3293 while (q > p && g_ascii_isspace (*q))
3298 uris.push_back (string (p, q - p + 1));
3302 p = strchr (p, '\n');
3314 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3315 if ((*i).substr (0,7) == "file://") {
3316 paths.push_back (Glib::filename_from_uri (*i));
3324 Editor::new_tempo_section ()
3329 Editor::map_transport_state ()
3331 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3333 if (_session && _session->transport_stopped()) {
3334 have_pending_keyboard_selection = false;
3337 update_loop_range_view ();
3343 Editor::begin_selection_op_history ()
3345 selection_op_cmd_depth = 0;
3346 selection_op_history_it = 0;
3348 while(!selection_op_history.empty()) {
3349 delete selection_op_history.front();
3350 selection_op_history.pop_front();
3353 selection_undo_action->set_sensitive (false);
3354 selection_redo_action->set_sensitive (false);
3355 selection_op_history.push_front (&_selection_memento->get_state ());
3359 Editor::begin_reversible_selection_op (string name)
3362 //cerr << name << endl;
3363 /* begin/commit pairs can be nested */
3364 selection_op_cmd_depth++;
3369 Editor::commit_reversible_selection_op ()
3372 if (selection_op_cmd_depth == 1) {
3374 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3376 The user has undone some selection ops and then made a new one,
3377 making anything earlier in the list invalid.
3380 list<XMLNode *>::iterator it = selection_op_history.begin();
3381 list<XMLNode *>::iterator e_it = it;
3382 advance (e_it, selection_op_history_it);
3384 for ( ; it != e_it; ++it) {
3387 selection_op_history.erase (selection_op_history.begin(), e_it);
3390 selection_op_history.push_front (&_selection_memento->get_state ());
3391 selection_op_history_it = 0;
3393 selection_undo_action->set_sensitive (true);
3394 selection_redo_action->set_sensitive (false);
3397 if (selection_op_cmd_depth > 0) {
3398 selection_op_cmd_depth--;
3404 Editor::undo_selection_op ()
3407 selection_op_history_it++;
3409 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3410 if (n == selection_op_history_it) {
3411 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3412 selection_redo_action->set_sensitive (true);
3416 /* is there an earlier entry? */
3417 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3418 selection_undo_action->set_sensitive (false);
3424 Editor::redo_selection_op ()
3427 if (selection_op_history_it > 0) {
3428 selection_op_history_it--;
3431 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3432 if (n == selection_op_history_it) {
3433 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3434 selection_undo_action->set_sensitive (true);
3439 if (selection_op_history_it == 0) {
3440 selection_redo_action->set_sensitive (false);
3446 Editor::begin_reversible_command (string name)
3449 before.push_back (&_selection_memento->get_state ());
3450 _session->begin_reversible_command (name);
3455 Editor::begin_reversible_command (GQuark q)
3458 before.push_back (&_selection_memento->get_state ());
3459 _session->begin_reversible_command (q);
3464 Editor::abort_reversible_command ()
3467 while(!before.empty()) {
3468 delete before.front();
3471 _session->abort_reversible_command ();
3476 Editor::commit_reversible_command ()
3479 if (before.size() == 1) {
3480 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3481 redo_action->set_sensitive(false);
3482 undo_action->set_sensitive(true);
3483 begin_selection_op_history ();
3486 if (before.empty()) {
3487 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3492 _session->commit_reversible_command ();
3497 Editor::history_changed ()
3501 if (undo_action && _session) {
3502 if (_session->undo_depth() == 0) {
3503 label = S_("Command|Undo");
3505 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3507 undo_action->property_label() = label;
3510 if (redo_action && _session) {
3511 if (_session->redo_depth() == 0) {
3513 redo_action->set_sensitive (false);
3515 label = string_compose(_("Redo (%1)"), _session->next_redo());
3516 redo_action->set_sensitive (true);
3518 redo_action->property_label() = label;
3523 Editor::duplicate_range (bool with_dialog)
3527 RegionSelection rs = get_regions_from_selection_and_entered ();
3529 if ( selection->time.length() == 0 && rs.empty()) {
3535 ArdourDialog win (_("Duplicate"));
3536 Label label (_("Number of duplications:"));
3537 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3538 SpinButton spinner (adjustment, 0.0, 1);
3541 win.get_vbox()->set_spacing (12);
3542 win.get_vbox()->pack_start (hbox);
3543 hbox.set_border_width (6);
3544 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3546 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3547 place, visually. so do this by hand.
3550 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3551 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3552 spinner.grab_focus();
3558 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3559 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3560 win.set_default_response (RESPONSE_ACCEPT);
3562 spinner.grab_focus ();
3564 switch (win.run ()) {
3565 case RESPONSE_ACCEPT:
3571 times = adjustment.get_value();
3574 if ((current_mouse_mode() == Editing::MouseRange)) {
3575 if (selection->time.length()) {
3576 duplicate_selection (times);
3578 } else if (get_smart_mode()) {
3579 if (selection->time.length()) {
3580 duplicate_selection (times);
3582 duplicate_some_regions (rs, times);
3584 duplicate_some_regions (rs, times);
3589 Editor::set_edit_mode (EditMode m)
3591 Config->set_edit_mode (m);
3595 Editor::cycle_edit_mode ()
3597 switch (Config->get_edit_mode()) {
3599 Config->set_edit_mode (Ripple);
3603 Config->set_edit_mode (Lock);
3606 Config->set_edit_mode (Slide);
3612 Editor::edit_mode_selection_done ( EditMode m )
3614 Config->set_edit_mode ( m );
3618 Editor::snap_type_selection_done (SnapType snaptype)
3620 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3622 ract->set_active ();
3627 Editor::snap_mode_selection_done (SnapMode mode)
3629 RefPtr<RadioAction> ract = snap_mode_action (mode);
3632 ract->set_active (true);
3637 Editor::cycle_edit_point (bool with_marker)
3639 if(Profile->get_mixbus())
3640 with_marker = false;
3642 switch (_edit_point) {
3644 set_edit_point_preference (EditAtPlayhead);
3646 case EditAtPlayhead:
3648 set_edit_point_preference (EditAtSelectedMarker);
3650 set_edit_point_preference (EditAtMouse);
3653 case EditAtSelectedMarker:
3654 set_edit_point_preference (EditAtMouse);
3660 Editor::edit_point_selection_done (EditPoint ep)
3662 set_edit_point_preference ( ep );
3666 Editor::build_zoom_focus_menu ()
3668 using namespace Menu_Helpers;
3670 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3671 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3672 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3673 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3674 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3675 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3677 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3681 Editor::zoom_focus_selection_done ( ZoomFocus f )
3683 RefPtr<RadioAction> ract = zoom_focus_action (f);
3685 ract->set_active ();
3690 Editor::build_track_count_menu ()
3692 using namespace Menu_Helpers;
3694 if (!Profile->get_mixbus()) {
3695 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3696 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3697 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3698 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3699 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3700 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3701 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3702 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3703 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3704 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3705 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3706 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3707 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3709 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3710 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3711 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3712 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3713 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3714 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3715 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3716 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3717 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3718 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3720 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3721 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3722 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3723 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3724 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3725 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3726 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3727 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3728 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3729 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3730 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3735 Editor::set_zoom_preset (int64_t ms)
3738 temporal_zoom_session();
3742 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3743 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3747 Editor::set_visible_track_count (int32_t n)
3749 _visible_track_count = n;
3751 /* if the canvas hasn't really been allocated any size yet, just
3752 record the desired number of visible tracks and return. when canvas
3753 allocation happens, we will get called again and then we can do the
3757 if (_visible_canvas_height <= 1) {
3763 DisplaySuspender ds;
3765 if (_visible_track_count > 0) {
3766 h = trackviews_height() / _visible_track_count;
3767 std::ostringstream s;
3768 s << _visible_track_count;
3770 } else if (_visible_track_count == 0) {
3772 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3773 if ((*i)->marked_for_display()) {
3777 h = trackviews_height() / n;
3780 /* negative value means that the visible track count has
3781 been overridden by explicit track height changes.
3783 visible_tracks_selector.set_text (X_("*"));
3787 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3788 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3791 if (str != visible_tracks_selector.get_text()) {
3792 visible_tracks_selector.set_text (str);
3797 Editor::override_visible_track_count ()
3799 _visible_track_count = -1;
3800 visible_tracks_selector.set_text ( _("*") );
3804 Editor::edit_controls_button_release (GdkEventButton* ev)
3806 if (Keyboard::is_context_menu_event (ev)) {
3807 ARDOUR_UI::instance()->add_route (current_toplevel());
3808 } else if (ev->button == 1) {
3809 selection->clear_tracks ();
3816 Editor::mouse_select_button_release (GdkEventButton* ev)
3818 /* this handles just right-clicks */
3820 if (ev->button != 3) {
3828 Editor::set_zoom_focus (ZoomFocus f)
3830 string str = zoom_focus_strings[(int)f];
3832 if (str != zoom_focus_selector.get_text()) {
3833 zoom_focus_selector.set_text (str);
3836 if (zoom_focus != f) {
3843 Editor::cycle_zoom_focus ()
3845 switch (zoom_focus) {
3847 set_zoom_focus (ZoomFocusRight);
3849 case ZoomFocusRight:
3850 set_zoom_focus (ZoomFocusCenter);
3852 case ZoomFocusCenter:
3853 set_zoom_focus (ZoomFocusPlayhead);
3855 case ZoomFocusPlayhead:
3856 set_zoom_focus (ZoomFocusMouse);
3858 case ZoomFocusMouse:
3859 set_zoom_focus (ZoomFocusEdit);
3862 set_zoom_focus (ZoomFocusLeft);
3868 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3870 /* recover or initialize pane positions. do this here rather than earlier because
3871 we don't want the positions to change the child allocations, which they seem to do.
3877 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3886 XMLNode* geometry = find_named_node (*node, "geometry");
3888 if (which == static_cast<Paned*> (&edit_pane)) {
3890 if (done & Horizontal) {
3894 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3895 _notebook_shrunk = string_is_affirmative (prop->value ());
3898 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3899 /* initial allocation is 90% to canvas, 10% to notebook */
3900 pos = (int) floor (alloc.get_width() * 0.90f);
3901 snprintf (buf, sizeof(buf), "%d", pos);
3903 pos = atoi (prop->value());
3906 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3907 edit_pane.set_position (pos);
3910 done = (Pane) (done | Horizontal);
3912 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3914 if (done & Vertical) {
3918 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3919 /* initial allocation is 90% to canvas, 10% to summary */
3920 pos = (int) floor (alloc.get_height() * 0.90f);
3921 snprintf (buf, sizeof(buf), "%d", pos);
3924 pos = atoi (prop->value());
3927 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3928 editor_summary_pane.set_position (pos);
3931 done = (Pane) (done | Vertical);
3936 Editor::set_show_measures (bool yn)
3938 if (_show_measures != yn) {
3941 if ((_show_measures = yn) == true) {
3943 tempo_lines->show();
3946 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3947 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3949 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3950 draw_measures (begin, end);
3958 Editor::toggle_follow_playhead ()
3960 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3962 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3963 set_follow_playhead (tact->get_active());
3967 /** @param yn true to follow playhead, otherwise false.
3968 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3971 Editor::set_follow_playhead (bool yn, bool catch_up)
3973 if (_follow_playhead != yn) {
3974 if ((_follow_playhead = yn) == true && catch_up) {
3976 reset_x_origin_to_follow_playhead ();
3983 Editor::toggle_stationary_playhead ()
3985 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3987 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3988 set_stationary_playhead (tact->get_active());
3993 Editor::set_stationary_playhead (bool yn)
3995 if (_stationary_playhead != yn) {
3996 if ((_stationary_playhead = yn) == true) {
3998 // FIXME need a 3.0 equivalent of this 2.X call
3999 // update_current_screen ();
4006 Editor::playlist_selector () const
4008 return *_playlist_selector;
4012 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
4014 if (paste_count == 0) {
4015 /* don't bother calculating an offset that will be zero anyway */
4019 /* calculate basic unsnapped multi-paste offset */
4020 framecnt_t offset = paste_count * duration;
4022 /* snap offset so pos + offset is aligned to the grid */
4023 framepos_t offset_pos = pos + offset;
4024 snap_to(offset_pos, RoundUpMaybe);
4025 offset = offset_pos - pos;
4031 Editor::get_grid_beat_divisions(framepos_t position)
4033 switch (_snap_type) {
4034 case SnapToBeatDiv128: return 128;
4035 case SnapToBeatDiv64: return 64;
4036 case SnapToBeatDiv32: return 32;
4037 case SnapToBeatDiv28: return 28;
4038 case SnapToBeatDiv24: return 24;
4039 case SnapToBeatDiv20: return 20;
4040 case SnapToBeatDiv16: return 16;
4041 case SnapToBeatDiv14: return 14;
4042 case SnapToBeatDiv12: return 12;
4043 case SnapToBeatDiv10: return 10;
4044 case SnapToBeatDiv8: return 8;
4045 case SnapToBeatDiv7: return 7;
4046 case SnapToBeatDiv6: return 6;
4047 case SnapToBeatDiv5: return 5;
4048 case SnapToBeatDiv4: return 4;
4049 case SnapToBeatDiv3: return 3;
4050 case SnapToBeatDiv2: return 2;
4057 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4061 const unsigned divisions = get_grid_beat_divisions(position);
4063 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4066 switch (_snap_type) {
4068 return Evoral::Beats(1.0);
4071 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4079 return Evoral::Beats();
4083 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4087 ret = nudge_clock->current_duration (pos);
4088 next = ret + 1; /* XXXX fix me */
4094 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4096 ArdourDialog dialog (_("Playlist Deletion"));
4097 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4098 "If it is kept, its audio files will not be cleaned.\n"
4099 "If it is deleted, audio files used by it alone will be cleaned."),
4102 dialog.set_position (WIN_POS_CENTER);
4103 dialog.get_vbox()->pack_start (label);
4107 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4108 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4109 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4110 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4111 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4113 // by default gtk uses the left most button
4114 keep->grab_focus ();
4116 switch (dialog.run ()) {
4118 /* keep this and all remaining ones */
4123 /* delete this and all others */
4127 case RESPONSE_ACCEPT:
4128 /* delete the playlist */
4132 case RESPONSE_REJECT:
4133 /* keep the playlist */
4145 Editor::audio_region_selection_covers (framepos_t where)
4147 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4148 if ((*a)->region()->covers (where)) {
4157 Editor::prepare_for_cleanup ()
4159 cut_buffer->clear_regions ();
4160 cut_buffer->clear_playlists ();
4162 selection->clear_regions ();
4163 selection->clear_playlists ();
4165 _regions->suspend_redisplay ();
4169 Editor::finish_cleanup ()
4171 _regions->resume_redisplay ();
4175 Editor::transport_loop_location()
4178 return _session->locations()->auto_loop_location();
4185 Editor::transport_punch_location()
4188 return _session->locations()->auto_punch_location();
4195 Editor::control_layout_scroll (GdkEventScroll* ev)
4197 /* Just forward to the normal canvas scroll method. The coordinate
4198 systems are different but since the canvas is always larger than the
4199 track headers, and aligned with the trackview area, this will work.
4201 In the not too distant future this layout is going away anyway and
4202 headers will be on the canvas.
4204 return canvas_scroll_event (ev, false);
4208 Editor::session_state_saved (string)
4211 _snapshots->redisplay ();
4215 Editor::maximise_editing_space ()
4221 Gtk::Window* toplevel = current_toplevel();
4224 toplevel->fullscreen ();
4230 Editor::restore_editing_space ()
4236 Gtk::Window* toplevel = current_toplevel();
4239 toplevel->unfullscreen();
4245 * Make new playlists for a given track and also any others that belong
4246 * to the same active route group with the `select' property.
4251 Editor::new_playlists (TimeAxisView* v)
4253 begin_reversible_command (_("new playlists"));
4254 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4255 _session->playlists->get (playlists);
4256 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4257 commit_reversible_command ();
4261 * Use a copy of the current playlist for a given track and also any others that belong
4262 * to the same active route group with the `select' property.
4267 Editor::copy_playlists (TimeAxisView* v)
4269 begin_reversible_command (_("copy playlists"));
4270 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4271 _session->playlists->get (playlists);
4272 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4273 commit_reversible_command ();
4276 /** Clear the current playlist for a given track and also any others that belong
4277 * to the same active route group with the `select' property.
4282 Editor::clear_playlists (TimeAxisView* v)
4284 begin_reversible_command (_("clear playlists"));
4285 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4286 _session->playlists->get (playlists);
4287 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4288 commit_reversible_command ();
4292 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4294 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4298 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4300 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4304 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4306 atv.clear_playlist ();
4310 Editor::get_y_origin () const
4312 return vertical_adjustment.get_value ();
4315 /** Queue up a change to the viewport x origin.
4316 * @param frame New x origin.
4319 Editor::reset_x_origin (framepos_t frame)
4321 pending_visual_change.add (VisualChange::TimeOrigin);
4322 pending_visual_change.time_origin = frame;
4323 ensure_visual_change_idle_handler ();
4327 Editor::reset_y_origin (double y)
4329 pending_visual_change.add (VisualChange::YOrigin);
4330 pending_visual_change.y_origin = y;
4331 ensure_visual_change_idle_handler ();
4335 Editor::reset_zoom (framecnt_t spp)
4337 if (spp == samples_per_pixel) {
4341 pending_visual_change.add (VisualChange::ZoomLevel);
4342 pending_visual_change.samples_per_pixel = spp;
4343 ensure_visual_change_idle_handler ();
4347 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4349 reset_x_origin (frame);
4352 if (!no_save_visual) {
4353 undo_visual_stack.push_back (current_visual_state(false));
4357 Editor::VisualState::VisualState (bool with_tracks)
4358 : gui_state (with_tracks ? new GUIObjectState : 0)
4362 Editor::VisualState::~VisualState ()
4367 Editor::VisualState*
4368 Editor::current_visual_state (bool with_tracks)
4370 VisualState* vs = new VisualState (with_tracks);
4371 vs->y_position = vertical_adjustment.get_value();
4372 vs->samples_per_pixel = samples_per_pixel;
4373 vs->leftmost_frame = leftmost_frame;
4374 vs->zoom_focus = zoom_focus;
4377 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4384 Editor::undo_visual_state ()
4386 if (undo_visual_stack.empty()) {
4390 VisualState* vs = undo_visual_stack.back();
4391 undo_visual_stack.pop_back();
4394 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4397 use_visual_state (*vs);
4402 Editor::redo_visual_state ()
4404 if (redo_visual_stack.empty()) {
4408 VisualState* vs = redo_visual_stack.back();
4409 redo_visual_stack.pop_back();
4411 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4412 // why do we check here?
4413 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4416 use_visual_state (*vs);
4421 Editor::swap_visual_state ()
4423 if (undo_visual_stack.empty()) {
4424 redo_visual_state ();
4426 undo_visual_state ();
4431 Editor::use_visual_state (VisualState& vs)
4433 PBD::Unwinder<bool> nsv (no_save_visual, true);
4434 DisplaySuspender ds;
4436 vertical_adjustment.set_value (vs.y_position);
4438 set_zoom_focus (vs.zoom_focus);
4439 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4442 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4444 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4445 (*i)->clear_property_cache();
4446 (*i)->reset_visual_state ();
4450 _routes->update_visibility ();
4453 /** This is the core function that controls the zoom level of the canvas. It is called
4454 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4455 * @param spp new number of samples per pixel
4458 Editor::set_samples_per_pixel (framecnt_t spp)
4464 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4465 const framecnt_t lots_of_pixels = 4000;
4467 /* if the zoom level is greater than what you'd get trying to display 3
4468 * days of audio on a really big screen, then it's too big.
4471 if (spp * lots_of_pixels > three_days) {
4475 samples_per_pixel = spp;
4478 tempo_lines->tempo_map_changed();
4481 bool const showing_time_selection = selection->time.length() > 0;
4483 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4484 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4485 (*i)->reshow_selection (selection->time);
4489 ZoomChanged (); /* EMIT_SIGNAL */
4491 ArdourCanvas::GtkCanvasViewport* c;
4493 c = get_track_canvas();
4495 c->canvas()->zoomed ();
4498 if (playhead_cursor) {
4499 playhead_cursor->set_position (playhead_cursor->current_frame ());
4502 refresh_location_display();
4503 _summary->set_overlays_dirty ();
4505 update_marker_labels ();
4511 Editor::queue_visual_videotimeline_update ()
4514 * pending_visual_change.add (VisualChange::VideoTimeline);
4515 * or maybe even more specific: which videotimeline-image
4516 * currently it calls update_video_timeline() to update
4517 * _all outdated_ images on the video-timeline.
4518 * see 'exposeimg()' in video_image_frame.cc
4520 ensure_visual_change_idle_handler ();
4524 Editor::ensure_visual_change_idle_handler ()
4526 if (pending_visual_change.idle_handler_id < 0) {
4527 // see comment in add_to_idle_resize above.
4528 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4529 pending_visual_change.being_handled = false;
4534 Editor::_idle_visual_changer (void* arg)
4536 return static_cast<Editor*>(arg)->idle_visual_changer ();
4540 Editor::idle_visual_changer ()
4542 /* set_horizontal_position() below (and maybe other calls) call
4543 gtk_main_iteration(), so it's possible that a signal will be handled
4544 half-way through this method. If this signal wants an
4545 idle_visual_changer we must schedule another one after this one, so
4546 mark the idle_handler_id as -1 here to allow that. Also make a note
4547 that we are doing the visual change, so that changes in response to
4548 super-rapid-screen-update can be dropped if we are still processing
4552 pending_visual_change.idle_handler_id = -1;
4553 pending_visual_change.being_handled = true;
4555 VisualChange vc = pending_visual_change;
4557 pending_visual_change.pending = (VisualChange::Type) 0;
4559 visual_changer (vc);
4561 pending_visual_change.being_handled = false;
4563 return 0; /* this is always a one-shot call */
4567 Editor::visual_changer (const VisualChange& vc)
4569 double const last_time_origin = horizontal_position ();
4571 if (vc.pending & VisualChange::ZoomLevel) {
4572 set_samples_per_pixel (vc.samples_per_pixel);
4574 compute_fixed_ruler_scale ();
4576 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4577 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4579 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4580 current_bbt_points_begin, current_bbt_points_end);
4581 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4582 current_bbt_points_begin, current_bbt_points_end);
4583 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4585 update_video_timeline();
4588 if (vc.pending & VisualChange::TimeOrigin) {
4589 set_horizontal_position (vc.time_origin / samples_per_pixel);
4592 if (vc.pending & VisualChange::YOrigin) {
4593 vertical_adjustment.set_value (vc.y_origin);
4596 if (last_time_origin == horizontal_position ()) {
4597 /* changed signal not emitted */
4598 update_fixed_rulers ();
4599 redisplay_tempo (true);
4602 if (!(vc.pending & VisualChange::ZoomLevel)) {
4603 update_video_timeline();
4606 _summary->set_overlays_dirty ();
4609 struct EditorOrderTimeAxisSorter {
4610 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4611 return a->order () < b->order ();
4616 Editor::sort_track_selection (TrackViewList& sel)
4618 EditorOrderTimeAxisSorter cmp;
4623 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4626 framepos_t where = 0;
4627 EditPoint ep = _edit_point;
4629 if (Profile->get_mixbus())
4630 if (ep == EditAtSelectedMarker)
4631 ep = EditAtPlayhead;
4633 if (from_outside_canvas && (ep == EditAtMouse)) {
4634 ep = EditAtPlayhead;
4635 } else if (from_context_menu && (ep == EditAtMouse)) {
4636 return canvas_event_sample (&context_click_event, 0, 0);
4639 if (entered_marker) {
4640 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4641 return entered_marker->position();
4644 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4645 ep = EditAtSelectedMarker;
4648 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4649 ep = EditAtPlayhead;
4653 case EditAtPlayhead:
4654 if (_dragging_playhead) {
4655 where = *_control_scroll_target;
4657 where = _session->audible_frame();
4659 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4662 case EditAtSelectedMarker:
4663 if (!selection->markers.empty()) {
4665 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4668 where = loc->start();
4672 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4680 if (!mouse_frame (where, ignored)) {
4681 /* XXX not right but what can we do ? */
4685 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4693 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4695 if (!_session) return;
4697 begin_reversible_command (cmd);
4701 if ((tll = transport_loop_location()) == 0) {
4702 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4703 XMLNode &before = _session->locations()->get_state();
4704 _session->locations()->add (loc, true);
4705 _session->set_auto_loop_location (loc);
4706 XMLNode &after = _session->locations()->get_state();
4707 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4709 XMLNode &before = tll->get_state();
4710 tll->set_hidden (false, this);
4711 tll->set (start, end);
4712 XMLNode &after = tll->get_state();
4713 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4716 commit_reversible_command ();
4720 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4722 if (!_session) return;
4724 begin_reversible_command (cmd);
4728 if ((tpl = transport_punch_location()) == 0) {
4729 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4730 XMLNode &before = _session->locations()->get_state();
4731 _session->locations()->add (loc, true);
4732 _session->set_auto_punch_location (loc);
4733 XMLNode &after = _session->locations()->get_state();
4734 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4736 XMLNode &before = tpl->get_state();
4737 tpl->set_hidden (false, this);
4738 tpl->set (start, end);
4739 XMLNode &after = tpl->get_state();
4740 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4743 commit_reversible_command ();
4746 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4747 * @param rs List to which found regions are added.
4748 * @param where Time to look at.
4749 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4752 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4754 const TrackViewList* tracks;
4757 tracks = &track_views;
4762 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4764 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4767 boost::shared_ptr<Track> tr;
4768 boost::shared_ptr<Playlist> pl;
4770 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4772 boost::shared_ptr<RegionList> regions = pl->regions_at (
4773 (framepos_t) floor ( (double) where * tr->speed()));
4775 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4776 RegionView* rv = rtv->view()->find_view (*i);
4787 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4789 const TrackViewList* tracks;
4792 tracks = &track_views;
4797 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4798 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4800 boost::shared_ptr<Track> tr;
4801 boost::shared_ptr<Playlist> pl;
4803 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4805 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4806 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4808 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4810 RegionView* rv = rtv->view()->find_view (*i);
4821 /** Get regions using the following method:
4823 * Make a region list using:
4824 * (a) any selected regions
4825 * (b) the intersection of any selected tracks and the edit point(*)
4826 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4828 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4830 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4834 Editor::get_regions_from_selection_and_edit_point ()
4836 RegionSelection regions;
4838 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4839 regions.add (entered_regionview);
4841 regions = selection->regions;
4844 if ( regions.empty() ) {
4845 TrackViewList tracks = selection->tracks;
4847 if (!tracks.empty()) {
4848 /* no region selected or entered, but some selected tracks:
4849 * act on all regions on the selected tracks at the edit point
4851 framepos_t const where = get_preferred_edit_position ();
4852 get_regions_at(regions, where, tracks);
4859 /** Get regions using the following method:
4861 * Make a region list using:
4862 * (a) any selected regions
4863 * (b) the intersection of any selected tracks and the edit point(*)
4864 * (c) if neither exists, then whatever region is under the mouse
4866 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4868 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4871 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4873 RegionSelection regions;
4875 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4876 regions.add (entered_regionview);
4878 regions = selection->regions;
4881 if ( regions.empty() ) {
4882 TrackViewList tracks = selection->tracks;
4884 if (!tracks.empty()) {
4885 /* no region selected or entered, but some selected tracks:
4886 * act on all regions on the selected tracks at the edit point
4888 get_regions_at(regions, pos, tracks);
4895 /** Start with regions that are selected, or the entered regionview if none are selected.
4896 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4897 * of the regions that we started with.
4901 Editor::get_regions_from_selection_and_entered ()
4903 RegionSelection regions = selection->regions;
4905 if (regions.empty() && entered_regionview) {
4906 regions.add (entered_regionview);
4913 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4915 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4916 RouteTimeAxisView* rtav;
4918 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4919 boost::shared_ptr<Playlist> pl;
4920 std::vector<boost::shared_ptr<Region> > results;
4921 boost::shared_ptr<Track> tr;
4923 if ((tr = rtav->track()) == 0) {
4928 if ((pl = (tr->playlist())) != 0) {
4929 boost::shared_ptr<Region> r = pl->region_by_id (id);
4931 RegionView* rv = rtav->view()->find_view (r);
4933 regions.push_back (rv);
4942 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4945 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4946 MidiTimeAxisView* mtav;
4948 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4950 mtav->get_per_region_note_selection (selection);
4957 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4959 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4961 RouteTimeAxisView* tatv;
4963 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4965 boost::shared_ptr<Playlist> pl;
4966 vector<boost::shared_ptr<Region> > results;
4968 boost::shared_ptr<Track> tr;
4970 if ((tr = tatv->track()) == 0) {
4975 if ((pl = (tr->playlist())) != 0) {
4976 if (src_comparison) {
4977 pl->get_source_equivalent_regions (region, results);
4979 pl->get_region_list_equivalent_regions (region, results);
4983 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4984 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4985 regions.push_back (marv);
4994 Editor::show_rhythm_ferret ()
4996 if (rhythm_ferret == 0) {
4997 rhythm_ferret = new RhythmFerret(*this);
5000 rhythm_ferret->set_session (_session);
5001 rhythm_ferret->show ();
5002 rhythm_ferret->present ();
5006 Editor::first_idle ()
5008 MessageDialog* dialog = 0;
5010 if (track_views.size() > 1) {
5011 Timers::TimerSuspender t;
5012 dialog = new MessageDialog (
5013 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5017 ARDOUR_UI::instance()->flush_pending ();
5020 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5024 // first idle adds route children (automation tracks), so we need to redisplay here
5025 _routes->redisplay ();
5029 if (_session->undo_depth() == 0) {
5030 undo_action->set_sensitive(false);
5032 redo_action->set_sensitive(false);
5033 begin_selection_op_history ();
5039 Editor::_idle_resize (gpointer arg)
5041 return ((Editor*)arg)->idle_resize ();
5045 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5047 if (resize_idle_id < 0) {
5048 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5049 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5050 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5052 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5053 _pending_resize_amount = 0;
5056 /* make a note of the smallest resulting height, so that we can clamp the
5057 lower limit at TimeAxisView::hSmall */
5059 int32_t min_resulting = INT32_MAX;
5061 _pending_resize_amount += h;
5062 _pending_resize_view = view;
5064 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5066 if (selection->tracks.contains (_pending_resize_view)) {
5067 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5068 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5072 if (min_resulting < 0) {
5077 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5078 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5082 /** Handle pending resizing of tracks */
5084 Editor::idle_resize ()
5086 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5088 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5089 selection->tracks.contains (_pending_resize_view)) {
5091 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5092 if (*i != _pending_resize_view) {
5093 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5098 _pending_resize_amount = 0;
5099 _group_tabs->set_dirty ();
5100 resize_idle_id = -1;
5108 ENSURE_GUI_THREAD (*this, &Editor::located);
5111 playhead_cursor->set_position (_session->audible_frame ());
5112 if (_follow_playhead && !_pending_initial_locate) {
5113 reset_x_origin_to_follow_playhead ();
5117 _pending_locate_request = false;
5118 _pending_initial_locate = false;
5122 Editor::region_view_added (RegionView * rv)
5124 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5125 if (rv->region ()->id () == (*pr)) {
5126 selection->add (rv);
5127 selection->regions.pending.erase (pr);
5132 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5134 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5135 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5136 if (rv->region()->id () == (*rnote).first) {
5137 mrv->select_notes ((*rnote).second);
5138 selection->pending_midi_note_selection.erase(rnote);
5144 _summary->set_background_dirty ();
5148 Editor::region_view_removed ()
5150 _summary->set_background_dirty ();
5154 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5156 TrackViewList::const_iterator j = track_views.begin ();
5157 while (j != track_views.end()) {
5158 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5159 if (rtv && rtv->route() == r) {
5170 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5174 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5175 TimeAxisView* tv = axis_view_from_route (*i);
5185 Editor::suspend_route_redisplay ()
5188 _routes->suspend_redisplay();
5193 Editor::resume_route_redisplay ()
5196 _routes->redisplay(); // queue redisplay
5197 _routes->resume_redisplay();
5202 Editor::add_routes (RouteList& routes)
5204 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5206 RouteTimeAxisView *rtv;
5207 list<RouteTimeAxisView*> new_views;
5208 TrackViewList new_selection;
5209 bool from_scratch = (track_views.size() == 0);
5211 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5212 boost::shared_ptr<Route> route = (*x);
5214 if (route->is_auditioner() || route->is_monitor()) {
5218 DataType dt = route->input()->default_type();
5220 if (dt == ARDOUR::DataType::AUDIO) {
5221 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5222 rtv->set_route (route);
5223 } else if (dt == ARDOUR::DataType::MIDI) {
5224 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5225 rtv->set_route (route);
5227 throw unknown_type();
5230 new_views.push_back (rtv);
5231 track_views.push_back (rtv);
5232 new_selection.push_back (rtv);
5234 rtv->effective_gain_display ();
5236 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5237 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5240 if (new_views.size() > 0) {
5241 _routes->routes_added (new_views);
5242 _summary->routes_added (new_views);
5245 if (!from_scratch) {
5246 selection->tracks.clear();
5247 selection->add (new_selection);
5248 begin_selection_op_history();
5251 if (show_editor_mixer_when_tracks_arrive) {
5252 show_editor_mixer (true);
5255 editor_list_button.set_sensitive (true);
5259 Editor::timeaxisview_deleted (TimeAxisView *tv)
5261 if (tv == entered_track) {
5265 if (_session && _session->deletion_in_progress()) {
5266 /* the situation is under control */
5270 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5272 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5274 _routes->route_removed (tv);
5276 TimeAxisView::Children c = tv->get_child_list ();
5277 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5278 if (entered_track == i->get()) {
5283 /* remove it from the list of track views */
5285 TrackViewList::iterator i;
5287 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5288 i = track_views.erase (i);
5291 /* update whatever the current mixer strip is displaying, if revelant */
5293 boost::shared_ptr<Route> route;
5296 route = rtav->route ();
5299 if (current_mixer_strip && current_mixer_strip->route() == route) {
5301 TimeAxisView* next_tv;
5303 if (track_views.empty()) {
5305 } else if (i == track_views.end()) {
5306 next_tv = track_views.front();
5313 set_selected_mixer_strip (*next_tv);
5315 /* make the editor mixer strip go away setting the
5316 * button to inactive (which also unticks the menu option)
5319 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5325 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5327 if (apply_to_selection) {
5328 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5330 TrackSelection::iterator j = i;
5333 hide_track_in_display (*i, false);
5338 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5340 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5341 // this will hide the mixer strip
5342 set_selected_mixer_strip (*tv);
5345 _routes->hide_track_in_display (*tv);
5350 Editor::sync_track_view_list_and_routes ()
5352 track_views = TrackViewList (_routes->views ());
5354 _summary->set_background_dirty();
5355 _group_tabs->set_dirty ();
5357 return false; // do not call again (until needed)
5361 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5363 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5368 /** Find a RouteTimeAxisView by the ID of its route */
5370 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5372 RouteTimeAxisView* v;
5374 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5375 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5376 if(v->route()->id() == id) {
5386 Editor::fit_route_group (RouteGroup *g)
5388 TrackViewList ts = axis_views_from_routes (g->route_list ());
5393 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5395 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5398 _session->cancel_audition ();
5402 if (_session->is_auditioning()) {
5403 _session->cancel_audition ();
5404 if (r == last_audition_region) {
5409 _session->audition_region (r);
5410 last_audition_region = r;
5415 Editor::hide_a_region (boost::shared_ptr<Region> r)
5417 r->set_hidden (true);
5421 Editor::show_a_region (boost::shared_ptr<Region> r)
5423 r->set_hidden (false);
5427 Editor::audition_region_from_region_list ()
5429 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5433 Editor::hide_region_from_region_list ()
5435 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5439 Editor::show_region_in_region_list ()
5441 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5445 Editor::step_edit_status_change (bool yn)
5448 start_step_editing ();
5450 stop_step_editing ();
5455 Editor::start_step_editing ()
5457 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5461 Editor::stop_step_editing ()
5463 step_edit_connection.disconnect ();
5467 Editor::check_step_edit ()
5469 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5470 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5472 mtv->check_step_edit ();
5476 return true; // do it again, till we stop
5480 Editor::scroll_press (Direction dir)
5482 ++_scroll_callbacks;
5484 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5485 /* delay the first auto-repeat */
5491 scroll_backward (1);
5499 scroll_up_one_track ();
5503 scroll_down_one_track ();
5507 /* do hacky auto-repeat */
5508 if (!_scroll_connection.connected ()) {
5510 _scroll_connection = Glib::signal_timeout().connect (
5511 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5514 _scroll_callbacks = 0;
5521 Editor::scroll_release ()
5523 _scroll_connection.disconnect ();
5526 /** Queue a change for the Editor viewport x origin to follow the playhead */
5528 Editor::reset_x_origin_to_follow_playhead ()
5530 framepos_t const frame = playhead_cursor->current_frame ();
5532 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5534 if (_session->transport_speed() < 0) {
5536 if (frame > (current_page_samples() / 2)) {
5537 center_screen (frame-(current_page_samples()/2));
5539 center_screen (current_page_samples()/2);
5546 if (frame < leftmost_frame) {
5548 if (_session->transport_rolling()) {
5549 /* rolling; end up with the playhead at the right of the page */
5550 l = frame - current_page_samples ();
5552 /* not rolling: end up with the playhead 1/4 of the way along the page */
5553 l = frame - current_page_samples() / 4;
5557 if (_session->transport_rolling()) {
5558 /* rolling: end up with the playhead on the left of the page */
5561 /* not rolling: end up with the playhead 3/4 of the way along the page */
5562 l = frame - 3 * current_page_samples() / 4;
5570 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5576 Editor::super_rapid_screen_update ()
5578 if (!_session || !_session->engine().running()) {
5582 /* METERING / MIXER STRIPS */
5584 /* update track meters, if required */
5585 if (contents().is_mapped() && meters_running) {
5586 RouteTimeAxisView* rtv;
5587 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5588 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5589 rtv->fast_update ();
5594 /* and any current mixer strip */
5595 if (current_mixer_strip) {
5596 current_mixer_strip->fast_update ();
5599 /* PLAYHEAD AND VIEWPORT */
5601 framepos_t const frame = _session->audible_frame();
5603 /* There are a few reasons why we might not update the playhead / viewport stuff:
5605 * 1. we don't update things when there's a pending locate request, otherwise
5606 * when the editor requests a locate there is a chance that this method
5607 * will move the playhead before the locate request is processed, causing
5609 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5610 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5613 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5615 last_update_frame = frame;
5617 if (!_dragging_playhead) {
5618 playhead_cursor->set_position (frame);
5621 if (!_stationary_playhead) {
5623 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5624 /* We only do this if we aren't already
5625 handling a visual change (ie if
5626 pending_visual_change.being_handled is
5627 false) so that these requests don't stack
5628 up there are too many of them to handle in
5631 reset_x_origin_to_follow_playhead ();
5636 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5637 framepos_t const frame = playhead_cursor->current_frame ();
5638 double target = ((double)frame - (double)current_page_samples()/2.0);
5639 if (target <= 0.0) {
5642 // compare to EditorCursor::set_position()
5643 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5644 double const new_pos = sample_to_pixel_unrounded (target);
5645 if (rint (new_pos) != rint (old_pos)) {
5646 reset_x_origin (pixel_to_sample (floor (new_pos)));
5657 Editor::session_going_away ()
5659 _have_idled = false;
5661 _session_connections.drop_connections ();
5663 super_rapid_screen_update_connection.disconnect ();
5665 selection->clear ();
5666 cut_buffer->clear ();
5668 clicked_regionview = 0;
5669 clicked_axisview = 0;
5670 clicked_routeview = 0;
5671 entered_regionview = 0;
5673 last_update_frame = 0;
5676 playhead_cursor->hide ();
5678 /* rip everything out of the list displays */
5682 _route_groups->clear ();
5684 /* do this first so that deleting a track doesn't reset cms to null
5685 and thus cause a leak.
5688 if (current_mixer_strip) {
5689 if (current_mixer_strip->get_parent() != 0) {
5690 global_hpacker.remove (*current_mixer_strip);
5692 delete current_mixer_strip;
5693 current_mixer_strip = 0;
5696 /* delete all trackviews */
5698 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5701 track_views.clear ();
5703 nudge_clock->set_session (0);
5705 editor_list_button.set_active(false);
5706 editor_list_button.set_sensitive(false);
5708 /* clear tempo/meter rulers */
5709 remove_metric_marks ();
5711 clear_marker_display ();
5713 stop_step_editing ();
5717 /* get rid of any existing editor mixer strip */
5719 WindowTitle title(Glib::get_application_name());
5720 title += _("Editor");
5722 own_window()->set_title (title.get_string());
5725 SessionHandlePtr::session_going_away ();
5729 Editor::manage_action_scripts ()
5731 ARDOUR_UI::instance()->lua_script_manager();
5735 Editor::trigger_script (int i)
5737 LuaInstance::instance()-> call_action (i);
5741 Editor::set_script_action_name (int i, const std::string& n)
5743 string const a = string_compose (X_("script-action-%1"), i + 1);
5744 Glib::RefPtr<Action> act = ActionManager::get_action(X_("Editor"), a.c_str());
5747 act->set_label (string_compose (_("Unset #%1"), i + 1));
5754 Editor::show_editor_list (bool yn)
5757 _the_notebook.show ();
5759 _the_notebook.hide ();
5764 Editor::change_region_layering_order (bool from_context_menu)
5766 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5768 if (!clicked_routeview) {
5769 if (layering_order_editor) {
5770 layering_order_editor->hide ();
5775 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5781 boost::shared_ptr<Playlist> pl = track->playlist();
5787 if (layering_order_editor == 0) {
5788 layering_order_editor = new RegionLayeringOrderEditor (*this);
5791 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5792 layering_order_editor->maybe_present ();
5796 Editor::update_region_layering_order_editor ()
5798 if (layering_order_editor && layering_order_editor->is_visible ()) {
5799 change_region_layering_order (true);
5804 Editor::setup_fade_images ()
5806 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5807 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5808 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5809 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5810 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5812 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5813 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5814 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5815 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5816 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5818 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5819 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5820 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5821 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5822 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5824 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5825 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5826 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5827 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5828 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5832 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5834 Editor::action_menu_item (std::string const & name)
5836 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5839 return *manage (a->create_menu_item ());
5843 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5845 EventBox* b = manage (new EventBox);
5846 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5847 Label* l = manage (new Label (name));
5851 _the_notebook.append_page (widget, *b);
5855 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5857 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5858 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5861 if (ev->type == GDK_2BUTTON_PRESS) {
5863 /* double-click on a notebook tab shrinks or expands the notebook */
5865 if (_notebook_shrunk) {
5866 if (pre_notebook_shrink_pane_width) {
5867 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5869 _notebook_shrunk = false;
5871 pre_notebook_shrink_pane_width = edit_pane.get_position();
5873 /* this expands the LHS of the edit pane to cover the notebook
5874 PAGE but leaves the tabs visible.
5876 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5877 _notebook_shrunk = true;
5885 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5887 using namespace Menu_Helpers;
5889 MenuList& items = _control_point_context_menu.items ();
5892 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5893 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5894 if (!can_remove_control_point (item)) {
5895 items.back().set_sensitive (false);
5898 _control_point_context_menu.popup (event->button.button, event->button.time);
5902 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5904 using namespace Menu_Helpers;
5906 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5911 /* We need to get the selection here and pass it to the operations, since
5912 popping up the menu will cause a region leave event which clears
5913 entered_regionview. */
5915 MidiRegionView& mrv = note->region_view();
5916 const RegionSelection rs = get_regions_from_selection_and_entered ();
5917 const uint32_t sel_size = mrv.selection_size ();
5919 MenuList& items = _note_context_menu.items();
5923 items.push_back(MenuElem(_("Delete"),
5924 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5927 items.push_back(MenuElem(_("Edit..."),
5928 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5929 if (sel_size != 1) {
5930 items.back().set_sensitive (false);
5933 items.push_back(MenuElem(_("Transpose..."),
5934 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5937 items.push_back(MenuElem(_("Legatize"),
5938 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5940 items.back().set_sensitive (false);
5943 items.push_back(MenuElem(_("Quantize..."),
5944 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5946 items.push_back(MenuElem(_("Remove Overlap"),
5947 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5949 items.back().set_sensitive (false);
5952 items.push_back(MenuElem(_("Transform..."),
5953 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5955 _note_context_menu.popup (event->button.button, event->button.time);
5959 Editor::zoom_vertical_modifier_released()
5961 _stepping_axis_view = 0;
5965 Editor::ui_parameter_changed (string parameter)
5967 if (parameter == "icon-set") {
5968 while (!_cursor_stack.empty()) {
5969 _cursor_stack.pop_back();
5971 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5972 _cursor_stack.push_back(_cursors->grabber);
5973 } else if (parameter == "draggable-playhead") {
5974 if (_verbose_cursor) {
5975 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5981 Editor::use_own_window (bool and_fill_it)
5983 bool new_window = !own_window();
5985 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5987 if (win && new_window) {
5988 win->set_name ("EditorWindow");
5990 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5992 // win->signal_realize().connect (*this, &Editor::on_realize);
5993 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
5994 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
5995 win->set_data ("ardour-bindings", bindings);
6000 DisplaySuspender ds;
6001 contents().show_all ();
6003 /* XXX: this is a bit unfortunate; it would probably
6004 be nicer if we could just call show () above rather
6005 than needing the show_all ()
6008 /* re-hide stuff if necessary */
6009 editor_list_button_toggled ();
6010 parameter_changed ("show-summary");
6011 parameter_changed ("show-group-tabs");
6012 parameter_changed ("show-zoom-tools");
6014 /* now reset all audio_time_axis heights, because widgets might need
6020 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6021 tv = (static_cast<TimeAxisView*>(*i));
6022 tv->reset_height ();
6025 if (current_mixer_strip) {
6026 current_mixer_strip->hide_things ();
6027 current_mixer_strip->parameter_changed ("mixer-element-visibility");