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/tearoff.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/audio_track.h"
69 #include "ardour/audioengine.h"
70 #include "ardour/audioregion.h"
71 #include "ardour/lmath.h"
72 #include "ardour/location.h"
73 #include "ardour/profile.h"
74 #include "ardour/route_group.h"
75 #include "ardour/session_playlists.h"
76 #include "ardour/tempo.h"
77 #include "ardour/utils.h"
79 #include "canvas/debug.h"
80 #include "canvas/text.h"
82 #include "control_protocol/control_protocol.h"
85 #include "analysis_window.h"
86 #include "audio_clock.h"
87 #include "audio_region_view.h"
88 #include "audio_streamview.h"
89 #include "audio_time_axis.h"
90 #include "automation_time_axis.h"
91 #include "bundle_manager.h"
92 #include "crossfade_edit.h"
96 #include "editor_cursors.h"
97 #include "editor_drag.h"
98 #include "editor_group_tabs.h"
99 #include "editor_locations.h"
100 #include "editor_regions.h"
101 #include "editor_route_groups.h"
102 #include "editor_routes.h"
103 #include "editor_snapshots.h"
104 #include "editor_summary.h"
105 #include "global_port_matrix.h"
106 #include "gui_object.h"
107 #include "gui_thread.h"
108 #include "keyboard.h"
110 #include "midi_region_view.h"
111 #include "midi_time_axis.h"
112 #include "mixer_strip.h"
113 #include "mixer_ui.h"
114 #include "mouse_cursors.h"
115 #include "note_base.h"
116 #include "playlist_selector.h"
117 #include "public_editor.h"
118 #include "quantize_dialog.h"
119 #include "region_layering_order_editor.h"
120 #include "rgb_macros.h"
121 #include "rhythm_ferret.h"
122 #include "selection.h"
124 #include "tempo_lines.h"
125 #include "time_axis_view.h"
127 #include "tooltips.h"
128 #include "ui_config.h"
130 #include "verbose_cursor.h"
135 using namespace ARDOUR;
136 using namespace ARDOUR_UI_UTILS;
139 using namespace Glib;
140 using namespace Gtkmm2ext;
141 using namespace Editing;
143 using PBD::internationalize;
145 using Gtkmm2ext::Keyboard;
147 double Editor::timebar_height = 15.0;
149 static const gchar *_snap_type_strings[] = {
183 static const gchar *_snap_mode_strings[] = {
190 static const gchar *_edit_point_strings[] = {
197 static const gchar *_edit_mode_strings[] = {
205 static const gchar *_zoom_focus_strings[] = {
215 #ifdef USE_RUBBERBAND
216 static const gchar *_rb_opt_strings[] = {
219 N_("Balanced multitimbral mixture"),
220 N_("Unpitched percussion with stable notes"),
221 N_("Crisp monophonic instrumental"),
222 N_("Unpitched solo percussion"),
223 N_("Resample without preserving pitch"),
228 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
231 pane_size_watcher (Paned* pane)
233 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
237 Quartz: impossible to access
239 so stop that by preventing it from ever getting too narrow. 35
240 pixels is basically a rough guess at the tab width.
245 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
247 gint pos = pane->get_position ();
249 if (pos > max_width_of_lhs) {
250 pane->set_position (max_width_of_lhs);
255 : PublicEditor (global_hpacker)
256 , editor_mixer_strip_width (Wide)
257 , constructed (false)
258 , _playlist_selector (0)
259 , no_save_visual (false)
261 , samples_per_pixel (2048)
262 , zoom_focus (ZoomFocusPlayhead)
263 , mouse_mode (MouseObject)
264 , pre_internal_snap_type (SnapToBeat)
265 , pre_internal_snap_mode (SnapOff)
266 , internal_snap_type (SnapToBeat)
267 , internal_snap_mode (SnapOff)
268 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
269 , _notebook_shrunk (false)
270 , location_marker_color (0)
271 , location_range_color (0)
272 , location_loop_color (0)
273 , location_punch_color (0)
274 , location_cd_marker_color (0)
276 , _show_marker_lines (false)
277 , clicked_axisview (0)
278 , clicked_routeview (0)
279 , clicked_regionview (0)
280 , clicked_selection (0)
281 , clicked_control_point (0)
282 , button_release_can_deselect (true)
283 , _mouse_changed_selection (false)
284 , region_edit_menu_split_item (0)
285 , region_edit_menu_split_multichannel_item (0)
286 , track_region_edit_playlist_menu (0)
287 , track_edit_playlist_submenu (0)
288 , track_selection_edit_playlist_submenu (0)
289 , _popup_region_menu_item (0)
290 , global_vpacker (key_bindings)
292 , _track_canvas_viewport (0)
293 , within_track_canvas (false)
294 , _verbose_cursor (0)
299 , range_marker_group (0)
300 , transport_marker_group (0)
301 , cd_marker_group (0)
302 , _time_markers_group (0)
303 , hv_scroll_group (0)
305 , cursor_scroll_group (0)
306 , no_scroll_group (0)
307 , _trackview_group (0)
308 , _drag_motion_group (0)
309 , _canvas_drop_zone (0)
310 , no_ruler_shown_update (false)
311 , ruler_grabbed_widget (0)
313 , minsec_mark_interval (0)
314 , minsec_mark_modulo (0)
316 , timecode_mark_modulo (0)
317 , timecode_nmarks (0)
318 , _samples_ruler_interval (0)
321 , bbt_bar_helper_on (0)
322 , bbt_accent_modulo (0)
327 , visible_timebars (0)
328 , editor_ruler_menu (0)
332 , range_marker_bar (0)
333 , transport_marker_bar (0)
335 , minsec_label (_("Mins:Secs"))
336 , bbt_label (_("Bars:Beats"))
337 , timecode_label (_("Timecode"))
338 , samples_label (_("Samples"))
339 , tempo_label (_("Tempo"))
340 , meter_label (_("Meter"))
341 , mark_label (_("Location Markers"))
342 , range_mark_label (_("Range Markers"))
343 , transport_mark_label (_("Loop/Punch Ranges"))
344 , cd_mark_label (_("CD Markers"))
345 , videotl_label (_("Video Timeline"))
347 , playhead_cursor (0)
348 , edit_packer (4, 4, true)
349 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
350 , horizontal_adjustment (0.0, 0.0, 1e16)
351 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
352 , controls_layout (unused_adjustment, vertical_adjustment)
353 , _scroll_callbacks (0)
354 , _visible_canvas_width (0)
355 , _visible_canvas_height (0)
356 , _full_canvas_height (0)
357 , edit_controls_left_menu (0)
358 , edit_controls_right_menu (0)
359 , last_update_frame (0)
360 , cut_buffer_start (0)
361 , cut_buffer_length (0)
362 , button_bindings (0)
366 , current_interthread_info (0)
367 , analysis_window (0)
368 , select_new_marker (false)
370 , scrubbing_direction (0)
371 , scrub_reversals (0)
372 , scrub_reverse_distance (0)
373 , have_pending_keyboard_selection (false)
374 , pending_keyboard_selection_start (0)
375 , _snap_type (SnapToBeat)
376 , _snap_mode (SnapOff)
377 , snap_threshold (5.0)
378 , ignore_gui_changes (false)
379 , _drags (new DragManager (this))
381 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
382 , _dragging_playhead (false)
383 , _dragging_edit_point (false)
384 , _show_measures (true)
385 , _follow_playhead (true)
386 , _stationary_playhead (false)
389 , global_rect_group (0)
390 , time_line_group (0)
391 , tempo_or_meter_marker_menu (0)
393 , range_marker_menu (0)
394 , transport_marker_menu (0)
395 , new_transport_marker_menu (0)
397 , marker_menu_item (0)
398 , bbt_beat_subdivision (4)
399 , _visible_track_count (-1)
400 , toolbar_selection_clock_table (2,3)
401 , _mouse_mode_tearoff (0)
402 , automation_mode_button (_("mode"))
405 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
406 , selection (new Selection (this))
407 , cut_buffer (new Selection (this))
408 , _selection_memento (new SelectionMemento())
409 , _all_region_actions_sensitized (false)
410 , _ignore_region_action (false)
411 , _last_region_menu_was_main (false)
412 , _ignore_follow_edits (false)
413 , cd_marker_bar_drag_rect (0)
414 , range_bar_drag_rect (0)
415 , transport_bar_drag_rect (0)
416 , transport_bar_range_rect (0)
417 , transport_bar_preroll_rect (0)
418 , transport_bar_postroll_rect (0)
419 , transport_loop_range_rect (0)
420 , transport_punch_range_rect (0)
421 , transport_punchin_line (0)
422 , transport_punchout_line (0)
423 , transport_preroll_rect (0)
424 , transport_postroll_rect (0)
426 , rubberband_rect (0)
432 , autoscroll_horizontal_allowed (false)
433 , autoscroll_vertical_allowed (false)
435 , autoscroll_widget (0)
436 , show_gain_after_trim (false)
437 , selection_op_cmd_depth (0)
438 , selection_op_history_it (0)
440 , current_mixer_strip (0)
441 , show_editor_mixer_when_tracks_arrive (false)
442 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
443 , current_stepping_trackview (0)
444 , last_track_height_step_timestamp (0)
446 , entered_regionview (0)
447 , clear_entered_track (false)
448 , _edit_point (EditAtMouse)
449 , meters_running (false)
451 , _have_idled (false)
452 , resize_idle_id (-1)
453 , _pending_resize_amount (0)
454 , _pending_resize_view (0)
455 , _pending_locate_request (false)
456 , _pending_initial_locate (false)
460 , layering_order_editor (0)
461 , _last_cut_copy_source_track (0)
462 , _region_selection_change_updates_region_list (true)
464 , _following_mixer_selection (false)
465 , _control_point_toggled_on_press (false)
466 , _stepping_axis_view (0)
467 , quantize_dialog (0)
468 , _main_menu_disabler (0)
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 = ARDOUR_UI::config()->color ("location marker");
500 location_range_color = ARDOUR_UI::config()->color ("location range");
501 location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker");
502 location_loop_color = ARDOUR_UI::config()->color ("location loop");
503 location_punch_color = ARDOUR_UI::config()->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 /* register actions now so that set_state() can find them and set toggles/checks etc */
752 /* when we start using our own keybinding system for the editor, this
753 * will be uncommented
759 _playlist_selector = new PlaylistSelector();
760 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
762 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
766 nudge_forward_button.set_name ("nudge button");
767 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
769 nudge_backward_button.set_name ("nudge button");
770 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
772 fade_context_menu.set_name ("ArdourContextMenu");
774 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
776 /* allow external control surfaces/protocols to do various things */
778 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
779 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
780 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
781 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
782 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
783 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
784 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
785 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
786 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
787 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
788 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
789 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
790 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
791 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
793 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
794 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
795 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
796 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
797 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
799 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
801 /* problematic: has to return a value and thus cannot be x-thread */
803 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
805 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
806 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
808 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
810 _ignore_region_action = false;
811 _last_region_menu_was_main = false;
812 _popup_region_menu_item = 0;
814 _ignore_follow_edits = false;
816 _show_marker_lines = false;
818 /* Button bindings */
820 button_bindings = new Bindings;
822 XMLNode* node = button_settings();
824 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
825 button_bindings->load (**i);
831 /* grab current parameter state */
832 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
833 UIConfiguration::instance().map_parameters (pc);
835 setup_fade_images ();
842 delete button_bindings;
844 delete _route_groups;
845 delete _track_canvas_viewport;
848 delete quantize_dialog;
854 delete _playlist_selector;
856 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
862 Editor::button_settings () const
864 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
865 XMLNode* node = find_named_node (*settings, X_("Buttons"));
868 node = new XMLNode (X_("Buttons"));
875 Editor::get_smart_mode () const
877 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
881 Editor::catch_vanishing_regionview (RegionView *rv)
883 /* note: the selection will take care of the vanishing
884 audioregionview by itself.
887 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
891 if (clicked_regionview == rv) {
892 clicked_regionview = 0;
895 if (entered_regionview == rv) {
896 set_entered_regionview (0);
899 if (!_all_region_actions_sensitized) {
900 sensitize_all_region_actions (true);
905 Editor::set_entered_regionview (RegionView* rv)
907 if (rv == entered_regionview) {
911 if (entered_regionview) {
912 entered_regionview->exited ();
915 entered_regionview = rv;
917 if (entered_regionview != 0) {
918 entered_regionview->entered ();
921 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
922 /* This RegionView entry might have changed what region actions
923 are allowed, so sensitize them all in case a key is pressed.
925 sensitize_all_region_actions (true);
930 Editor::set_entered_track (TimeAxisView* tav)
933 entered_track->exited ();
939 entered_track->entered ();
944 Editor::instant_save ()
946 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
951 _session->add_instant_xml(get_state());
953 Config->add_instant_xml(get_state());
958 Editor::control_vertical_zoom_in_all ()
960 tav_zoom_smooth (false, true);
964 Editor::control_vertical_zoom_out_all ()
966 tav_zoom_smooth (true, true);
970 Editor::control_vertical_zoom_in_selected ()
972 tav_zoom_smooth (false, false);
976 Editor::control_vertical_zoom_out_selected ()
978 tav_zoom_smooth (true, false);
982 Editor::control_view (uint32_t view)
984 goto_visual_state (view);
988 Editor::control_unselect ()
990 selection->clear_tracks ();
994 Editor::control_select (uint32_t rid, Selection::Operation op)
996 /* handles the (static) signal from the ControlProtocol class that
997 * requests setting the selected track to a given RID
1004 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1010 TimeAxisView* tav = axis_view_from_route (r);
1014 case Selection::Add:
1015 selection->add (tav);
1017 case Selection::Toggle:
1018 selection->toggle (tav);
1020 case Selection::Extend:
1022 case Selection::Set:
1023 selection->set (tav);
1027 selection->clear_tracks ();
1032 Editor::control_step_tracks_up ()
1034 scroll_tracks_up_line ();
1038 Editor::control_step_tracks_down ()
1040 scroll_tracks_down_line ();
1044 Editor::control_scroll (float fraction)
1046 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1052 double step = fraction * current_page_samples();
1055 _control_scroll_target is an optional<T>
1057 it acts like a pointer to an framepos_t, with
1058 a operator conversion to boolean to check
1059 that it has a value could possibly use
1060 playhead_cursor->current_frame to store the
1061 value and a boolean in the class to know
1062 when it's out of date
1065 if (!_control_scroll_target) {
1066 _control_scroll_target = _session->transport_frame();
1067 _dragging_playhead = true;
1070 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1071 *_control_scroll_target = 0;
1072 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1073 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1075 *_control_scroll_target += (framepos_t) trunc (step);
1078 /* move visuals, we'll catch up with it later */
1080 playhead_cursor->set_position (*_control_scroll_target);
1081 UpdateAllTransportClocks (*_control_scroll_target);
1083 if (*_control_scroll_target > (current_page_samples() / 2)) {
1084 /* try to center PH in window */
1085 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1091 Now we do a timeout to actually bring the session to the right place
1092 according to the playhead. This is to avoid reading disk buffers on every
1093 call to control_scroll, which is driven by ScrollTimeline and therefore
1094 probably by a control surface wheel which can generate lots of events.
1096 /* cancel the existing timeout */
1098 control_scroll_connection.disconnect ();
1100 /* add the next timeout */
1102 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1106 Editor::deferred_control_scroll (framepos_t /*target*/)
1108 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1109 // reset for next stream
1110 _control_scroll_target = boost::none;
1111 _dragging_playhead = false;
1116 Editor::access_action (std::string action_group, std::string action_item)
1122 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1125 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1133 Editor::on_realize ()
1137 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1138 start_lock_event_timing ();
1143 Editor::start_lock_event_timing ()
1145 /* check if we should lock the GUI every 30 seconds */
1147 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1151 Editor::generic_event_handler (GdkEvent* ev)
1154 case GDK_BUTTON_PRESS:
1155 case GDK_BUTTON_RELEASE:
1156 case GDK_MOTION_NOTIFY:
1158 case GDK_KEY_RELEASE:
1159 if (contents().is_mapped()) {
1160 gettimeofday (&last_event_time, 0);
1164 case GDK_LEAVE_NOTIFY:
1165 switch (ev->crossing.detail) {
1166 case GDK_NOTIFY_UNKNOWN:
1167 case GDK_NOTIFY_INFERIOR:
1168 case GDK_NOTIFY_ANCESTOR:
1170 case GDK_NOTIFY_VIRTUAL:
1171 case GDK_NOTIFY_NONLINEAR:
1172 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1173 /* leaving window, so reset focus, thus ending any and
1174 all text entry operations.
1189 Editor::lock_timeout_callback ()
1191 struct timeval now, delta;
1193 gettimeofday (&now, 0);
1195 timersub (&now, &last_event_time, &delta);
1197 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1199 /* don't call again. Returning false will effectively
1200 disconnect us from the timer callback.
1202 unlock() will call start_lock_event_timing() to get things
1212 Editor::map_position_change (framepos_t frame)
1214 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1216 if (_session == 0) {
1220 if (_follow_playhead) {
1221 center_screen (frame);
1224 playhead_cursor->set_position (frame);
1228 Editor::center_screen (framepos_t frame)
1230 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1232 /* if we're off the page, then scroll.
1235 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1236 center_screen_internal (frame, page);
1241 Editor::center_screen_internal (framepos_t frame, float page)
1246 frame -= (framepos_t) page;
1251 reset_x_origin (frame);
1256 Editor::update_title ()
1258 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1260 if (!own_window()) {
1265 bool dirty = _session->dirty();
1267 string session_name;
1269 if (_session->snap_name() != _session->name()) {
1270 session_name = _session->snap_name();
1272 session_name = _session->name();
1276 session_name = "*" + session_name;
1279 WindowTitle title(session_name);
1280 title += Glib::get_application_name();
1281 own_window()->set_title (title.get_string());
1283 /* ::session_going_away() will have taken care of it */
1288 Editor::set_session (Session *t)
1290 SessionHandlePtr::set_session (t);
1296 _playlist_selector->set_session (_session);
1297 nudge_clock->set_session (_session);
1298 _summary->set_session (_session);
1299 _group_tabs->set_session (_session);
1300 _route_groups->set_session (_session);
1301 _regions->set_session (_session);
1302 _snapshots->set_session (_session);
1303 _routes->set_session (_session);
1304 _locations->set_session (_session);
1306 if (rhythm_ferret) {
1307 rhythm_ferret->set_session (_session);
1310 if (analysis_window) {
1311 analysis_window->set_session (_session);
1315 sfbrowser->set_session (_session);
1318 compute_fixed_ruler_scale ();
1320 /* Make sure we have auto loop and auto punch ranges */
1322 Location* loc = _session->locations()->auto_loop_location();
1324 loc->set_name (_("Loop"));
1327 loc = _session->locations()->auto_punch_location();
1330 loc->set_name (_("Punch"));
1333 refresh_location_display ();
1335 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1336 the selected Marker; this needs the LocationMarker list to be available.
1338 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1340 cerr << "Editor - found state node " << node << endl;
1341 set_state (*node, Stateful::loading_state_version);
1343 /* catch up with the playhead */
1345 _session->request_locate (playhead_cursor->current_frame ());
1346 _pending_initial_locate = true;
1350 /* These signals can all be emitted by a non-GUI thread. Therefore the
1351 handlers for them must not attempt to directly interact with the GUI,
1352 but use PBD::Signal<T>::connect() which accepts an event loop
1353 ("context") where the handler will be asked to run.
1356 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1357 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1358 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1359 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1360 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1361 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1362 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1363 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1364 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1365 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1366 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1367 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1368 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1370 playhead_cursor->show ();
1372 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1373 Config->map_parameters (pc);
1374 _session->config.map_parameters (pc);
1376 restore_ruler_visibility ();
1377 //tempo_map_changed (PropertyChange (0));
1378 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1380 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1381 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1384 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1385 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1388 switch (_snap_type) {
1389 case SnapToRegionStart:
1390 case SnapToRegionEnd:
1391 case SnapToRegionSync:
1392 case SnapToRegionBoundary:
1393 build_region_boundary_cache ();
1400 /* register for undo history */
1401 _session->register_with_memento_command_factory(id(), this);
1402 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1404 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1406 start_updating_meters ();
1410 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1412 if (a->get_name() == "RegionMenu") {
1413 /* When the main menu's region menu is opened, we setup the actions so that they look right
1414 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1415 so we resensitize all region actions when the entered regionview or the region selection
1416 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1417 happens after the region context menu is opened. So we set a flag here, too.
1421 sensitize_the_right_region_actions ();
1422 _last_region_menu_was_main = true;
1427 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1429 using namespace Menu_Helpers;
1431 void (Editor::*emf)(FadeShape);
1432 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1435 images = &_xfade_in_images;
1436 emf = &Editor::set_fade_in_shape;
1438 images = &_xfade_out_images;
1439 emf = &Editor::set_fade_out_shape;
1444 _("Linear (for highly correlated material)"),
1445 *(*images)[FadeLinear],
1446 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1450 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1454 _("Constant power"),
1455 *(*images)[FadeConstantPower],
1456 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1459 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1464 *(*images)[FadeSymmetric],
1465 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1469 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1474 *(*images)[FadeSlow],
1475 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1478 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1483 *(*images)[FadeFast],
1484 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1487 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1490 /** Pop up a context menu for when the user clicks on a start crossfade */
1492 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1494 using namespace Menu_Helpers;
1495 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1500 MenuList& items (xfade_in_context_menu.items());
1503 if (arv->audio_region()->fade_in_active()) {
1504 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1506 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1509 items.push_back (SeparatorElem());
1510 fill_xfade_menu (items, true);
1512 xfade_in_context_menu.popup (button, time);
1515 /** Pop up a context menu for when the user clicks on an end crossfade */
1517 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1519 using namespace Menu_Helpers;
1520 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1525 MenuList& items (xfade_out_context_menu.items());
1528 if (arv->audio_region()->fade_out_active()) {
1529 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1531 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1534 items.push_back (SeparatorElem());
1535 fill_xfade_menu (items, false);
1537 xfade_out_context_menu.popup (button, time);
1541 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1543 using namespace Menu_Helpers;
1544 Menu* (Editor::*build_menu_function)();
1547 switch (item_type) {
1549 case RegionViewName:
1550 case RegionViewNameHighlight:
1551 case LeftFrameHandle:
1552 case RightFrameHandle:
1553 if (with_selection) {
1554 build_menu_function = &Editor::build_track_selection_context_menu;
1556 build_menu_function = &Editor::build_track_region_context_menu;
1561 if (with_selection) {
1562 build_menu_function = &Editor::build_track_selection_context_menu;
1564 build_menu_function = &Editor::build_track_context_menu;
1569 if (clicked_routeview->track()) {
1570 build_menu_function = &Editor::build_track_context_menu;
1572 build_menu_function = &Editor::build_track_bus_context_menu;
1577 /* probably shouldn't happen but if it does, we don't care */
1581 menu = (this->*build_menu_function)();
1582 menu->set_name ("ArdourContextMenu");
1584 /* now handle specific situations */
1586 switch (item_type) {
1588 case RegionViewName:
1589 case RegionViewNameHighlight:
1590 case LeftFrameHandle:
1591 case RightFrameHandle:
1592 if (!with_selection) {
1593 if (region_edit_menu_split_item) {
1594 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1595 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1597 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1600 if (region_edit_menu_split_multichannel_item) {
1601 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1602 region_edit_menu_split_multichannel_item->set_sensitive (true);
1604 region_edit_menu_split_multichannel_item->set_sensitive (false);
1617 /* probably shouldn't happen but if it does, we don't care */
1621 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1623 /* Bounce to disk */
1625 using namespace Menu_Helpers;
1626 MenuList& edit_items = menu->items();
1628 edit_items.push_back (SeparatorElem());
1630 switch (clicked_routeview->audio_track()->freeze_state()) {
1631 case AudioTrack::NoFreeze:
1632 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1635 case AudioTrack::Frozen:
1636 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1639 case AudioTrack::UnFrozen:
1640 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1646 if (item_type == StreamItem && clicked_routeview) {
1647 clicked_routeview->build_underlay_menu(menu);
1650 /* When the region menu is opened, we setup the actions so that they look right
1653 sensitize_the_right_region_actions ();
1654 _last_region_menu_was_main = false;
1656 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1657 menu->popup (button, time);
1661 Editor::build_track_context_menu ()
1663 using namespace Menu_Helpers;
1665 MenuList& edit_items = track_context_menu.items();
1668 add_dstream_context_items (edit_items);
1669 return &track_context_menu;
1673 Editor::build_track_bus_context_menu ()
1675 using namespace Menu_Helpers;
1677 MenuList& edit_items = track_context_menu.items();
1680 add_bus_context_items (edit_items);
1681 return &track_context_menu;
1685 Editor::build_track_region_context_menu ()
1687 using namespace Menu_Helpers;
1688 MenuList& edit_items = track_region_context_menu.items();
1691 /* we've just cleared the track region context menu, so the menu that these
1692 two items were on will have disappeared; stop them dangling.
1694 region_edit_menu_split_item = 0;
1695 region_edit_menu_split_multichannel_item = 0;
1697 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1700 boost::shared_ptr<Track> tr;
1701 boost::shared_ptr<Playlist> pl;
1703 if ((tr = rtv->track())) {
1704 add_region_context_items (edit_items, tr);
1708 add_dstream_context_items (edit_items);
1710 return &track_region_context_menu;
1714 Editor::analyze_region_selection ()
1716 if (analysis_window == 0) {
1717 analysis_window = new AnalysisWindow();
1720 analysis_window->set_session(_session);
1722 analysis_window->show_all();
1725 analysis_window->set_regionmode();
1726 analysis_window->analyze();
1728 analysis_window->present();
1732 Editor::analyze_range_selection()
1734 if (analysis_window == 0) {
1735 analysis_window = new AnalysisWindow();
1738 analysis_window->set_session(_session);
1740 analysis_window->show_all();
1743 analysis_window->set_rangemode();
1744 analysis_window->analyze();
1746 analysis_window->present();
1750 Editor::build_track_selection_context_menu ()
1752 using namespace Menu_Helpers;
1753 MenuList& edit_items = track_selection_context_menu.items();
1754 edit_items.clear ();
1756 add_selection_context_items (edit_items);
1757 // edit_items.push_back (SeparatorElem());
1758 // add_dstream_context_items (edit_items);
1760 return &track_selection_context_menu;
1764 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1766 using namespace Menu_Helpers;
1768 /* OK, stick the region submenu at the top of the list, and then add
1772 RegionSelection rs = get_regions_from_selection_and_entered ();
1774 string::size_type pos = 0;
1775 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1777 /* we have to hack up the region name because "_" has a special
1778 meaning for menu titles.
1781 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1782 menu_item_name.replace (pos, 1, "__");
1786 if (_popup_region_menu_item == 0) {
1787 _popup_region_menu_item = new MenuItem (menu_item_name);
1788 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1789 _popup_region_menu_item->show ();
1791 _popup_region_menu_item->set_label (menu_item_name);
1794 /* No latering allowed in later is higher layering model */
1795 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1796 if (act && Config->get_layer_model() == LaterHigher) {
1797 act->set_sensitive (false);
1799 act->set_sensitive (true);
1802 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1804 edit_items.push_back (*_popup_region_menu_item);
1805 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1806 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1808 edit_items.push_back (SeparatorElem());
1811 /** Add context menu items relevant to selection ranges.
1812 * @param edit_items List to add the items to.
1815 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1817 using namespace Menu_Helpers;
1819 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1820 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1822 edit_items.push_back (SeparatorElem());
1823 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1825 edit_items.push_back (SeparatorElem());
1826 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1828 edit_items.push_back (SeparatorElem());
1830 edit_items.push_back (
1832 _("Move Range Start to Previous Region Boundary"),
1833 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1837 edit_items.push_back (
1839 _("Move Range Start to Next Region Boundary"),
1840 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1844 edit_items.push_back (
1846 _("Move Range End to Previous Region Boundary"),
1847 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1851 edit_items.push_back (
1853 _("Move Range End to Next Region Boundary"),
1854 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1858 edit_items.push_back (SeparatorElem());
1859 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1860 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1862 edit_items.push_back (SeparatorElem());
1863 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1865 edit_items.push_back (SeparatorElem());
1866 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1867 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1868 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1870 edit_items.push_back (SeparatorElem());
1871 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1873 edit_items.push_back (SeparatorElem());
1874 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1875 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1877 edit_items.push_back (SeparatorElem());
1878 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1879 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1880 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1881 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1882 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1883 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1884 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1890 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1892 using namespace Menu_Helpers;
1896 Menu *play_menu = manage (new Menu);
1897 MenuList& play_items = play_menu->items();
1898 play_menu->set_name ("ArdourContextMenu");
1900 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1901 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1902 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1903 play_items.push_back (SeparatorElem());
1904 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1906 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1910 Menu *select_menu = manage (new Menu);
1911 MenuList& select_items = select_menu->items();
1912 select_menu->set_name ("ArdourContextMenu");
1914 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1915 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1916 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1917 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1918 select_items.push_back (SeparatorElem());
1919 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1920 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1921 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
1922 select_items.push_back (SeparatorElem());
1923 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
1924 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
1925 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1926 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1927 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1928 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1929 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1931 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1935 Menu *cutnpaste_menu = manage (new Menu);
1936 MenuList& cutnpaste_items = cutnpaste_menu->items();
1937 cutnpaste_menu->set_name ("ArdourContextMenu");
1939 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1940 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1941 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1943 cutnpaste_items.push_back (SeparatorElem());
1945 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1946 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1948 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1950 /* Adding new material */
1952 edit_items.push_back (SeparatorElem());
1953 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1954 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1958 Menu *nudge_menu = manage (new Menu());
1959 MenuList& nudge_items = nudge_menu->items();
1960 nudge_menu->set_name ("ArdourContextMenu");
1962 edit_items.push_back (SeparatorElem());
1963 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1964 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1965 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1966 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1968 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1972 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1974 using namespace Menu_Helpers;
1978 Menu *play_menu = manage (new Menu);
1979 MenuList& play_items = play_menu->items();
1980 play_menu->set_name ("ArdourContextMenu");
1982 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1983 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1984 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1988 Menu *select_menu = manage (new Menu);
1989 MenuList& select_items = select_menu->items();
1990 select_menu->set_name ("ArdourContextMenu");
1992 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1993 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1994 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1995 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1996 select_items.push_back (SeparatorElem());
1997 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
1998 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
1999 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2000 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2002 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2006 Menu *cutnpaste_menu = manage (new Menu);
2007 MenuList& cutnpaste_items = cutnpaste_menu->items();
2008 cutnpaste_menu->set_name ("ArdourContextMenu");
2010 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2011 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2012 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2014 Menu *nudge_menu = manage (new Menu());
2015 MenuList& nudge_items = nudge_menu->items();
2016 nudge_menu->set_name ("ArdourContextMenu");
2018 edit_items.push_back (SeparatorElem());
2019 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2020 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2021 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2022 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2024 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2028 Editor::snap_type() const
2034 Editor::snap_mode() const
2040 Editor::set_snap_to (SnapType st)
2042 unsigned int snap_ind = (unsigned int)st;
2044 if (internal_editing()) {
2045 internal_snap_type = st;
2047 pre_internal_snap_type = st;
2052 if (snap_ind > snap_type_strings.size() - 1) {
2054 _snap_type = (SnapType)snap_ind;
2057 string str = snap_type_strings[snap_ind];
2059 if (str != snap_type_selector.get_text()) {
2060 snap_type_selector.set_text (str);
2065 switch (_snap_type) {
2066 case SnapToBeatDiv128:
2067 case SnapToBeatDiv64:
2068 case SnapToBeatDiv32:
2069 case SnapToBeatDiv28:
2070 case SnapToBeatDiv24:
2071 case SnapToBeatDiv20:
2072 case SnapToBeatDiv16:
2073 case SnapToBeatDiv14:
2074 case SnapToBeatDiv12:
2075 case SnapToBeatDiv10:
2076 case SnapToBeatDiv8:
2077 case SnapToBeatDiv7:
2078 case SnapToBeatDiv6:
2079 case SnapToBeatDiv5:
2080 case SnapToBeatDiv4:
2081 case SnapToBeatDiv3:
2082 case SnapToBeatDiv2: {
2083 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2084 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2086 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2087 current_bbt_points_begin, current_bbt_points_end);
2088 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2089 current_bbt_points_begin, current_bbt_points_end);
2090 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2094 case SnapToRegionStart:
2095 case SnapToRegionEnd:
2096 case SnapToRegionSync:
2097 case SnapToRegionBoundary:
2098 build_region_boundary_cache ();
2106 redisplay_tempo (false);
2108 SnapChanged (); /* EMIT SIGNAL */
2112 Editor::set_snap_mode (SnapMode mode)
2114 string str = snap_mode_strings[(int)mode];
2116 if (internal_editing()) {
2117 internal_snap_mode = mode;
2119 pre_internal_snap_mode = mode;
2124 if (str != snap_mode_selector.get_text ()) {
2125 snap_mode_selector.set_text (str);
2132 Editor::set_edit_point_preference (EditPoint ep, bool force)
2134 bool changed = (_edit_point != ep);
2137 if (Profile->get_mixbus())
2138 if (ep == EditAtSelectedMarker)
2139 ep = EditAtPlayhead;
2141 string str = edit_point_strings[(int)ep];
2142 if (str != edit_point_selector.get_text ()) {
2143 edit_point_selector.set_text (str);
2146 update_all_enter_cursors();
2148 if (!force && !changed) {
2152 const char* action=NULL;
2154 switch (_edit_point) {
2155 case EditAtPlayhead:
2156 action = "edit-at-playhead";
2158 case EditAtSelectedMarker:
2159 action = "edit-at-marker";
2162 action = "edit-at-mouse";
2166 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2168 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2172 bool in_track_canvas;
2174 if (!mouse_frame (foo, in_track_canvas)) {
2175 in_track_canvas = false;
2178 reset_canvas_action_sensitivity (in_track_canvas);
2184 Editor::set_state (const XMLNode& node, int version)
2186 const XMLProperty* prop;
2189 Tabbable::set_state (node, version);
2191 if (_session && (prop = node.property ("playhead"))) {
2193 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2195 playhead_cursor->set_position (pos);
2197 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2198 playhead_cursor->set_position (0);
2201 playhead_cursor->set_position (0);
2204 if ((prop = node.property ("mixer-width"))) {
2205 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2208 if ((prop = node.property ("zoom-focus"))) {
2209 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2212 if ((prop = node.property ("zoom"))) {
2213 /* older versions of ardour used floating point samples_per_pixel */
2214 double f = PBD::atof (prop->value());
2215 reset_zoom (llrintf (f));
2217 reset_zoom (samples_per_pixel);
2220 if ((prop = node.property ("visible-track-count"))) {
2221 set_visible_track_count (PBD::atoi (prop->value()));
2224 if ((prop = node.property ("snap-to"))) {
2225 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2228 if ((prop = node.property ("snap-mode"))) {
2229 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2232 if ((prop = node.property ("internal-snap-to"))) {
2233 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2236 if ((prop = node.property ("internal-snap-mode"))) {
2237 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2240 if ((prop = node.property ("pre-internal-snap-to"))) {
2241 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2244 if ((prop = node.property ("pre-internal-snap-mode"))) {
2245 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2248 if ((prop = node.property ("mouse-mode"))) {
2249 MouseMode m = str2mousemode(prop->value());
2250 set_mouse_mode (m, true);
2252 set_mouse_mode (MouseObject, true);
2255 if ((prop = node.property ("left-frame")) != 0) {
2257 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2261 reset_x_origin (pos);
2265 if ((prop = node.property ("y-origin")) != 0) {
2266 reset_y_origin (atof (prop->value ()));
2269 if ((prop = node.property ("join-object-range"))) {
2270 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2271 bool yn = string_is_affirmative (prop->value());
2273 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2274 tact->set_active (!yn);
2275 tact->set_active (yn);
2277 set_mouse_mode(mouse_mode, true);
2280 if ((prop = node.property ("edit-point"))) {
2281 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2284 if ((prop = node.property ("show-measures"))) {
2285 bool yn = string_is_affirmative (prop->value());
2286 _show_measures = yn;
2289 if ((prop = node.property ("follow-playhead"))) {
2290 bool yn = string_is_affirmative (prop->value());
2291 set_follow_playhead (yn);
2294 if ((prop = node.property ("stationary-playhead"))) {
2295 bool yn = string_is_affirmative (prop->value());
2296 set_stationary_playhead (yn);
2299 if ((prop = node.property ("region-list-sort-type"))) {
2300 RegionListSortType st;
2301 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2304 if ((prop = node.property ("show-editor-mixer"))) {
2306 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2309 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2310 bool yn = string_is_affirmative (prop->value());
2312 /* do it twice to force the change */
2314 tact->set_active (!yn);
2315 tact->set_active (yn);
2318 if ((prop = node.property ("show-editor-list"))) {
2320 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2323 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2324 bool yn = string_is_affirmative (prop->value());
2326 /* do it twice to force the change */
2328 tact->set_active (!yn);
2329 tact->set_active (yn);
2332 if ((prop = node.property (X_("editor-list-page")))) {
2333 _the_notebook.set_current_page (atoi (prop->value ()));
2336 if ((prop = node.property (X_("show-marker-lines")))) {
2337 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2339 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2340 bool yn = string_is_affirmative (prop->value ());
2342 tact->set_active (!yn);
2343 tact->set_active (yn);
2346 XMLNodeList children = node.children ();
2347 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2348 selection->set_state (**i, Stateful::current_state_version);
2349 _regions->set_state (**i);
2352 if ((prop = node.property ("maximised"))) {
2353 bool yn = string_is_affirmative (prop->value());
2354 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2356 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2357 bool fs = tact && tact->get_active();
2359 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2363 if ((prop = node.property ("nudge-clock-value"))) {
2365 sscanf (prop->value().c_str(), "%" PRId64, &f);
2366 nudge_clock->set (f);
2368 nudge_clock->set_mode (AudioClock::Timecode);
2369 nudge_clock->set (_session->frame_rate() * 5, true);
2374 * Not all properties may have been in XML, but
2375 * those that are linked to a private variable may need changing
2380 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2382 yn = _show_measures;
2383 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2384 /* do it twice to force the change */
2385 tact->set_active (!yn);
2386 tact->set_active (yn);
2389 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2390 yn = _follow_playhead;
2392 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2393 if (tact->get_active() != yn) {
2394 tact->set_active (yn);
2398 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2399 yn = _stationary_playhead;
2401 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2402 if (tact->get_active() != yn) {
2403 tact->set_active (yn);
2412 Editor::get_state ()
2414 XMLNode* node = new XMLNode (X_("Editor"));
2417 id().print (buf, sizeof (buf));
2418 node->add_property ("id", buf);
2420 node->add_child_nocopy (Tabbable::get_state());
2422 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2423 node->add_property("edit-horizontal-pane-pos", string(buf));
2424 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2425 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2426 node->add_property("edit-vertical-pane-pos", string(buf));
2428 maybe_add_mixer_strip_width (*node);
2430 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2432 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2433 node->add_property ("zoom", buf);
2434 node->add_property ("snap-to", enum_2_string (_snap_type));
2435 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2436 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2437 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2438 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2439 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2440 node->add_property ("edit-point", enum_2_string (_edit_point));
2441 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2442 node->add_property ("visible-track-count", buf);
2444 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2445 node->add_property ("playhead", buf);
2446 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2447 node->add_property ("left-frame", buf);
2448 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2449 node->add_property ("y-origin", buf);
2451 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2452 node->add_property ("maximised", _maximised ? "yes" : "no");
2453 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2454 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2455 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2456 node->add_property ("mouse-mode", enum2str(mouse_mode));
2457 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2459 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2461 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2462 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2465 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2467 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2468 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2471 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2472 node->add_property (X_("editor-list-page"), buf);
2474 if (button_bindings) {
2475 XMLNode* bb = new XMLNode (X_("Buttons"));
2476 button_bindings->save (*bb);
2477 node->add_child_nocopy (*bb);
2480 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2482 node->add_child_nocopy (selection->get_state ());
2483 node->add_child_nocopy (_regions->get_state ());
2485 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2486 node->add_property ("nudge-clock-value", buf);
2491 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2492 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2494 * @return pair: TimeAxisView that y is over, layer index.
2496 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2497 * in stacked or expanded region display mode, otherwise 0.
2499 std::pair<TimeAxisView *, double>
2500 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2502 if (!trackview_relative_offset) {
2503 y -= _trackview_group->canvas_origin().y;
2507 return std::make_pair ( (TimeAxisView *) 0, 0);
2510 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2512 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2519 return std::make_pair ( (TimeAxisView *) 0, 0);
2522 /** Snap a position to the grid, if appropriate, taking into account current
2523 * grid settings and also the state of any snap modifier keys that may be pressed.
2524 * @param start Position to snap.
2525 * @param event Event to get current key modifier information from, or 0.
2528 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2530 if (!_session || !event) {
2534 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2535 if (_snap_mode == SnapOff) {
2536 snap_to_internal (start, direction, for_mark);
2539 if (_snap_mode != SnapOff) {
2540 snap_to_internal (start, direction, for_mark);
2541 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2542 /* SnapOff, but we pressed the snap_delta modifier */
2543 snap_to_internal (start, direction, for_mark);
2549 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2551 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2555 snap_to_internal (start, direction, for_mark, ensure_snap);
2559 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2561 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2562 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2564 switch (_snap_type) {
2565 case SnapToTimecodeFrame:
2566 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2567 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2568 /* start is already on a whole timecode frame, do nothing */
2569 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2570 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2572 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2576 case SnapToTimecodeSeconds:
2577 if (_session->config.get_timecode_offset_negative()) {
2578 start += _session->config.get_timecode_offset ();
2580 start -= _session->config.get_timecode_offset ();
2582 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2583 (start % one_timecode_second == 0)) {
2584 /* start is already on a whole second, do nothing */
2585 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2586 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2588 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2591 if (_session->config.get_timecode_offset_negative()) {
2592 start -= _session->config.get_timecode_offset ();
2594 start += _session->config.get_timecode_offset ();
2598 case SnapToTimecodeMinutes:
2599 if (_session->config.get_timecode_offset_negative()) {
2600 start += _session->config.get_timecode_offset ();
2602 start -= _session->config.get_timecode_offset ();
2604 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2605 (start % one_timecode_minute == 0)) {
2606 /* start is already on a whole minute, do nothing */
2607 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2608 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2610 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2612 if (_session->config.get_timecode_offset_negative()) {
2613 start -= _session->config.get_timecode_offset ();
2615 start += _session->config.get_timecode_offset ();
2619 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2620 abort(); /*NOTREACHED*/
2625 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2627 const framepos_t one_second = _session->frame_rate();
2628 const framepos_t one_minute = _session->frame_rate() * 60;
2629 framepos_t presnap = start;
2633 switch (_snap_type) {
2634 case SnapToTimecodeFrame:
2635 case SnapToTimecodeSeconds:
2636 case SnapToTimecodeMinutes:
2637 return timecode_snap_to_internal (start, direction, for_mark);
2640 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2641 start % (one_second/75) == 0) {
2642 /* start is already on a whole CD frame, do nothing */
2643 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2644 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2646 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2651 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2652 start % one_second == 0) {
2653 /* start is already on a whole second, do nothing */
2654 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2655 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2657 start = (framepos_t) floor ((double) start / one_second) * one_second;
2662 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2663 start % one_minute == 0) {
2664 /* start is already on a whole minute, do nothing */
2665 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2666 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2668 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2673 start = _session->tempo_map().round_to_bar (start, direction);
2677 start = _session->tempo_map().round_to_beat (start, direction);
2680 case SnapToBeatDiv128:
2681 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2683 case SnapToBeatDiv64:
2684 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2686 case SnapToBeatDiv32:
2687 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2689 case SnapToBeatDiv28:
2690 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2692 case SnapToBeatDiv24:
2693 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2695 case SnapToBeatDiv20:
2696 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2698 case SnapToBeatDiv16:
2699 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2701 case SnapToBeatDiv14:
2702 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2704 case SnapToBeatDiv12:
2705 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2707 case SnapToBeatDiv10:
2708 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2710 case SnapToBeatDiv8:
2711 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2713 case SnapToBeatDiv7:
2714 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2716 case SnapToBeatDiv6:
2717 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2719 case SnapToBeatDiv5:
2720 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2722 case SnapToBeatDiv4:
2723 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2725 case SnapToBeatDiv3:
2726 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2728 case SnapToBeatDiv2:
2729 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2737 _session->locations()->marks_either_side (start, before, after);
2739 if (before == max_framepos && after == max_framepos) {
2740 /* No marks to snap to, so just don't snap */
2742 } else if (before == max_framepos) {
2744 } else if (after == max_framepos) {
2746 } else if (before != max_framepos && after != max_framepos) {
2747 /* have before and after */
2748 if ((start - before) < (after - start)) {
2757 case SnapToRegionStart:
2758 case SnapToRegionEnd:
2759 case SnapToRegionSync:
2760 case SnapToRegionBoundary:
2761 if (!region_boundary_cache.empty()) {
2763 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2764 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2766 if (direction > 0) {
2767 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2769 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2772 if (next != region_boundary_cache.begin ()) {
2777 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2778 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2780 if (start > (p + n) / 2) {
2789 switch (_snap_mode) {
2799 if (presnap > start) {
2800 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2804 } else if (presnap < start) {
2805 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2811 /* handled at entry */
2819 Editor::setup_toolbar ()
2821 HBox* mode_box = manage(new HBox);
2822 mode_box->set_border_width (2);
2823 mode_box->set_spacing(2);
2825 HBox* mouse_mode_box = manage (new HBox);
2826 HBox* mouse_mode_hbox = manage (new HBox);
2827 VBox* mouse_mode_vbox = manage (new VBox);
2828 Alignment* mouse_mode_align = manage (new Alignment);
2830 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2831 mouse_mode_size_group->add_widget (smart_mode_button);
2832 mouse_mode_size_group->add_widget (mouse_move_button);
2833 mouse_mode_size_group->add_widget (mouse_cut_button);
2834 mouse_mode_size_group->add_widget (mouse_select_button);
2835 mouse_mode_size_group->add_widget (mouse_timefx_button);
2836 mouse_mode_size_group->add_widget (mouse_audition_button);
2837 mouse_mode_size_group->add_widget (mouse_draw_button);
2838 mouse_mode_size_group->add_widget (mouse_content_button);
2840 mouse_mode_size_group->add_widget (zoom_in_button);
2841 mouse_mode_size_group->add_widget (zoom_out_button);
2842 mouse_mode_size_group->add_widget (zoom_preset_selector);
2843 mouse_mode_size_group->add_widget (zoom_out_full_button);
2844 mouse_mode_size_group->add_widget (zoom_focus_selector);
2846 mouse_mode_size_group->add_widget (tav_shrink_button);
2847 mouse_mode_size_group->add_widget (tav_expand_button);
2848 mouse_mode_size_group->add_widget (visible_tracks_selector);
2850 mouse_mode_size_group->add_widget (snap_type_selector);
2851 mouse_mode_size_group->add_widget (snap_mode_selector);
2853 mouse_mode_size_group->add_widget (edit_point_selector);
2854 mouse_mode_size_group->add_widget (edit_mode_selector);
2856 mouse_mode_size_group->add_widget (*nudge_clock);
2857 mouse_mode_size_group->add_widget (nudge_forward_button);
2858 mouse_mode_size_group->add_widget (nudge_backward_button);
2860 mouse_mode_hbox->set_spacing (2);
2862 if (!ARDOUR::Profile->get_trx()) {
2863 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2866 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2867 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2869 if (!ARDOUR::Profile->get_mixbus()) {
2870 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2873 if (!ARDOUR::Profile->get_trx()) {
2874 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2875 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2876 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2877 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2880 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2882 mouse_mode_align->add (*mouse_mode_vbox);
2883 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2885 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2887 edit_mode_selector.set_name ("mouse mode button");
2889 if (!ARDOUR::Profile->get_trx()) {
2890 mode_box->pack_start (edit_mode_selector, false, false);
2892 mode_box->pack_start (*mouse_mode_box, false, false);
2894 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2895 _mouse_mode_tearoff->set_name ("MouseModeBase");
2896 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2898 if (Profile->get_sae() || Profile->get_mixbus() ) {
2899 _mouse_mode_tearoff->set_can_be_torn_off (false);
2902 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2903 &_mouse_mode_tearoff->tearoff_window()));
2904 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2905 &_mouse_mode_tearoff->tearoff_window(), 1));
2906 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2907 &_mouse_mode_tearoff->tearoff_window()));
2908 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2909 &_mouse_mode_tearoff->tearoff_window(), 1));
2913 _zoom_box.set_spacing (2);
2914 _zoom_box.set_border_width (2);
2918 zoom_preset_selector.set_name ("zoom button");
2919 zoom_preset_selector.set_image(::get_icon ("time_exp"));
2920 zoom_preset_selector.set_size_request (42, -1);
2922 zoom_in_button.set_name ("zoom button");
2923 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
2924 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2925 zoom_in_button.set_related_action (act);
2927 zoom_out_button.set_name ("zoom button");
2928 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
2929 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2930 zoom_out_button.set_related_action (act);
2932 zoom_out_full_button.set_name ("zoom button");
2933 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
2934 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2935 zoom_out_full_button.set_related_action (act);
2937 zoom_focus_selector.set_name ("zoom button");
2939 if (ARDOUR::Profile->get_mixbus()) {
2940 _zoom_box.pack_start (zoom_preset_selector, false, false);
2941 } else if (ARDOUR::Profile->get_trx()) {
2942 mode_box->pack_start (zoom_out_button, false, false);
2943 mode_box->pack_start (zoom_in_button, false, false);
2945 _zoom_box.pack_start (zoom_out_button, false, false);
2946 _zoom_box.pack_start (zoom_in_button, false, false);
2947 _zoom_box.pack_start (zoom_out_full_button, false, false);
2948 _zoom_box.pack_start (zoom_focus_selector, false, false);
2951 /* Track zoom buttons */
2952 visible_tracks_selector.set_name ("zoom button");
2953 if (Profile->get_mixbus()) {
2954 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2955 visible_tracks_selector.set_size_request (42, -1);
2957 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
2960 tav_expand_button.set_name ("zoom button");
2961 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
2962 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2963 tav_expand_button.set_related_action (act);
2965 tav_shrink_button.set_name ("zoom button");
2966 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
2967 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2968 tav_shrink_button.set_related_action (act);
2970 if (ARDOUR::Profile->get_mixbus()) {
2971 _zoom_box.pack_start (visible_tracks_selector);
2972 } else if (ARDOUR::Profile->get_trx()) {
2973 _zoom_box.pack_start (tav_shrink_button);
2974 _zoom_box.pack_start (tav_expand_button);
2976 _zoom_box.pack_start (visible_tracks_selector);
2977 _zoom_box.pack_start (tav_shrink_button);
2978 _zoom_box.pack_start (tav_expand_button);
2981 if (!ARDOUR::Profile->get_trx()) {
2982 _zoom_tearoff = manage (new TearOff (_zoom_box));
2984 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2985 &_zoom_tearoff->tearoff_window()));
2986 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2987 &_zoom_tearoff->tearoff_window(), 0));
2988 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2989 &_zoom_tearoff->tearoff_window()));
2990 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2991 &_zoom_tearoff->tearoff_window(), 0));
2994 if (Profile->get_sae() || Profile->get_mixbus() ) {
2995 _zoom_tearoff->set_can_be_torn_off (false);
2998 snap_box.set_spacing (2);
2999 snap_box.set_border_width (2);
3001 snap_type_selector.set_name ("mouse mode button");
3003 snap_mode_selector.set_name ("mouse mode button");
3005 edit_point_selector.set_name ("mouse mode button");
3007 snap_box.pack_start (snap_mode_selector, false, false);
3008 snap_box.pack_start (snap_type_selector, false, false);
3009 snap_box.pack_start (edit_point_selector, false, false);
3013 HBox *nudge_box = manage (new HBox);
3014 nudge_box->set_spacing (2);
3015 nudge_box->set_border_width (2);
3017 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3018 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3020 nudge_box->pack_start (nudge_backward_button, false, false);
3021 nudge_box->pack_start (nudge_forward_button, false, false);
3022 nudge_box->pack_start (*nudge_clock, false, false);
3025 /* Pack everything in... */
3027 HBox* hbox = manage (new HBox);
3028 hbox->set_spacing(2);
3030 _tools_tearoff = manage (new TearOff (*hbox));
3031 _tools_tearoff->set_name ("MouseModeBase");
3032 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3034 if (Profile->get_sae() || Profile->get_mixbus()) {
3035 _tools_tearoff->set_can_be_torn_off (false);
3038 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3039 &_tools_tearoff->tearoff_window()));
3040 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3041 &_tools_tearoff->tearoff_window(), 0));
3042 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3043 &_tools_tearoff->tearoff_window()));
3044 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3045 &_tools_tearoff->tearoff_window(), 0));
3047 toolbar_hbox.set_spacing (2);
3048 toolbar_hbox.set_border_width (1);
3050 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3051 if (!ARDOUR::Profile->get_trx()) {
3052 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3053 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3056 if (!ARDOUR::Profile->get_trx()) {
3057 hbox->pack_start (snap_box, false, false);
3058 hbox->pack_start (*nudge_box, false, false);
3060 hbox->pack_start (panic_box, false, false);
3064 toolbar_base.set_name ("ToolBarBase");
3065 toolbar_base.add (toolbar_hbox);
3067 _toolbar_viewport.add (toolbar_base);
3068 /* stick to the required height but allow width to vary if there's not enough room */
3069 _toolbar_viewport.set_size_request (1, -1);
3071 toolbar_frame.set_shadow_type (SHADOW_OUT);
3072 toolbar_frame.set_name ("BaseFrame");
3073 toolbar_frame.add (_toolbar_viewport);
3077 Editor::build_edit_point_menu ()
3079 using namespace Menu_Helpers;
3081 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3082 if(!Profile->get_mixbus())
3083 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3084 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3086 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3090 Editor::build_edit_mode_menu ()
3092 using namespace Menu_Helpers;
3094 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3095 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3096 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3097 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3099 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3103 Editor::build_snap_mode_menu ()
3105 using namespace Menu_Helpers;
3107 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3108 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3109 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3111 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3115 Editor::build_snap_type_menu ()
3117 using namespace Menu_Helpers;
3119 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3120 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3121 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3122 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3123 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3124 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3125 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3126 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3127 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3128 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3129 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3130 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3131 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3132 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3133 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3134 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3135 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3136 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3137 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3138 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3139 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3140 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3141 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3142 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3143 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3144 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3145 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3146 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3147 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3148 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3150 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3155 Editor::setup_tooltips ()
3157 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3158 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3159 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3160 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3161 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3162 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3163 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3164 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3165 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3166 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3167 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3168 set_tooltip (zoom_in_button, _("Zoom In"));
3169 set_tooltip (zoom_out_button, _("Zoom Out"));
3170 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3171 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3172 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3173 set_tooltip (tav_expand_button, _("Expand Tracks"));
3174 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3175 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3176 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3177 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3178 set_tooltip (edit_point_selector, _("Edit Point"));
3179 set_tooltip (edit_mode_selector, _("Edit Mode"));
3180 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3184 Editor::convert_drop_to_paths (
3185 vector<string>& paths,
3186 const RefPtr<Gdk::DragContext>& /*context*/,
3189 const SelectionData& data,
3193 if (_session == 0) {
3197 vector<string> uris = data.get_uris();
3201 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3202 are actually URI lists. So do it by hand.
3205 if (data.get_target() != "text/plain") {
3209 /* Parse the "uri-list" format that Nautilus provides,
3210 where each pathname is delimited by \r\n.
3212 THERE MAY BE NO NULL TERMINATING CHAR!!!
3215 string txt = data.get_text();
3219 p = (char *) malloc (txt.length() + 1);
3220 txt.copy (p, txt.length(), 0);
3221 p[txt.length()] = '\0';
3227 while (g_ascii_isspace (*p))
3231 while (*q && (*q != '\n') && (*q != '\r')) {
3238 while (q > p && g_ascii_isspace (*q))
3243 uris.push_back (string (p, q - p + 1));
3247 p = strchr (p, '\n');
3259 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3260 if ((*i).substr (0,7) == "file://") {
3261 paths.push_back (Glib::filename_from_uri (*i));
3269 Editor::new_tempo_section ()
3274 Editor::map_transport_state ()
3276 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3278 if (_session && _session->transport_stopped()) {
3279 have_pending_keyboard_selection = false;
3282 update_loop_range_view ();
3288 Editor::begin_selection_op_history ()
3290 selection_op_cmd_depth = 0;
3291 selection_op_history_it = 0;
3293 while(!selection_op_history.empty()) {
3294 delete selection_op_history.front();
3295 selection_op_history.pop_front();
3298 selection_undo_action->set_sensitive (false);
3299 selection_redo_action->set_sensitive (false);
3300 selection_op_history.push_front (&_selection_memento->get_state ());
3304 Editor::begin_reversible_selection_op (string name)
3307 //cerr << name << endl;
3308 /* begin/commit pairs can be nested */
3309 selection_op_cmd_depth++;
3314 Editor::commit_reversible_selection_op ()
3317 if (selection_op_cmd_depth == 1) {
3319 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3321 The user has undone some selection ops and then made a new one,
3322 making anything earlier in the list invalid.
3325 list<XMLNode *>::iterator it = selection_op_history.begin();
3326 list<XMLNode *>::iterator e_it = it;
3327 advance (e_it, selection_op_history_it);
3329 for ( ; it != e_it; ++it) {
3332 selection_op_history.erase (selection_op_history.begin(), e_it);
3335 selection_op_history.push_front (&_selection_memento->get_state ());
3336 selection_op_history_it = 0;
3338 selection_undo_action->set_sensitive (true);
3339 selection_redo_action->set_sensitive (false);
3342 if (selection_op_cmd_depth > 0) {
3343 selection_op_cmd_depth--;
3349 Editor::undo_selection_op ()
3352 selection_op_history_it++;
3354 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3355 if (n == selection_op_history_it) {
3356 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3357 selection_redo_action->set_sensitive (true);
3361 /* is there an earlier entry? */
3362 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3363 selection_undo_action->set_sensitive (false);
3369 Editor::redo_selection_op ()
3372 if (selection_op_history_it > 0) {
3373 selection_op_history_it--;
3376 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3377 if (n == selection_op_history_it) {
3378 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3379 selection_undo_action->set_sensitive (true);
3384 if (selection_op_history_it == 0) {
3385 selection_redo_action->set_sensitive (false);
3391 Editor::begin_reversible_command (string name)
3394 before.push_back (&_selection_memento->get_state ());
3395 _session->begin_reversible_command (name);
3400 Editor::begin_reversible_command (GQuark q)
3403 before.push_back (&_selection_memento->get_state ());
3404 _session->begin_reversible_command (q);
3409 Editor::abort_reversible_command ()
3412 while(!before.empty()) {
3413 delete before.front();
3416 _session->abort_reversible_command ();
3421 Editor::commit_reversible_command ()
3424 if (before.size() == 1) {
3425 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3426 redo_action->set_sensitive(false);
3427 undo_action->set_sensitive(true);
3428 begin_selection_op_history ();
3431 if (before.empty()) {
3432 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3437 _session->commit_reversible_command ();
3442 Editor::history_changed ()
3446 if (undo_action && _session) {
3447 if (_session->undo_depth() == 0) {
3448 label = S_("Command|Undo");
3450 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3452 undo_action->property_label() = label;
3455 if (redo_action && _session) {
3456 if (_session->redo_depth() == 0) {
3458 redo_action->set_sensitive (false);
3460 label = string_compose(_("Redo (%1)"), _session->next_redo());
3461 redo_action->set_sensitive (true);
3463 redo_action->property_label() = label;
3468 Editor::duplicate_range (bool with_dialog)
3472 RegionSelection rs = get_regions_from_selection_and_entered ();
3474 if ( selection->time.length() == 0 && rs.empty()) {
3480 ArdourDialog win (_("Duplicate"));
3481 Label label (_("Number of duplications:"));
3482 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3483 SpinButton spinner (adjustment, 0.0, 1);
3486 win.get_vbox()->set_spacing (12);
3487 win.get_vbox()->pack_start (hbox);
3488 hbox.set_border_width (6);
3489 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3491 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3492 place, visually. so do this by hand.
3495 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3496 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3497 spinner.grab_focus();
3503 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3504 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3505 win.set_default_response (RESPONSE_ACCEPT);
3507 spinner.grab_focus ();
3509 switch (win.run ()) {
3510 case RESPONSE_ACCEPT:
3516 times = adjustment.get_value();
3519 if ((current_mouse_mode() == Editing::MouseRange)) {
3520 if (selection->time.length()) {
3521 duplicate_selection (times);
3523 } else if (get_smart_mode()) {
3524 if (selection->time.length()) {
3525 duplicate_selection (times);
3527 duplicate_some_regions (rs, times);
3529 duplicate_some_regions (rs, times);
3534 Editor::set_edit_mode (EditMode m)
3536 Config->set_edit_mode (m);
3540 Editor::cycle_edit_mode ()
3542 switch (Config->get_edit_mode()) {
3544 if (Profile->get_sae()) {
3545 Config->set_edit_mode (Lock);
3547 Config->set_edit_mode (Ripple);
3552 Config->set_edit_mode (Lock);
3555 Config->set_edit_mode (Slide);
3561 Editor::edit_mode_selection_done ( EditMode m )
3563 Config->set_edit_mode ( m );
3567 Editor::snap_type_selection_done (SnapType snaptype)
3569 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3571 ract->set_active ();
3576 Editor::snap_mode_selection_done (SnapMode mode)
3578 RefPtr<RadioAction> ract = snap_mode_action (mode);
3581 ract->set_active (true);
3586 Editor::cycle_edit_point (bool with_marker)
3588 if(Profile->get_mixbus())
3589 with_marker = false;
3591 switch (_edit_point) {
3593 set_edit_point_preference (EditAtPlayhead);
3595 case EditAtPlayhead:
3597 set_edit_point_preference (EditAtSelectedMarker);
3599 set_edit_point_preference (EditAtMouse);
3602 case EditAtSelectedMarker:
3603 set_edit_point_preference (EditAtMouse);
3609 Editor::edit_point_selection_done (EditPoint ep)
3611 set_edit_point_preference ( ep );
3615 Editor::build_zoom_focus_menu ()
3617 using namespace Menu_Helpers;
3619 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3620 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3621 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3622 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3623 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3624 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3626 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3630 Editor::zoom_focus_selection_done ( ZoomFocus f )
3632 RefPtr<RadioAction> ract = zoom_focus_action (f);
3634 ract->set_active ();
3639 Editor::build_track_count_menu ()
3641 using namespace Menu_Helpers;
3643 if (!Profile->get_mixbus()) {
3644 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3645 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3646 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3647 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3648 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3649 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3650 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3651 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3652 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3653 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3654 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3655 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3656 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3658 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3659 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3660 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3661 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3662 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3663 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3664 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3665 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3666 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3667 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3669 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3670 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3671 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3672 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3673 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3674 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3675 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3676 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3677 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3678 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3679 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3684 Editor::set_zoom_preset (int64_t ms)
3687 temporal_zoom_session();
3691 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3692 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3696 Editor::set_visible_track_count (int32_t n)
3698 _visible_track_count = n;
3700 /* if the canvas hasn't really been allocated any size yet, just
3701 record the desired number of visible tracks and return. when canvas
3702 allocation happens, we will get called again and then we can do the
3706 if (_visible_canvas_height <= 1) {
3712 DisplaySuspender ds;
3714 if (_visible_track_count > 0) {
3715 h = trackviews_height() / _visible_track_count;
3716 std::ostringstream s;
3717 s << _visible_track_count;
3719 } else if (_visible_track_count == 0) {
3721 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3722 if ((*i)->marked_for_display()) {
3726 h = trackviews_height() / n;
3729 /* negative value means that the visible track count has
3730 been overridden by explicit track height changes.
3732 visible_tracks_selector.set_text (X_("*"));
3736 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3737 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3740 if (str != visible_tracks_selector.get_text()) {
3741 visible_tracks_selector.set_text (str);
3746 Editor::override_visible_track_count ()
3748 _visible_track_count = -1;
3749 visible_tracks_selector.set_text ( _("*") );
3753 Editor::edit_controls_button_release (GdkEventButton* ev)
3755 if (Keyboard::is_context_menu_event (ev)) {
3756 ARDOUR_UI::instance()->add_route (current_toplevel());
3757 } else if (ev->button == 1) {
3758 selection->clear_tracks ();
3765 Editor::mouse_select_button_release (GdkEventButton* ev)
3767 /* this handles just right-clicks */
3769 if (ev->button != 3) {
3777 Editor::set_zoom_focus (ZoomFocus f)
3779 string str = zoom_focus_strings[(int)f];
3781 if (str != zoom_focus_selector.get_text()) {
3782 zoom_focus_selector.set_text (str);
3785 if (zoom_focus != f) {
3792 Editor::cycle_zoom_focus ()
3794 switch (zoom_focus) {
3796 set_zoom_focus (ZoomFocusRight);
3798 case ZoomFocusRight:
3799 set_zoom_focus (ZoomFocusCenter);
3801 case ZoomFocusCenter:
3802 set_zoom_focus (ZoomFocusPlayhead);
3804 case ZoomFocusPlayhead:
3805 set_zoom_focus (ZoomFocusMouse);
3807 case ZoomFocusMouse:
3808 set_zoom_focus (ZoomFocusEdit);
3811 set_zoom_focus (ZoomFocusLeft);
3817 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3819 /* recover or initialize pane positions. do this here rather than earlier because
3820 we don't want the positions to change the child allocations, which they seem to do.
3826 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3835 XMLNode* geometry = find_named_node (*node, "geometry");
3837 if (which == static_cast<Paned*> (&edit_pane)) {
3839 if (done & Horizontal) {
3843 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3844 _notebook_shrunk = string_is_affirmative (prop->value ());
3847 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3848 /* initial allocation is 90% to canvas, 10% to notebook */
3849 pos = (int) floor (alloc.get_width() * 0.90f);
3850 snprintf (buf, sizeof(buf), "%d", pos);
3852 pos = atoi (prop->value());
3855 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3856 edit_pane.set_position (pos);
3859 done = (Pane) (done | Horizontal);
3861 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3863 if (done & Vertical) {
3867 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3868 /* initial allocation is 90% to canvas, 10% to summary */
3869 pos = (int) floor (alloc.get_height() * 0.90f);
3870 snprintf (buf, sizeof(buf), "%d", pos);
3873 pos = atoi (prop->value());
3876 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3877 editor_summary_pane.set_position (pos);
3880 done = (Pane) (done | Vertical);
3885 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3887 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3888 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3889 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3890 top_hbox.remove (toolbar_frame);
3895 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3897 if (toolbar_frame.get_parent() == 0) {
3898 top_hbox.pack_end (toolbar_frame);
3903 Editor::set_show_measures (bool yn)
3905 if (_show_measures != yn) {
3908 if ((_show_measures = yn) == true) {
3910 tempo_lines->show();
3913 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3914 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3916 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3917 draw_measures (begin, end);
3925 Editor::toggle_follow_playhead ()
3927 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3929 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3930 set_follow_playhead (tact->get_active());
3934 /** @param yn true to follow playhead, otherwise false.
3935 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3938 Editor::set_follow_playhead (bool yn, bool catch_up)
3940 if (_follow_playhead != yn) {
3941 if ((_follow_playhead = yn) == true && catch_up) {
3943 reset_x_origin_to_follow_playhead ();
3950 Editor::toggle_stationary_playhead ()
3952 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3954 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3955 set_stationary_playhead (tact->get_active());
3960 Editor::set_stationary_playhead (bool yn)
3962 if (_stationary_playhead != yn) {
3963 if ((_stationary_playhead = yn) == true) {
3965 // FIXME need a 3.0 equivalent of this 2.X call
3966 // update_current_screen ();
3973 Editor::playlist_selector () const
3975 return *_playlist_selector;
3979 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
3981 if (paste_count == 0) {
3982 /* don't bother calculating an offset that will be zero anyway */
3986 /* calculate basic unsnapped multi-paste offset */
3987 framecnt_t offset = paste_count * duration;
3989 /* snap offset so pos + offset is aligned to the grid */
3990 framepos_t offset_pos = pos + offset;
3991 snap_to(offset_pos, RoundUpMaybe);
3992 offset = offset_pos - pos;
3998 Editor::get_grid_beat_divisions(framepos_t position)
4000 switch (_snap_type) {
4001 case SnapToBeatDiv128: return 128;
4002 case SnapToBeatDiv64: return 64;
4003 case SnapToBeatDiv32: return 32;
4004 case SnapToBeatDiv28: return 28;
4005 case SnapToBeatDiv24: return 24;
4006 case SnapToBeatDiv20: return 20;
4007 case SnapToBeatDiv16: return 16;
4008 case SnapToBeatDiv14: return 14;
4009 case SnapToBeatDiv12: return 12;
4010 case SnapToBeatDiv10: return 10;
4011 case SnapToBeatDiv8: return 8;
4012 case SnapToBeatDiv7: return 7;
4013 case SnapToBeatDiv6: return 6;
4014 case SnapToBeatDiv5: return 5;
4015 case SnapToBeatDiv4: return 4;
4016 case SnapToBeatDiv3: return 3;
4017 case SnapToBeatDiv2: return 2;
4024 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4028 const unsigned divisions = get_grid_beat_divisions(position);
4030 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4033 switch (_snap_type) {
4035 return Evoral::Beats(1.0);
4038 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4046 return Evoral::Beats();
4050 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4054 ret = nudge_clock->current_duration (pos);
4055 next = ret + 1; /* XXXX fix me */
4061 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4063 ArdourDialog dialog (_("Playlist Deletion"));
4064 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4065 "If it is kept, its audio files will not be cleaned.\n"
4066 "If it is deleted, audio files used by it alone will be cleaned."),
4069 dialog.set_position (WIN_POS_CENTER);
4070 dialog.get_vbox()->pack_start (label);
4074 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4075 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4076 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4077 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4078 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4080 // by default gtk uses the left most button
4081 keep->grab_focus ();
4083 switch (dialog.run ()) {
4085 /* keep this and all remaining ones */
4090 /* delete this and all others */
4094 case RESPONSE_ACCEPT:
4095 /* delete the playlist */
4099 case RESPONSE_REJECT:
4100 /* keep the playlist */
4112 Editor::audio_region_selection_covers (framepos_t where)
4114 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4115 if ((*a)->region()->covers (where)) {
4124 Editor::prepare_for_cleanup ()
4126 cut_buffer->clear_regions ();
4127 cut_buffer->clear_playlists ();
4129 selection->clear_regions ();
4130 selection->clear_playlists ();
4132 _regions->suspend_redisplay ();
4136 Editor::finish_cleanup ()
4138 _regions->resume_redisplay ();
4142 Editor::transport_loop_location()
4145 return _session->locations()->auto_loop_location();
4152 Editor::transport_punch_location()
4155 return _session->locations()->auto_punch_location();
4162 Editor::control_layout_scroll (GdkEventScroll* ev)
4164 /* Just forward to the normal canvas scroll method. The coordinate
4165 systems are different but since the canvas is always larger than the
4166 track headers, and aligned with the trackview area, this will work.
4168 In the not too distant future this layout is going away anyway and
4169 headers will be on the canvas.
4171 return canvas_scroll_event (ev, false);
4175 Editor::session_state_saved (string)
4178 _snapshots->redisplay ();
4182 Editor::update_tearoff_visibility()
4184 bool visible = UIConfiguration::instance().get_keep_tearoffs();
4185 _mouse_mode_tearoff->set_visible (visible);
4186 _tools_tearoff->set_visible (visible);
4187 if (_zoom_tearoff) {
4188 _zoom_tearoff->set_visible (visible);
4193 Editor::reattach_all_tearoffs ()
4195 if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
4196 if (_tools_tearoff) _tools_tearoff->put_it_back ();
4197 if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
4201 Editor::maximise_editing_space ()
4207 current_toplevel()->fullscreen ();
4213 Editor::restore_editing_space ()
4219 current_toplevel()->unfullscreen();
4225 * Make new playlists for a given track and also any others that belong
4226 * to the same active route group with the `select' property.
4231 Editor::new_playlists (TimeAxisView* v)
4233 begin_reversible_command (_("new playlists"));
4234 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4235 _session->playlists->get (playlists);
4236 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4237 commit_reversible_command ();
4241 * Use a copy of the current playlist for a given track and also any others that belong
4242 * to the same active route group with the `select' property.
4247 Editor::copy_playlists (TimeAxisView* v)
4249 begin_reversible_command (_("copy playlists"));
4250 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4251 _session->playlists->get (playlists);
4252 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4253 commit_reversible_command ();
4256 /** Clear the current playlist for a given track and also any others that belong
4257 * to the same active route group with the `select' property.
4262 Editor::clear_playlists (TimeAxisView* v)
4264 begin_reversible_command (_("clear playlists"));
4265 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4266 _session->playlists->get (playlists);
4267 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4268 commit_reversible_command ();
4272 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4274 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4278 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4280 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4284 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4286 atv.clear_playlist ();
4290 Editor::get_y_origin () const
4292 return vertical_adjustment.get_value ();
4295 /** Queue up a change to the viewport x origin.
4296 * @param frame New x origin.
4299 Editor::reset_x_origin (framepos_t frame)
4301 pending_visual_change.add (VisualChange::TimeOrigin);
4302 pending_visual_change.time_origin = frame;
4303 ensure_visual_change_idle_handler ();
4307 Editor::reset_y_origin (double y)
4309 pending_visual_change.add (VisualChange::YOrigin);
4310 pending_visual_change.y_origin = y;
4311 ensure_visual_change_idle_handler ();
4315 Editor::reset_zoom (framecnt_t spp)
4317 if (spp == samples_per_pixel) {
4321 pending_visual_change.add (VisualChange::ZoomLevel);
4322 pending_visual_change.samples_per_pixel = spp;
4323 ensure_visual_change_idle_handler ();
4327 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4329 reset_x_origin (frame);
4332 if (!no_save_visual) {
4333 undo_visual_stack.push_back (current_visual_state(false));
4337 Editor::VisualState::VisualState (bool with_tracks)
4338 : gui_state (with_tracks ? new GUIObjectState : 0)
4342 Editor::VisualState::~VisualState ()
4347 Editor::VisualState*
4348 Editor::current_visual_state (bool with_tracks)
4350 VisualState* vs = new VisualState (with_tracks);
4351 vs->y_position = vertical_adjustment.get_value();
4352 vs->samples_per_pixel = samples_per_pixel;
4353 vs->leftmost_frame = leftmost_frame;
4354 vs->zoom_focus = zoom_focus;
4357 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4364 Editor::undo_visual_state ()
4366 if (undo_visual_stack.empty()) {
4370 VisualState* vs = undo_visual_stack.back();
4371 undo_visual_stack.pop_back();
4374 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4377 use_visual_state (*vs);
4382 Editor::redo_visual_state ()
4384 if (redo_visual_stack.empty()) {
4388 VisualState* vs = redo_visual_stack.back();
4389 redo_visual_stack.pop_back();
4391 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4392 // why do we check here?
4393 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4396 use_visual_state (*vs);
4401 Editor::swap_visual_state ()
4403 if (undo_visual_stack.empty()) {
4404 redo_visual_state ();
4406 undo_visual_state ();
4411 Editor::use_visual_state (VisualState& vs)
4413 PBD::Unwinder<bool> nsv (no_save_visual, true);
4414 DisplaySuspender ds;
4416 vertical_adjustment.set_value (vs.y_position);
4418 set_zoom_focus (vs.zoom_focus);
4419 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4422 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4424 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4425 (*i)->clear_property_cache();
4426 (*i)->reset_visual_state ();
4430 _routes->update_visibility ();
4433 /** This is the core function that controls the zoom level of the canvas. It is called
4434 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4435 * @param spp new number of samples per pixel
4438 Editor::set_samples_per_pixel (framecnt_t spp)
4444 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4445 const framecnt_t lots_of_pixels = 4000;
4447 /* if the zoom level is greater than what you'd get trying to display 3
4448 * days of audio on a really big screen, then it's too big.
4451 if (spp * lots_of_pixels > three_days) {
4455 samples_per_pixel = spp;
4458 tempo_lines->tempo_map_changed();
4461 bool const showing_time_selection = selection->time.length() > 0;
4463 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4464 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4465 (*i)->reshow_selection (selection->time);
4469 ZoomChanged (); /* EMIT_SIGNAL */
4471 ArdourCanvas::GtkCanvasViewport* c;
4473 c = get_track_canvas();
4475 c->canvas()->zoomed ();
4478 if (playhead_cursor) {
4479 playhead_cursor->set_position (playhead_cursor->current_frame ());
4482 refresh_location_display();
4483 _summary->set_overlays_dirty ();
4485 update_marker_labels ();
4491 Editor::queue_visual_videotimeline_update ()
4494 * pending_visual_change.add (VisualChange::VideoTimeline);
4495 * or maybe even more specific: which videotimeline-image
4496 * currently it calls update_video_timeline() to update
4497 * _all outdated_ images on the video-timeline.
4498 * see 'exposeimg()' in video_image_frame.cc
4500 ensure_visual_change_idle_handler ();
4504 Editor::ensure_visual_change_idle_handler ()
4506 if (pending_visual_change.idle_handler_id < 0) {
4507 // see comment in add_to_idle_resize above.
4508 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4509 pending_visual_change.being_handled = false;
4514 Editor::_idle_visual_changer (void* arg)
4516 return static_cast<Editor*>(arg)->idle_visual_changer ();
4520 Editor::idle_visual_changer ()
4522 /* set_horizontal_position() below (and maybe other calls) call
4523 gtk_main_iteration(), so it's possible that a signal will be handled
4524 half-way through this method. If this signal wants an
4525 idle_visual_changer we must schedule another one after this one, so
4526 mark the idle_handler_id as -1 here to allow that. Also make a note
4527 that we are doing the visual change, so that changes in response to
4528 super-rapid-screen-update can be dropped if we are still processing
4532 pending_visual_change.idle_handler_id = -1;
4533 pending_visual_change.being_handled = true;
4535 VisualChange vc = pending_visual_change;
4537 pending_visual_change.pending = (VisualChange::Type) 0;
4539 visual_changer (vc);
4541 pending_visual_change.being_handled = false;
4543 return 0; /* this is always a one-shot call */
4547 Editor::visual_changer (const VisualChange& vc)
4549 double const last_time_origin = horizontal_position ();
4551 if (vc.pending & VisualChange::ZoomLevel) {
4552 set_samples_per_pixel (vc.samples_per_pixel);
4554 compute_fixed_ruler_scale ();
4556 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4557 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4559 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4560 current_bbt_points_begin, current_bbt_points_end);
4561 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4562 current_bbt_points_begin, current_bbt_points_end);
4563 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4565 update_video_timeline();
4568 if (vc.pending & VisualChange::TimeOrigin) {
4569 set_horizontal_position (vc.time_origin / samples_per_pixel);
4572 if (vc.pending & VisualChange::YOrigin) {
4573 vertical_adjustment.set_value (vc.y_origin);
4576 if (last_time_origin == horizontal_position ()) {
4577 /* changed signal not emitted */
4578 update_fixed_rulers ();
4579 redisplay_tempo (true);
4582 if (!(vc.pending & VisualChange::ZoomLevel)) {
4583 update_video_timeline();
4586 _summary->set_overlays_dirty ();
4589 struct EditorOrderTimeAxisSorter {
4590 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4591 return a->order () < b->order ();
4596 Editor::sort_track_selection (TrackViewList& sel)
4598 EditorOrderTimeAxisSorter cmp;
4603 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4606 framepos_t where = 0;
4607 EditPoint ep = _edit_point;
4609 if (Profile->get_mixbus())
4610 if (ep == EditAtSelectedMarker)
4611 ep = EditAtPlayhead;
4613 if (from_outside_canvas && (ep == EditAtMouse)) {
4614 ep = EditAtPlayhead;
4615 } else if (from_context_menu && (ep == EditAtMouse)) {
4616 return canvas_event_sample (&context_click_event, 0, 0);
4619 if (entered_marker) {
4620 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4621 return entered_marker->position();
4624 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4625 ep = EditAtSelectedMarker;
4628 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4629 ep = EditAtPlayhead;
4633 case EditAtPlayhead:
4634 if (_dragging_playhead) {
4635 where = *_control_scroll_target;
4637 where = _session->audible_frame();
4639 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4642 case EditAtSelectedMarker:
4643 if (!selection->markers.empty()) {
4645 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4648 where = loc->start();
4652 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4660 if (!mouse_frame (where, ignored)) {
4661 /* XXX not right but what can we do ? */
4665 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4673 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4675 if (!_session) return;
4677 begin_reversible_command (cmd);
4681 if ((tll = transport_loop_location()) == 0) {
4682 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4683 XMLNode &before = _session->locations()->get_state();
4684 _session->locations()->add (loc, true);
4685 _session->set_auto_loop_location (loc);
4686 XMLNode &after = _session->locations()->get_state();
4687 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4689 XMLNode &before = tll->get_state();
4690 tll->set_hidden (false, this);
4691 tll->set (start, end);
4692 XMLNode &after = tll->get_state();
4693 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4696 commit_reversible_command ();
4700 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4702 if (!_session) return;
4704 begin_reversible_command (cmd);
4708 if ((tpl = transport_punch_location()) == 0) {
4709 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4710 XMLNode &before = _session->locations()->get_state();
4711 _session->locations()->add (loc, true);
4712 _session->set_auto_punch_location (loc);
4713 XMLNode &after = _session->locations()->get_state();
4714 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4716 XMLNode &before = tpl->get_state();
4717 tpl->set_hidden (false, this);
4718 tpl->set (start, end);
4719 XMLNode &after = tpl->get_state();
4720 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4723 commit_reversible_command ();
4726 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4727 * @param rs List to which found regions are added.
4728 * @param where Time to look at.
4729 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4732 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4734 const TrackViewList* tracks;
4737 tracks = &track_views;
4742 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4744 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4747 boost::shared_ptr<Track> tr;
4748 boost::shared_ptr<Playlist> pl;
4750 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4752 boost::shared_ptr<RegionList> regions = pl->regions_at (
4753 (framepos_t) floor ( (double) where * tr->speed()));
4755 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4756 RegionView* rv = rtv->view()->find_view (*i);
4767 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4769 const TrackViewList* tracks;
4772 tracks = &track_views;
4777 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4778 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4780 boost::shared_ptr<Track> tr;
4781 boost::shared_ptr<Playlist> pl;
4783 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4785 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4786 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4788 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4790 RegionView* rv = rtv->view()->find_view (*i);
4801 /** Get regions using the following method:
4803 * Make a region list using:
4804 * (a) any selected regions
4805 * (b) the intersection of any selected tracks and the edit point(*)
4806 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4808 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4810 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4814 Editor::get_regions_from_selection_and_edit_point ()
4816 RegionSelection regions;
4818 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4819 regions.add (entered_regionview);
4821 regions = selection->regions;
4824 if ( regions.empty() ) {
4825 TrackViewList tracks = selection->tracks;
4827 if (!tracks.empty()) {
4828 /* no region selected or entered, but some selected tracks:
4829 * act on all regions on the selected tracks at the edit point
4831 framepos_t const where = get_preferred_edit_position ();
4832 get_regions_at(regions, where, tracks);
4839 /** Get regions using the following method:
4841 * Make a region list using:
4842 * (a) any selected regions
4843 * (b) the intersection of any selected tracks and the edit point(*)
4844 * (c) if neither exists, then whatever region is under the mouse
4846 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4848 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4851 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4853 RegionSelection regions;
4855 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4856 regions.add (entered_regionview);
4858 regions = selection->regions;
4861 if ( regions.empty() ) {
4862 TrackViewList tracks = selection->tracks;
4864 if (!tracks.empty()) {
4865 /* no region selected or entered, but some selected tracks:
4866 * act on all regions on the selected tracks at the edit point
4868 get_regions_at(regions, pos, tracks);
4875 /** Start with regions that are selected, or the entered regionview if none are selected.
4876 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4877 * of the regions that we started with.
4881 Editor::get_regions_from_selection_and_entered ()
4883 RegionSelection regions = selection->regions;
4885 if (regions.empty() && entered_regionview) {
4886 regions.add (entered_regionview);
4893 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4895 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4896 RouteTimeAxisView* rtav;
4898 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4899 boost::shared_ptr<Playlist> pl;
4900 std::vector<boost::shared_ptr<Region> > results;
4901 boost::shared_ptr<Track> tr;
4903 if ((tr = rtav->track()) == 0) {
4908 if ((pl = (tr->playlist())) != 0) {
4909 boost::shared_ptr<Region> r = pl->region_by_id (id);
4911 RegionView* rv = rtav->view()->find_view (r);
4913 regions.push_back (rv);
4922 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4925 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4926 MidiTimeAxisView* mtav;
4928 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4930 mtav->get_per_region_note_selection (selection);
4937 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4939 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4941 RouteTimeAxisView* tatv;
4943 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4945 boost::shared_ptr<Playlist> pl;
4946 vector<boost::shared_ptr<Region> > results;
4948 boost::shared_ptr<Track> tr;
4950 if ((tr = tatv->track()) == 0) {
4955 if ((pl = (tr->playlist())) != 0) {
4956 if (src_comparison) {
4957 pl->get_source_equivalent_regions (region, results);
4959 pl->get_region_list_equivalent_regions (region, results);
4963 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4964 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4965 regions.push_back (marv);
4974 Editor::show_rhythm_ferret ()
4976 if (rhythm_ferret == 0) {
4977 rhythm_ferret = new RhythmFerret(*this);
4980 rhythm_ferret->set_session (_session);
4981 rhythm_ferret->show ();
4982 rhythm_ferret->present ();
4986 Editor::first_idle ()
4988 MessageDialog* dialog = 0;
4990 if (track_views.size() > 1) {
4991 Timers::TimerSuspender t;
4992 dialog = new MessageDialog (
4993 *current_toplevel(),
4994 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4998 ARDOUR_UI::instance()->flush_pending ();
5001 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5005 // first idle adds route children (automation tracks), so we need to redisplay here
5006 _routes->redisplay ();
5010 if (_session->undo_depth() == 0) {
5011 undo_action->set_sensitive(false);
5013 redo_action->set_sensitive(false);
5014 begin_selection_op_history ();
5020 Editor::_idle_resize (gpointer arg)
5022 return ((Editor*)arg)->idle_resize ();
5026 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5028 if (resize_idle_id < 0) {
5029 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5030 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5031 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5033 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5034 _pending_resize_amount = 0;
5037 /* make a note of the smallest resulting height, so that we can clamp the
5038 lower limit at TimeAxisView::hSmall */
5040 int32_t min_resulting = INT32_MAX;
5042 _pending_resize_amount += h;
5043 _pending_resize_view = view;
5045 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5047 if (selection->tracks.contains (_pending_resize_view)) {
5048 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5049 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5053 if (min_resulting < 0) {
5058 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5059 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5063 /** Handle pending resizing of tracks */
5065 Editor::idle_resize ()
5067 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5069 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5070 selection->tracks.contains (_pending_resize_view)) {
5072 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5073 if (*i != _pending_resize_view) {
5074 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5079 _pending_resize_amount = 0;
5080 _group_tabs->set_dirty ();
5081 resize_idle_id = -1;
5089 ENSURE_GUI_THREAD (*this, &Editor::located);
5092 playhead_cursor->set_position (_session->audible_frame ());
5093 if (_follow_playhead && !_pending_initial_locate) {
5094 reset_x_origin_to_follow_playhead ();
5098 _pending_locate_request = false;
5099 _pending_initial_locate = false;
5103 Editor::region_view_added (RegionView * rv)
5105 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5106 if (rv->region ()->id () == (*pr)) {
5107 selection->add (rv);
5108 selection->regions.pending.erase (pr);
5113 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5115 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5116 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5117 if (rv->region()->id () == (*rnote).first) {
5118 mrv->select_notes ((*rnote).second);
5119 selection->pending_midi_note_selection.erase(rnote);
5125 _summary->set_background_dirty ();
5129 Editor::region_view_removed ()
5131 _summary->set_background_dirty ();
5135 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5137 TrackViewList::const_iterator j = track_views.begin ();
5138 while (j != track_views.end()) {
5139 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5140 if (rtv && rtv->route() == r) {
5151 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5155 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5156 TimeAxisView* tv = axis_view_from_route (*i);
5166 Editor::suspend_route_redisplay ()
5169 _routes->suspend_redisplay();
5174 Editor::resume_route_redisplay ()
5177 _routes->redisplay(); // queue redisplay
5178 _routes->resume_redisplay();
5183 Editor::add_routes (RouteList& routes)
5185 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5187 RouteTimeAxisView *rtv;
5188 list<RouteTimeAxisView*> new_views;
5189 TrackViewList new_selection;
5190 bool from_scratch = (track_views.size() == 0);
5192 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5193 boost::shared_ptr<Route> route = (*x);
5195 if (route->is_auditioner() || route->is_monitor()) {
5199 DataType dt = route->input()->default_type();
5201 if (dt == ARDOUR::DataType::AUDIO) {
5202 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5203 rtv->set_route (route);
5204 } else if (dt == ARDOUR::DataType::MIDI) {
5205 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5206 rtv->set_route (route);
5208 throw unknown_type();
5211 new_views.push_back (rtv);
5212 track_views.push_back (rtv);
5213 new_selection.push_back (rtv);
5215 rtv->effective_gain_display ();
5217 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5218 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5221 if (new_views.size() > 0) {
5222 _routes->routes_added (new_views);
5223 _summary->routes_added (new_views);
5226 if (!from_scratch) {
5227 selection->tracks.clear();
5228 selection->add (new_selection);
5229 begin_selection_op_history();
5232 if (show_editor_mixer_when_tracks_arrive) {
5233 show_editor_mixer (true);
5236 editor_list_button.set_sensitive (true);
5240 Editor::timeaxisview_deleted (TimeAxisView *tv)
5242 if (tv == entered_track) {
5246 if (_session && _session->deletion_in_progress()) {
5247 /* the situation is under control */
5251 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5253 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5255 _routes->route_removed (tv);
5257 TimeAxisView::Children c = tv->get_child_list ();
5258 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5259 if (entered_track == i->get()) {
5264 /* remove it from the list of track views */
5266 TrackViewList::iterator i;
5268 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5269 i = track_views.erase (i);
5272 /* update whatever the current mixer strip is displaying, if revelant */
5274 boost::shared_ptr<Route> route;
5277 route = rtav->route ();
5280 if (current_mixer_strip && current_mixer_strip->route() == route) {
5282 TimeAxisView* next_tv;
5284 if (track_views.empty()) {
5286 } else if (i == track_views.end()) {
5287 next_tv = track_views.front();
5294 set_selected_mixer_strip (*next_tv);
5296 /* make the editor mixer strip go away setting the
5297 * button to inactive (which also unticks the menu option)
5300 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5306 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5308 if (apply_to_selection) {
5309 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5311 TrackSelection::iterator j = i;
5314 hide_track_in_display (*i, false);
5319 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5321 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5322 // this will hide the mixer strip
5323 set_selected_mixer_strip (*tv);
5326 _routes->hide_track_in_display (*tv);
5331 Editor::sync_track_view_list_and_routes ()
5333 track_views = TrackViewList (_routes->views ());
5335 _summary->set_background_dirty();
5336 _group_tabs->set_dirty ();
5338 return false; // do not call again (until needed)
5342 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5344 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5349 /** Find a RouteTimeAxisView by the ID of its route */
5351 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5353 RouteTimeAxisView* v;
5355 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5356 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5357 if(v->route()->id() == id) {
5367 Editor::fit_route_group (RouteGroup *g)
5369 TrackViewList ts = axis_views_from_routes (g->route_list ());
5374 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5376 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5379 _session->cancel_audition ();
5383 if (_session->is_auditioning()) {
5384 _session->cancel_audition ();
5385 if (r == last_audition_region) {
5390 _session->audition_region (r);
5391 last_audition_region = r;
5396 Editor::hide_a_region (boost::shared_ptr<Region> r)
5398 r->set_hidden (true);
5402 Editor::show_a_region (boost::shared_ptr<Region> r)
5404 r->set_hidden (false);
5408 Editor::audition_region_from_region_list ()
5410 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5414 Editor::hide_region_from_region_list ()
5416 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5420 Editor::show_region_in_region_list ()
5422 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5426 Editor::step_edit_status_change (bool yn)
5429 start_step_editing ();
5431 stop_step_editing ();
5436 Editor::start_step_editing ()
5438 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5442 Editor::stop_step_editing ()
5444 step_edit_connection.disconnect ();
5448 Editor::check_step_edit ()
5450 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5451 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5453 mtv->check_step_edit ();
5457 return true; // do it again, till we stop
5461 Editor::scroll_press (Direction dir)
5463 ++_scroll_callbacks;
5465 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5466 /* delay the first auto-repeat */
5472 scroll_backward (1);
5480 scroll_up_one_track ();
5484 scroll_down_one_track ();
5488 /* do hacky auto-repeat */
5489 if (!_scroll_connection.connected ()) {
5491 _scroll_connection = Glib::signal_timeout().connect (
5492 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5495 _scroll_callbacks = 0;
5502 Editor::scroll_release ()
5504 _scroll_connection.disconnect ();
5507 /** Queue a change for the Editor viewport x origin to follow the playhead */
5509 Editor::reset_x_origin_to_follow_playhead ()
5511 framepos_t const frame = playhead_cursor->current_frame ();
5513 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5515 if (_session->transport_speed() < 0) {
5517 if (frame > (current_page_samples() / 2)) {
5518 center_screen (frame-(current_page_samples()/2));
5520 center_screen (current_page_samples()/2);
5527 if (frame < leftmost_frame) {
5529 if (_session->transport_rolling()) {
5530 /* rolling; end up with the playhead at the right of the page */
5531 l = frame - current_page_samples ();
5533 /* not rolling: end up with the playhead 1/4 of the way along the page */
5534 l = frame - current_page_samples() / 4;
5538 if (_session->transport_rolling()) {
5539 /* rolling: end up with the playhead on the left of the page */
5542 /* not rolling: end up with the playhead 3/4 of the way along the page */
5543 l = frame - 3 * current_page_samples() / 4;
5551 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5557 Editor::super_rapid_screen_update ()
5559 if (!_session || !_session->engine().running()) {
5563 /* METERING / MIXER STRIPS */
5565 /* update track meters, if required */
5566 if (contents().is_mapped() && meters_running) {
5567 RouteTimeAxisView* rtv;
5568 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5569 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5570 rtv->fast_update ();
5575 /* and any current mixer strip */
5576 if (current_mixer_strip) {
5577 current_mixer_strip->fast_update ();
5580 /* PLAYHEAD AND VIEWPORT */
5582 framepos_t const frame = _session->audible_frame();
5584 /* There are a few reasons why we might not update the playhead / viewport stuff:
5586 * 1. we don't update things when there's a pending locate request, otherwise
5587 * when the editor requests a locate there is a chance that this method
5588 * will move the playhead before the locate request is processed, causing
5590 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5591 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5594 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5596 last_update_frame = frame;
5598 if (!_dragging_playhead) {
5599 playhead_cursor->set_position (frame);
5602 if (!_stationary_playhead) {
5604 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5605 /* We only do this if we aren't already
5606 handling a visual change (ie if
5607 pending_visual_change.being_handled is
5608 false) so that these requests don't stack
5609 up there are too many of them to handle in
5612 reset_x_origin_to_follow_playhead ();
5617 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5618 framepos_t const frame = playhead_cursor->current_frame ();
5619 double target = ((double)frame - (double)current_page_samples()/2.0);
5620 if (target <= 0.0) {
5623 // compare to EditorCursor::set_position()
5624 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5625 double const new_pos = sample_to_pixel_unrounded (target);
5626 if (rint (new_pos) != rint (old_pos)) {
5627 reset_x_origin (pixel_to_sample (floor (new_pos)));
5638 Editor::session_going_away ()
5640 _have_idled = false;
5642 _session_connections.drop_connections ();
5644 super_rapid_screen_update_connection.disconnect ();
5646 selection->clear ();
5647 cut_buffer->clear ();
5649 clicked_regionview = 0;
5650 clicked_axisview = 0;
5651 clicked_routeview = 0;
5652 entered_regionview = 0;
5654 last_update_frame = 0;
5657 playhead_cursor->hide ();
5659 /* rip everything out of the list displays */
5663 _route_groups->clear ();
5665 /* do this first so that deleting a track doesn't reset cms to null
5666 and thus cause a leak.
5669 if (current_mixer_strip) {
5670 if (current_mixer_strip->get_parent() != 0) {
5671 global_hpacker.remove (*current_mixer_strip);
5673 delete current_mixer_strip;
5674 current_mixer_strip = 0;
5677 /* delete all trackviews */
5679 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5682 track_views.clear ();
5684 nudge_clock->set_session (0);
5686 editor_list_button.set_active(false);
5687 editor_list_button.set_sensitive(false);
5689 /* clear tempo/meter rulers */
5690 remove_metric_marks ();
5692 clear_marker_display ();
5694 stop_step_editing ();
5698 /* get rid of any existing editor mixer strip */
5700 WindowTitle title(Glib::get_application_name());
5701 title += _("Editor");
5703 own_window()->set_title (title.get_string());
5706 SessionHandlePtr::session_going_away ();
5711 Editor::show_editor_list (bool yn)
5714 _the_notebook.show ();
5716 _the_notebook.hide ();
5721 Editor::change_region_layering_order (bool from_context_menu)
5723 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5725 if (!clicked_routeview) {
5726 if (layering_order_editor) {
5727 layering_order_editor->hide ();
5732 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5738 boost::shared_ptr<Playlist> pl = track->playlist();
5744 if (layering_order_editor == 0) {
5745 layering_order_editor = new RegionLayeringOrderEditor (*this);
5748 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5749 layering_order_editor->maybe_present ();
5753 Editor::update_region_layering_order_editor ()
5755 if (layering_order_editor && layering_order_editor->is_visible ()) {
5756 change_region_layering_order (true);
5761 Editor::setup_fade_images ()
5763 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5764 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5765 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5766 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5767 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5769 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5770 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5771 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5772 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5773 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5775 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5776 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5777 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5778 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5779 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5781 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5782 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5783 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5784 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5785 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5789 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5791 Editor::action_menu_item (std::string const & name)
5793 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5796 return *manage (a->create_menu_item ());
5800 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5802 EventBox* b = manage (new EventBox);
5803 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5804 Label* l = manage (new Label (name));
5808 _the_notebook.append_page (widget, *b);
5812 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5814 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5815 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5818 if (ev->type == GDK_2BUTTON_PRESS) {
5820 /* double-click on a notebook tab shrinks or expands the notebook */
5822 if (_notebook_shrunk) {
5823 if (pre_notebook_shrink_pane_width) {
5824 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5826 _notebook_shrunk = false;
5828 pre_notebook_shrink_pane_width = edit_pane.get_position();
5830 /* this expands the LHS of the edit pane to cover the notebook
5831 PAGE but leaves the tabs visible.
5833 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5834 _notebook_shrunk = true;
5842 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5844 using namespace Menu_Helpers;
5846 MenuList& items = _control_point_context_menu.items ();
5849 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5850 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5851 if (!can_remove_control_point (item)) {
5852 items.back().set_sensitive (false);
5855 _control_point_context_menu.popup (event->button.button, event->button.time);
5859 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5861 using namespace Menu_Helpers;
5863 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5868 /* We need to get the selection here and pass it to the operations, since
5869 popping up the menu will cause a region leave event which clears
5870 entered_regionview. */
5872 MidiRegionView& mrv = note->region_view();
5873 const RegionSelection rs = get_regions_from_selection_and_entered ();
5874 const uint32_t sel_size = mrv.selection_size ();
5876 MenuList& items = _note_context_menu.items();
5880 items.push_back(MenuElem(_("Delete"),
5881 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5884 items.push_back(MenuElem(_("Edit..."),
5885 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5886 if (sel_size != 1) {
5887 items.back().set_sensitive (false);
5890 items.push_back(MenuElem(_("Transpose..."),
5891 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5894 items.push_back(MenuElem(_("Legatize"),
5895 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5897 items.back().set_sensitive (false);
5900 items.push_back(MenuElem(_("Quantize..."),
5901 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5903 items.push_back(MenuElem(_("Remove Overlap"),
5904 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5906 items.back().set_sensitive (false);
5909 items.push_back(MenuElem(_("Transform..."),
5910 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5912 _note_context_menu.popup (event->button.button, event->button.time);
5916 Editor::zoom_vertical_modifier_released()
5918 _stepping_axis_view = 0;
5922 Editor::ui_parameter_changed (string parameter)
5924 if (parameter == "icon-set") {
5925 while (!_cursor_stack.empty()) {
5926 _cursor_stack.pop_back();
5928 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5929 _cursor_stack.push_back(_cursors->grabber);
5930 } else if (parameter == "draggable-playhead") {
5931 if (_verbose_cursor) {
5932 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5938 Editor::use_own_window (bool and_fill_it)
5940 bool new_window = !own_window();
5942 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5944 if (win && new_window) {
5945 win->set_name ("EditorWindow");
5947 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5949 // win->signal_realize().connect (*this, &Editor::on_realize);
5950 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
5955 DisplaySuspender ds;
5956 contents().show_all ();
5958 /* XXX: this is a bit unfortunate; it would probably
5959 be nicer if we could just call show () above rather
5960 than needing the show_all ()
5963 /* re-hide stuff if necessary */
5964 editor_list_button_toggled ();
5965 parameter_changed ("show-summary");
5966 parameter_changed ("show-group-tabs");
5967 parameter_changed ("show-zoom-tools");
5969 /* now reset all audio_time_axis heights, because widgets might need
5975 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5976 tv = (static_cast<TimeAxisView*>(*i));
5977 tv->reset_height ();
5980 if (current_mixer_strip) {
5981 current_mixer_strip->hide_things ();
5982 current_mixer_strip->parameter_changed ("mixer-element-visibility");