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)
291 , _track_canvas_viewport (0)
292 , within_track_canvas (false)
293 , _verbose_cursor (0)
298 , range_marker_group (0)
299 , transport_marker_group (0)
300 , cd_marker_group (0)
301 , _time_markers_group (0)
302 , hv_scroll_group (0)
304 , cursor_scroll_group (0)
305 , no_scroll_group (0)
306 , _trackview_group (0)
307 , _drag_motion_group (0)
308 , _canvas_drop_zone (0)
309 , no_ruler_shown_update (false)
310 , ruler_grabbed_widget (0)
312 , minsec_mark_interval (0)
313 , minsec_mark_modulo (0)
315 , timecode_mark_modulo (0)
316 , timecode_nmarks (0)
317 , _samples_ruler_interval (0)
320 , bbt_bar_helper_on (0)
321 , bbt_accent_modulo (0)
326 , visible_timebars (0)
327 , editor_ruler_menu (0)
331 , range_marker_bar (0)
332 , transport_marker_bar (0)
334 , minsec_label (_("Mins:Secs"))
335 , bbt_label (_("Bars:Beats"))
336 , timecode_label (_("Timecode"))
337 , samples_label (_("Samples"))
338 , tempo_label (_("Tempo"))
339 , meter_label (_("Meter"))
340 , mark_label (_("Location Markers"))
341 , range_mark_label (_("Range Markers"))
342 , transport_mark_label (_("Loop/Punch Ranges"))
343 , cd_mark_label (_("CD Markers"))
344 , videotl_label (_("Video Timeline"))
346 , playhead_cursor (0)
347 , edit_packer (4, 4, true)
348 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
349 , horizontal_adjustment (0.0, 0.0, 1e16)
350 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
351 , controls_layout (unused_adjustment, vertical_adjustment)
352 , _scroll_callbacks (0)
353 , _visible_canvas_width (0)
354 , _visible_canvas_height (0)
355 , _full_canvas_height (0)
356 , edit_controls_left_menu (0)
357 , edit_controls_right_menu (0)
358 , last_update_frame (0)
359 , cut_buffer_start (0)
360 , cut_buffer_length (0)
361 , button_bindings (0)
365 , current_interthread_info (0)
366 , analysis_window (0)
367 , select_new_marker (false)
369 , scrubbing_direction (0)
370 , scrub_reversals (0)
371 , scrub_reverse_distance (0)
372 , have_pending_keyboard_selection (false)
373 , pending_keyboard_selection_start (0)
374 , _snap_type (SnapToBeat)
375 , _snap_mode (SnapOff)
376 , snap_threshold (5.0)
377 , ignore_gui_changes (false)
378 , _drags (new DragManager (this))
380 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
381 , _dragging_playhead (false)
382 , _dragging_edit_point (false)
383 , _show_measures (true)
384 , _follow_playhead (true)
385 , _stationary_playhead (false)
388 , global_rect_group (0)
389 , time_line_group (0)
390 , tempo_or_meter_marker_menu (0)
392 , range_marker_menu (0)
393 , transport_marker_menu (0)
394 , new_transport_marker_menu (0)
396 , marker_menu_item (0)
397 , bbt_beat_subdivision (4)
398 , _visible_track_count (-1)
399 , toolbar_selection_clock_table (2,3)
400 , _mouse_mode_tearoff (0)
401 , automation_mode_button (_("mode"))
404 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
405 , selection (new Selection (this))
406 , cut_buffer (new Selection (this))
407 , _selection_memento (new SelectionMemento())
408 , _all_region_actions_sensitized (false)
409 , _ignore_region_action (false)
410 , _last_region_menu_was_main (false)
411 , _ignore_follow_edits (false)
412 , cd_marker_bar_drag_rect (0)
413 , range_bar_drag_rect (0)
414 , transport_bar_drag_rect (0)
415 , transport_bar_range_rect (0)
416 , transport_bar_preroll_rect (0)
417 , transport_bar_postroll_rect (0)
418 , transport_loop_range_rect (0)
419 , transport_punch_range_rect (0)
420 , transport_punchin_line (0)
421 , transport_punchout_line (0)
422 , transport_preroll_rect (0)
423 , transport_postroll_rect (0)
425 , rubberband_rect (0)
431 , autoscroll_horizontal_allowed (false)
432 , autoscroll_vertical_allowed (false)
434 , autoscroll_widget (0)
435 , show_gain_after_trim (false)
436 , selection_op_cmd_depth (0)
437 , selection_op_history_it (0)
439 , current_mixer_strip (0)
440 , show_editor_mixer_when_tracks_arrive (false)
441 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
442 , current_stepping_trackview (0)
443 , last_track_height_step_timestamp (0)
445 , entered_regionview (0)
446 , clear_entered_track (false)
447 , _edit_point (EditAtMouse)
448 , meters_running (false)
450 , _have_idled (false)
451 , resize_idle_id (-1)
452 , _pending_resize_amount (0)
453 , _pending_resize_view (0)
454 , _pending_locate_request (false)
455 , _pending_initial_locate (false)
459 , layering_order_editor (0)
460 , _last_cut_copy_source_track (0)
461 , _region_selection_change_updates_region_list (true)
463 , _following_mixer_selection (false)
464 , _control_point_toggled_on_press (false)
465 , _stepping_axis_view (0)
466 , quantize_dialog (0)
467 , _main_menu_disabler (0)
469 /* we are a singleton */
471 PublicEditor::_instance = this;
475 last_event_time.tv_sec = 0;
476 last_event_time.tv_usec = 0;
478 global_hpacker.set_data ("ardour-bindings", &key_bindings);
480 selection_op_history.clear();
483 snap_type_strings = I18N (_snap_type_strings);
484 snap_mode_strings = I18N (_snap_mode_strings);
485 zoom_focus_strings = I18N (_zoom_focus_strings);
486 edit_mode_strings = I18N (_edit_mode_strings);
487 edit_point_strings = I18N (_edit_point_strings);
488 #ifdef USE_RUBBERBAND
489 rb_opt_strings = I18N (_rb_opt_strings);
493 build_edit_mode_menu();
494 build_zoom_focus_menu();
495 build_track_count_menu();
496 build_snap_mode_menu();
497 build_snap_type_menu();
498 build_edit_point_menu();
500 location_marker_color = ARDOUR_UI::config()->color ("location marker");
501 location_range_color = ARDOUR_UI::config()->color ("location range");
502 location_cd_marker_color = ARDOUR_UI::config()->color ("location cd marker");
503 location_loop_color = ARDOUR_UI::config()->color ("location loop");
504 location_punch_color = ARDOUR_UI::config()->color ("location punch");
506 timebar_height = std::max(12., ceil (15. * ARDOUR_UI::ui_scale));
508 TimeAxisView::setup_sizes ();
509 ArdourMarker::setup_sizes (timebar_height);
511 bbt_label.set_name ("EditorRulerLabel");
512 bbt_label.set_size_request (-1, (int)timebar_height);
513 bbt_label.set_alignment (1.0, 0.5);
514 bbt_label.set_padding (5,0);
516 bbt_label.set_no_show_all();
517 minsec_label.set_name ("EditorRulerLabel");
518 minsec_label.set_size_request (-1, (int)timebar_height);
519 minsec_label.set_alignment (1.0, 0.5);
520 minsec_label.set_padding (5,0);
521 minsec_label.hide ();
522 minsec_label.set_no_show_all();
523 timecode_label.set_name ("EditorRulerLabel");
524 timecode_label.set_size_request (-1, (int)timebar_height);
525 timecode_label.set_alignment (1.0, 0.5);
526 timecode_label.set_padding (5,0);
527 timecode_label.hide ();
528 timecode_label.set_no_show_all();
529 samples_label.set_name ("EditorRulerLabel");
530 samples_label.set_size_request (-1, (int)timebar_height);
531 samples_label.set_alignment (1.0, 0.5);
532 samples_label.set_padding (5,0);
533 samples_label.hide ();
534 samples_label.set_no_show_all();
536 tempo_label.set_name ("EditorRulerLabel");
537 tempo_label.set_size_request (-1, (int)timebar_height);
538 tempo_label.set_alignment (1.0, 0.5);
539 tempo_label.set_padding (5,0);
541 tempo_label.set_no_show_all();
543 meter_label.set_name ("EditorRulerLabel");
544 meter_label.set_size_request (-1, (int)timebar_height);
545 meter_label.set_alignment (1.0, 0.5);
546 meter_label.set_padding (5,0);
548 meter_label.set_no_show_all();
550 if (Profile->get_trx()) {
551 mark_label.set_text (_("Markers"));
553 mark_label.set_name ("EditorRulerLabel");
554 mark_label.set_size_request (-1, (int)timebar_height);
555 mark_label.set_alignment (1.0, 0.5);
556 mark_label.set_padding (5,0);
558 mark_label.set_no_show_all();
560 cd_mark_label.set_name ("EditorRulerLabel");
561 cd_mark_label.set_size_request (-1, (int)timebar_height);
562 cd_mark_label.set_alignment (1.0, 0.5);
563 cd_mark_label.set_padding (5,0);
564 cd_mark_label.hide();
565 cd_mark_label.set_no_show_all();
567 videotl_bar_height = 4;
568 videotl_label.set_name ("EditorRulerLabel");
569 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
570 videotl_label.set_alignment (1.0, 0.5);
571 videotl_label.set_padding (5,0);
572 videotl_label.hide();
573 videotl_label.set_no_show_all();
575 range_mark_label.set_name ("EditorRulerLabel");
576 range_mark_label.set_size_request (-1, (int)timebar_height);
577 range_mark_label.set_alignment (1.0, 0.5);
578 range_mark_label.set_padding (5,0);
579 range_mark_label.hide();
580 range_mark_label.set_no_show_all();
582 transport_mark_label.set_name ("EditorRulerLabel");
583 transport_mark_label.set_size_request (-1, (int)timebar_height);
584 transport_mark_label.set_alignment (1.0, 0.5);
585 transport_mark_label.set_padding (5,0);
586 transport_mark_label.hide();
587 transport_mark_label.set_no_show_all();
589 initialize_canvas ();
591 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
593 _summary = new EditorSummary (this);
595 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
596 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
598 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
600 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
601 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
603 edit_controls_vbox.set_spacing (0);
604 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
605 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
607 HBox* h = manage (new HBox);
608 _group_tabs = new EditorGroupTabs (this);
609 if (!ARDOUR::Profile->get_trx()) {
610 h->pack_start (*_group_tabs, PACK_SHRINK);
612 h->pack_start (edit_controls_vbox);
613 controls_layout.add (*h);
615 controls_layout.set_name ("EditControlsBase");
616 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
617 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
618 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
620 _cursors = new MouseCursors;
621 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
622 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
624 /* Push default cursor to ever-present bottom of cursor stack. */
625 push_canvas_cursor(_cursors->grabber);
627 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
629 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
630 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
631 pad_line_1->set_outline_color (0xFF0000FF);
637 edit_packer.set_col_spacings (0);
638 edit_packer.set_row_spacings (0);
639 edit_packer.set_homogeneous (false);
640 edit_packer.set_border_width (0);
641 edit_packer.set_name ("EditorWindow");
643 time_bars_event_box.add (time_bars_vbox);
644 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
645 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
647 /* labels for the time bars */
648 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
650 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
652 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
654 bottom_hbox.set_border_width (2);
655 bottom_hbox.set_spacing (3);
657 _route_groups = new EditorRouteGroups (this);
658 _routes = new EditorRoutes (this);
659 _regions = new EditorRegions (this);
660 _snapshots = new EditorSnapshots (this);
661 _locations = new EditorLocations (this);
663 /* these are static location signals */
665 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
666 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
667 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
669 add_notebook_page (_("Regions"), _regions->widget ());
670 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
671 add_notebook_page (_("Snapshots"), _snapshots->widget ());
672 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
673 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
675 _the_notebook.set_show_tabs (true);
676 _the_notebook.set_scrollable (true);
677 _the_notebook.popup_disable ();
678 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
679 _the_notebook.show_all ();
681 _notebook_shrunk = false;
683 editor_summary_pane.pack1(edit_packer);
685 Button* summary_arrows_left_left = manage (new Button);
686 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
687 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
688 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
690 Button* summary_arrows_left_right = manage (new Button);
691 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
692 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
693 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
695 VBox* summary_arrows_left = manage (new VBox);
696 summary_arrows_left->pack_start (*summary_arrows_left_left);
697 summary_arrows_left->pack_start (*summary_arrows_left_right);
699 Button* summary_arrows_right_up = manage (new Button);
700 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
701 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
702 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
704 Button* summary_arrows_right_down = manage (new Button);
705 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
706 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
707 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
709 VBox* summary_arrows_right = manage (new VBox);
710 summary_arrows_right->pack_start (*summary_arrows_right_up);
711 summary_arrows_right->pack_start (*summary_arrows_right_down);
713 Frame* summary_frame = manage (new Frame);
714 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
716 summary_frame->add (*_summary);
717 summary_frame->show ();
719 _summary_hbox.pack_start (*summary_arrows_left, false, false);
720 _summary_hbox.pack_start (*summary_frame, true, true);
721 _summary_hbox.pack_start (*summary_arrows_right, false, false);
723 if (!ARDOUR::Profile->get_trx()) {
724 editor_summary_pane.pack2 (_summary_hbox);
727 edit_pane.pack1 (editor_summary_pane, true, true);
728 if (!ARDOUR::Profile->get_trx()) {
729 edit_pane.pack2 (_the_notebook, false, true);
732 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
734 /* XXX: editor_summary_pane might need similar to the edit_pane */
736 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
738 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
739 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
741 top_hbox.pack_start (toolbar_frame);
743 HBox *hbox = manage (new HBox);
744 hbox->pack_start (edit_pane, true, true);
746 global_vpacker.pack_start (top_hbox, false, false);
747 global_vpacker.pack_start (*hbox, true, true);
748 global_hpacker.pack_start (global_vpacker, true, true);
750 /* register actions now so that set_state() can find them and set toggles/checks etc */
753 /* when we start using our own keybinding system for the editor, this
754 * will be uncommented
760 _playlist_selector = new PlaylistSelector();
761 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
763 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
767 nudge_forward_button.set_name ("nudge button");
768 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
770 nudge_backward_button.set_name ("nudge button");
771 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
773 fade_context_menu.set_name ("ArdourContextMenu");
775 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
777 /* allow external control surfaces/protocols to do various things */
779 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
780 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
781 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
782 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
783 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
784 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
785 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
786 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
787 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
788 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
789 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
790 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
791 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
792 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
794 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
795 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
796 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
797 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
798 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
800 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
802 /* problematic: has to return a value and thus cannot be x-thread */
804 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
806 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
807 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
809 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
811 _ignore_region_action = false;
812 _last_region_menu_was_main = false;
813 _popup_region_menu_item = 0;
815 _ignore_follow_edits = false;
817 _show_marker_lines = false;
819 /* Button bindings */
821 button_bindings = new Bindings;
823 XMLNode* node = button_settings();
825 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
826 button_bindings->load (**i);
832 /* grab current parameter state */
833 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
834 UIConfiguration::instance().map_parameters (pc);
836 setup_fade_images ();
843 delete button_bindings;
845 delete _route_groups;
846 delete _track_canvas_viewport;
849 delete quantize_dialog;
855 delete _playlist_selector;
857 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
863 Editor::button_settings () const
865 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
866 XMLNode* node = find_named_node (*settings, X_("Buttons"));
869 node = new XMLNode (X_("Buttons"));
876 Editor::get_smart_mode () const
878 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
882 Editor::catch_vanishing_regionview (RegionView *rv)
884 /* note: the selection will take care of the vanishing
885 audioregionview by itself.
888 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
892 if (clicked_regionview == rv) {
893 clicked_regionview = 0;
896 if (entered_regionview == rv) {
897 set_entered_regionview (0);
900 if (!_all_region_actions_sensitized) {
901 sensitize_all_region_actions (true);
906 Editor::set_entered_regionview (RegionView* rv)
908 if (rv == entered_regionview) {
912 if (entered_regionview) {
913 entered_regionview->exited ();
916 entered_regionview = rv;
918 if (entered_regionview != 0) {
919 entered_regionview->entered ();
922 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
923 /* This RegionView entry might have changed what region actions
924 are allowed, so sensitize them all in case a key is pressed.
926 sensitize_all_region_actions (true);
931 Editor::set_entered_track (TimeAxisView* tav)
934 entered_track->exited ();
940 entered_track->entered ();
945 Editor::instant_save ()
947 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
952 _session->add_instant_xml(get_state());
954 Config->add_instant_xml(get_state());
959 Editor::control_vertical_zoom_in_all ()
961 tav_zoom_smooth (false, true);
965 Editor::control_vertical_zoom_out_all ()
967 tav_zoom_smooth (true, true);
971 Editor::control_vertical_zoom_in_selected ()
973 tav_zoom_smooth (false, false);
977 Editor::control_vertical_zoom_out_selected ()
979 tav_zoom_smooth (true, false);
983 Editor::control_view (uint32_t view)
985 goto_visual_state (view);
989 Editor::control_unselect ()
991 selection->clear_tracks ();
995 Editor::control_select (uint32_t rid, Selection::Operation op)
997 /* handles the (static) signal from the ControlProtocol class that
998 * requests setting the selected track to a given RID
1005 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1011 TimeAxisView* tav = axis_view_from_route (r);
1015 case Selection::Add:
1016 selection->add (tav);
1018 case Selection::Toggle:
1019 selection->toggle (tav);
1021 case Selection::Extend:
1023 case Selection::Set:
1024 selection->set (tav);
1028 selection->clear_tracks ();
1033 Editor::control_step_tracks_up ()
1035 scroll_tracks_up_line ();
1039 Editor::control_step_tracks_down ()
1041 scroll_tracks_down_line ();
1045 Editor::control_scroll (float fraction)
1047 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1053 double step = fraction * current_page_samples();
1056 _control_scroll_target is an optional<T>
1058 it acts like a pointer to an framepos_t, with
1059 a operator conversion to boolean to check
1060 that it has a value could possibly use
1061 playhead_cursor->current_frame to store the
1062 value and a boolean in the class to know
1063 when it's out of date
1066 if (!_control_scroll_target) {
1067 _control_scroll_target = _session->transport_frame();
1068 _dragging_playhead = true;
1071 if ((fraction < 0.0f) && (*_control_scroll_target <= (framepos_t) fabs(step))) {
1072 *_control_scroll_target = 0;
1073 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1074 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1076 *_control_scroll_target += (framepos_t) trunc (step);
1079 /* move visuals, we'll catch up with it later */
1081 playhead_cursor->set_position (*_control_scroll_target);
1082 UpdateAllTransportClocks (*_control_scroll_target);
1084 if (*_control_scroll_target > (current_page_samples() / 2)) {
1085 /* try to center PH in window */
1086 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1092 Now we do a timeout to actually bring the session to the right place
1093 according to the playhead. This is to avoid reading disk buffers on every
1094 call to control_scroll, which is driven by ScrollTimeline and therefore
1095 probably by a control surface wheel which can generate lots of events.
1097 /* cancel the existing timeout */
1099 control_scroll_connection.disconnect ();
1101 /* add the next timeout */
1103 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1107 Editor::deferred_control_scroll (framepos_t /*target*/)
1109 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1110 // reset for next stream
1111 _control_scroll_target = boost::none;
1112 _dragging_playhead = false;
1117 Editor::access_action (std::string action_group, std::string action_item)
1123 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1126 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1134 Editor::on_realize ()
1138 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1139 start_lock_event_timing ();
1144 Editor::start_lock_event_timing ()
1146 /* check if we should lock the GUI every 30 seconds */
1148 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1152 Editor::generic_event_handler (GdkEvent* ev)
1155 case GDK_BUTTON_PRESS:
1156 case GDK_BUTTON_RELEASE:
1157 case GDK_MOTION_NOTIFY:
1159 case GDK_KEY_RELEASE:
1160 if (contents().is_mapped()) {
1161 gettimeofday (&last_event_time, 0);
1165 case GDK_LEAVE_NOTIFY:
1166 switch (ev->crossing.detail) {
1167 case GDK_NOTIFY_UNKNOWN:
1168 case GDK_NOTIFY_INFERIOR:
1169 case GDK_NOTIFY_ANCESTOR:
1171 case GDK_NOTIFY_VIRTUAL:
1172 case GDK_NOTIFY_NONLINEAR:
1173 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1174 /* leaving window, so reset focus, thus ending any and
1175 all text entry operations.
1190 Editor::lock_timeout_callback ()
1192 struct timeval now, delta;
1194 gettimeofday (&now, 0);
1196 timersub (&now, &last_event_time, &delta);
1198 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1200 /* don't call again. Returning false will effectively
1201 disconnect us from the timer callback.
1203 unlock() will call start_lock_event_timing() to get things
1213 Editor::map_position_change (framepos_t frame)
1215 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1217 if (_session == 0) {
1221 if (_follow_playhead) {
1222 center_screen (frame);
1225 playhead_cursor->set_position (frame);
1229 Editor::center_screen (framepos_t frame)
1231 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1233 /* if we're off the page, then scroll.
1236 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1237 center_screen_internal (frame, page);
1242 Editor::center_screen_internal (framepos_t frame, float page)
1247 frame -= (framepos_t) page;
1252 reset_x_origin (frame);
1257 Editor::update_title ()
1259 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1261 if (!own_window()) {
1266 bool dirty = _session->dirty();
1268 string session_name;
1270 if (_session->snap_name() != _session->name()) {
1271 session_name = _session->snap_name();
1273 session_name = _session->name();
1277 session_name = "*" + session_name;
1280 WindowTitle title(session_name);
1281 title += Glib::get_application_name();
1282 own_window()->set_title (title.get_string());
1284 /* ::session_going_away() will have taken care of it */
1289 Editor::set_session (Session *t)
1291 SessionHandlePtr::set_session (t);
1297 _playlist_selector->set_session (_session);
1298 nudge_clock->set_session (_session);
1299 _summary->set_session (_session);
1300 _group_tabs->set_session (_session);
1301 _route_groups->set_session (_session);
1302 _regions->set_session (_session);
1303 _snapshots->set_session (_session);
1304 _routes->set_session (_session);
1305 _locations->set_session (_session);
1307 if (rhythm_ferret) {
1308 rhythm_ferret->set_session (_session);
1311 if (analysis_window) {
1312 analysis_window->set_session (_session);
1316 sfbrowser->set_session (_session);
1319 compute_fixed_ruler_scale ();
1321 /* Make sure we have auto loop and auto punch ranges */
1323 Location* loc = _session->locations()->auto_loop_location();
1325 loc->set_name (_("Loop"));
1328 loc = _session->locations()->auto_punch_location();
1331 loc->set_name (_("Punch"));
1334 refresh_location_display ();
1336 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1337 the selected Marker; this needs the LocationMarker list to be available.
1339 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1340 set_state (*node, Stateful::loading_state_version);
1342 /* catch up with the playhead */
1344 _session->request_locate (playhead_cursor->current_frame ());
1345 _pending_initial_locate = true;
1349 /* These signals can all be emitted by a non-GUI thread. Therefore the
1350 handlers for them must not attempt to directly interact with the GUI,
1351 but use PBD::Signal<T>::connect() which accepts an event loop
1352 ("context") where the handler will be asked to run.
1355 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1356 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1357 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1358 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1359 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1360 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1361 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1362 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1363 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1364 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1365 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1366 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1367 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1369 playhead_cursor->show ();
1371 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1372 Config->map_parameters (pc);
1373 _session->config.map_parameters (pc);
1375 restore_ruler_visibility ();
1376 //tempo_map_changed (PropertyChange (0));
1377 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1379 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1380 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1383 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1384 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1387 switch (_snap_type) {
1388 case SnapToRegionStart:
1389 case SnapToRegionEnd:
1390 case SnapToRegionSync:
1391 case SnapToRegionBoundary:
1392 build_region_boundary_cache ();
1399 /* register for undo history */
1400 _session->register_with_memento_command_factory(id(), this);
1401 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1403 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1405 start_updating_meters ();
1409 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1411 if (a->get_name() == "RegionMenu") {
1412 /* When the main menu's region menu is opened, we setup the actions so that they look right
1413 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1414 so we resensitize all region actions when the entered regionview or the region selection
1415 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1416 happens after the region context menu is opened. So we set a flag here, too.
1420 sensitize_the_right_region_actions ();
1421 _last_region_menu_was_main = true;
1426 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1428 using namespace Menu_Helpers;
1430 void (Editor::*emf)(FadeShape);
1431 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1434 images = &_xfade_in_images;
1435 emf = &Editor::set_fade_in_shape;
1437 images = &_xfade_out_images;
1438 emf = &Editor::set_fade_out_shape;
1443 _("Linear (for highly correlated material)"),
1444 *(*images)[FadeLinear],
1445 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1449 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1453 _("Constant power"),
1454 *(*images)[FadeConstantPower],
1455 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1458 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1463 *(*images)[FadeSymmetric],
1464 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1468 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1473 *(*images)[FadeSlow],
1474 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1477 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1482 *(*images)[FadeFast],
1483 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1486 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1489 /** Pop up a context menu for when the user clicks on a start crossfade */
1491 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1493 using namespace Menu_Helpers;
1494 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1499 MenuList& items (xfade_in_context_menu.items());
1502 if (arv->audio_region()->fade_in_active()) {
1503 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1505 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1508 items.push_back (SeparatorElem());
1509 fill_xfade_menu (items, true);
1511 xfade_in_context_menu.popup (button, time);
1514 /** Pop up a context menu for when the user clicks on an end crossfade */
1516 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1518 using namespace Menu_Helpers;
1519 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1524 MenuList& items (xfade_out_context_menu.items());
1527 if (arv->audio_region()->fade_out_active()) {
1528 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1530 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1533 items.push_back (SeparatorElem());
1534 fill_xfade_menu (items, false);
1536 xfade_out_context_menu.popup (button, time);
1540 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1542 using namespace Menu_Helpers;
1543 Menu* (Editor::*build_menu_function)();
1546 switch (item_type) {
1548 case RegionViewName:
1549 case RegionViewNameHighlight:
1550 case LeftFrameHandle:
1551 case RightFrameHandle:
1552 if (with_selection) {
1553 build_menu_function = &Editor::build_track_selection_context_menu;
1555 build_menu_function = &Editor::build_track_region_context_menu;
1560 if (with_selection) {
1561 build_menu_function = &Editor::build_track_selection_context_menu;
1563 build_menu_function = &Editor::build_track_context_menu;
1568 if (clicked_routeview->track()) {
1569 build_menu_function = &Editor::build_track_context_menu;
1571 build_menu_function = &Editor::build_track_bus_context_menu;
1576 /* probably shouldn't happen but if it does, we don't care */
1580 menu = (this->*build_menu_function)();
1581 menu->set_name ("ArdourContextMenu");
1583 /* now handle specific situations */
1585 switch (item_type) {
1587 case RegionViewName:
1588 case RegionViewNameHighlight:
1589 case LeftFrameHandle:
1590 case RightFrameHandle:
1591 if (!with_selection) {
1592 if (region_edit_menu_split_item) {
1593 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1594 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1596 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1599 if (region_edit_menu_split_multichannel_item) {
1600 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1601 region_edit_menu_split_multichannel_item->set_sensitive (true);
1603 region_edit_menu_split_multichannel_item->set_sensitive (false);
1616 /* probably shouldn't happen but if it does, we don't care */
1620 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1622 /* Bounce to disk */
1624 using namespace Menu_Helpers;
1625 MenuList& edit_items = menu->items();
1627 edit_items.push_back (SeparatorElem());
1629 switch (clicked_routeview->audio_track()->freeze_state()) {
1630 case AudioTrack::NoFreeze:
1631 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1634 case AudioTrack::Frozen:
1635 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1638 case AudioTrack::UnFrozen:
1639 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1645 if (item_type == StreamItem && clicked_routeview) {
1646 clicked_routeview->build_underlay_menu(menu);
1649 /* When the region menu is opened, we setup the actions so that they look right
1652 sensitize_the_right_region_actions ();
1653 _last_region_menu_was_main = false;
1655 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1656 menu->popup (button, time);
1660 Editor::build_track_context_menu ()
1662 using namespace Menu_Helpers;
1664 MenuList& edit_items = track_context_menu.items();
1667 add_dstream_context_items (edit_items);
1668 return &track_context_menu;
1672 Editor::build_track_bus_context_menu ()
1674 using namespace Menu_Helpers;
1676 MenuList& edit_items = track_context_menu.items();
1679 add_bus_context_items (edit_items);
1680 return &track_context_menu;
1684 Editor::build_track_region_context_menu ()
1686 using namespace Menu_Helpers;
1687 MenuList& edit_items = track_region_context_menu.items();
1690 /* we've just cleared the track region context menu, so the menu that these
1691 two items were on will have disappeared; stop them dangling.
1693 region_edit_menu_split_item = 0;
1694 region_edit_menu_split_multichannel_item = 0;
1696 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1699 boost::shared_ptr<Track> tr;
1700 boost::shared_ptr<Playlist> pl;
1702 if ((tr = rtv->track())) {
1703 add_region_context_items (edit_items, tr);
1707 add_dstream_context_items (edit_items);
1709 return &track_region_context_menu;
1713 Editor::analyze_region_selection ()
1715 if (analysis_window == 0) {
1716 analysis_window = new AnalysisWindow();
1719 analysis_window->set_session(_session);
1721 analysis_window->show_all();
1724 analysis_window->set_regionmode();
1725 analysis_window->analyze();
1727 analysis_window->present();
1731 Editor::analyze_range_selection()
1733 if (analysis_window == 0) {
1734 analysis_window = new AnalysisWindow();
1737 analysis_window->set_session(_session);
1739 analysis_window->show_all();
1742 analysis_window->set_rangemode();
1743 analysis_window->analyze();
1745 analysis_window->present();
1749 Editor::build_track_selection_context_menu ()
1751 using namespace Menu_Helpers;
1752 MenuList& edit_items = track_selection_context_menu.items();
1753 edit_items.clear ();
1755 add_selection_context_items (edit_items);
1756 // edit_items.push_back (SeparatorElem());
1757 // add_dstream_context_items (edit_items);
1759 return &track_selection_context_menu;
1763 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1765 using namespace Menu_Helpers;
1767 /* OK, stick the region submenu at the top of the list, and then add
1771 RegionSelection rs = get_regions_from_selection_and_entered ();
1773 string::size_type pos = 0;
1774 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1776 /* we have to hack up the region name because "_" has a special
1777 meaning for menu titles.
1780 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1781 menu_item_name.replace (pos, 1, "__");
1785 if (_popup_region_menu_item == 0) {
1786 _popup_region_menu_item = new MenuItem (menu_item_name);
1787 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1788 _popup_region_menu_item->show ();
1790 _popup_region_menu_item->set_label (menu_item_name);
1793 /* No latering allowed in later is higher layering model */
1794 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1795 if (act && Config->get_layer_model() == LaterHigher) {
1796 act->set_sensitive (false);
1798 act->set_sensitive (true);
1801 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1803 edit_items.push_back (*_popup_region_menu_item);
1804 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1805 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1807 edit_items.push_back (SeparatorElem());
1810 /** Add context menu items relevant to selection ranges.
1811 * @param edit_items List to add the items to.
1814 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1816 using namespace Menu_Helpers;
1818 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1819 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1821 edit_items.push_back (SeparatorElem());
1822 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1824 edit_items.push_back (SeparatorElem());
1825 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1827 edit_items.push_back (SeparatorElem());
1829 edit_items.push_back (
1831 _("Move Range Start to Previous Region Boundary"),
1832 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1836 edit_items.push_back (
1838 _("Move Range Start to Next Region Boundary"),
1839 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1843 edit_items.push_back (
1845 _("Move Range End to Previous Region Boundary"),
1846 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1850 edit_items.push_back (
1852 _("Move Range End to Next Region Boundary"),
1853 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1857 edit_items.push_back (SeparatorElem());
1858 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1859 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1861 edit_items.push_back (SeparatorElem());
1862 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1864 edit_items.push_back (SeparatorElem());
1865 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1866 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1867 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1869 edit_items.push_back (SeparatorElem());
1870 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1872 edit_items.push_back (SeparatorElem());
1873 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1874 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1876 edit_items.push_back (SeparatorElem());
1877 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1878 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1879 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1880 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1881 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1882 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1883 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1889 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1891 using namespace Menu_Helpers;
1895 Menu *play_menu = manage (new Menu);
1896 MenuList& play_items = play_menu->items();
1897 play_menu->set_name ("ArdourContextMenu");
1899 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1900 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1901 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1902 play_items.push_back (SeparatorElem());
1903 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1905 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1909 Menu *select_menu = manage (new Menu);
1910 MenuList& select_items = select_menu->items();
1911 select_menu->set_name ("ArdourContextMenu");
1913 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1914 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1915 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1916 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1917 select_items.push_back (SeparatorElem());
1918 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1919 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1920 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
1921 select_items.push_back (SeparatorElem());
1922 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
1923 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
1924 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1925 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1926 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1927 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1928 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1930 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1934 Menu *cutnpaste_menu = manage (new Menu);
1935 MenuList& cutnpaste_items = cutnpaste_menu->items();
1936 cutnpaste_menu->set_name ("ArdourContextMenu");
1938 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1939 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1940 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1942 cutnpaste_items.push_back (SeparatorElem());
1944 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1945 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1947 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1949 /* Adding new material */
1951 edit_items.push_back (SeparatorElem());
1952 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1953 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1957 Menu *nudge_menu = manage (new Menu());
1958 MenuList& nudge_items = nudge_menu->items();
1959 nudge_menu->set_name ("ArdourContextMenu");
1961 edit_items.push_back (SeparatorElem());
1962 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1963 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1964 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1965 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1967 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1971 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1973 using namespace Menu_Helpers;
1977 Menu *play_menu = manage (new Menu);
1978 MenuList& play_items = play_menu->items();
1979 play_menu->set_name ("ArdourContextMenu");
1981 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1982 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1983 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1987 Menu *select_menu = manage (new Menu);
1988 MenuList& select_items = select_menu->items();
1989 select_menu->set_name ("ArdourContextMenu");
1991 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1992 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1993 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1994 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1995 select_items.push_back (SeparatorElem());
1996 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
1997 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
1998 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1999 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2001 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2005 Menu *cutnpaste_menu = manage (new Menu);
2006 MenuList& cutnpaste_items = cutnpaste_menu->items();
2007 cutnpaste_menu->set_name ("ArdourContextMenu");
2009 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2010 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2011 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2013 Menu *nudge_menu = manage (new Menu());
2014 MenuList& nudge_items = nudge_menu->items();
2015 nudge_menu->set_name ("ArdourContextMenu");
2017 edit_items.push_back (SeparatorElem());
2018 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2019 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2020 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2021 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2023 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2027 Editor::snap_type() const
2033 Editor::snap_mode() const
2039 Editor::set_snap_to (SnapType st)
2041 unsigned int snap_ind = (unsigned int)st;
2043 if (internal_editing()) {
2044 internal_snap_type = st;
2046 pre_internal_snap_type = st;
2051 if (snap_ind > snap_type_strings.size() - 1) {
2053 _snap_type = (SnapType)snap_ind;
2056 string str = snap_type_strings[snap_ind];
2058 if (str != snap_type_selector.get_text()) {
2059 snap_type_selector.set_text (str);
2064 switch (_snap_type) {
2065 case SnapToBeatDiv128:
2066 case SnapToBeatDiv64:
2067 case SnapToBeatDiv32:
2068 case SnapToBeatDiv28:
2069 case SnapToBeatDiv24:
2070 case SnapToBeatDiv20:
2071 case SnapToBeatDiv16:
2072 case SnapToBeatDiv14:
2073 case SnapToBeatDiv12:
2074 case SnapToBeatDiv10:
2075 case SnapToBeatDiv8:
2076 case SnapToBeatDiv7:
2077 case SnapToBeatDiv6:
2078 case SnapToBeatDiv5:
2079 case SnapToBeatDiv4:
2080 case SnapToBeatDiv3:
2081 case SnapToBeatDiv2: {
2082 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2083 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2085 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2086 current_bbt_points_begin, current_bbt_points_end);
2087 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2088 current_bbt_points_begin, current_bbt_points_end);
2089 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2093 case SnapToRegionStart:
2094 case SnapToRegionEnd:
2095 case SnapToRegionSync:
2096 case SnapToRegionBoundary:
2097 build_region_boundary_cache ();
2105 redisplay_tempo (false);
2107 SnapChanged (); /* EMIT SIGNAL */
2111 Editor::set_snap_mode (SnapMode mode)
2113 string str = snap_mode_strings[(int)mode];
2115 if (internal_editing()) {
2116 internal_snap_mode = mode;
2118 pre_internal_snap_mode = mode;
2123 if (str != snap_mode_selector.get_text ()) {
2124 snap_mode_selector.set_text (str);
2131 Editor::set_edit_point_preference (EditPoint ep, bool force)
2133 bool changed = (_edit_point != ep);
2136 if (Profile->get_mixbus())
2137 if (ep == EditAtSelectedMarker)
2138 ep = EditAtPlayhead;
2140 string str = edit_point_strings[(int)ep];
2141 if (str != edit_point_selector.get_text ()) {
2142 edit_point_selector.set_text (str);
2145 update_all_enter_cursors();
2147 if (!force && !changed) {
2151 const char* action=NULL;
2153 switch (_edit_point) {
2154 case EditAtPlayhead:
2155 action = "edit-at-playhead";
2157 case EditAtSelectedMarker:
2158 action = "edit-at-marker";
2161 action = "edit-at-mouse";
2165 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2167 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2171 bool in_track_canvas;
2173 if (!mouse_frame (foo, in_track_canvas)) {
2174 in_track_canvas = false;
2177 reset_canvas_action_sensitivity (in_track_canvas);
2183 Editor::set_state (const XMLNode& node, int version)
2185 const XMLProperty* prop;
2188 Tabbable::set_state (node, version);
2190 if (_session && (prop = node.property ("playhead"))) {
2192 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2194 playhead_cursor->set_position (pos);
2196 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2197 playhead_cursor->set_position (0);
2200 playhead_cursor->set_position (0);
2203 if ((prop = node.property ("mixer-width"))) {
2204 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2207 if ((prop = node.property ("zoom-focus"))) {
2208 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2211 if ((prop = node.property ("zoom"))) {
2212 /* older versions of ardour used floating point samples_per_pixel */
2213 double f = PBD::atof (prop->value());
2214 reset_zoom (llrintf (f));
2216 reset_zoom (samples_per_pixel);
2219 if ((prop = node.property ("visible-track-count"))) {
2220 set_visible_track_count (PBD::atoi (prop->value()));
2223 if ((prop = node.property ("snap-to"))) {
2224 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2227 if ((prop = node.property ("snap-mode"))) {
2228 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2231 if ((prop = node.property ("internal-snap-to"))) {
2232 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2235 if ((prop = node.property ("internal-snap-mode"))) {
2236 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2239 if ((prop = node.property ("pre-internal-snap-to"))) {
2240 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2243 if ((prop = node.property ("pre-internal-snap-mode"))) {
2244 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2247 if ((prop = node.property ("mouse-mode"))) {
2248 MouseMode m = str2mousemode(prop->value());
2249 set_mouse_mode (m, true);
2251 set_mouse_mode (MouseObject, true);
2254 if ((prop = node.property ("left-frame")) != 0) {
2256 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2260 reset_x_origin (pos);
2264 if ((prop = node.property ("y-origin")) != 0) {
2265 reset_y_origin (atof (prop->value ()));
2268 if ((prop = node.property ("join-object-range"))) {
2269 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2270 bool yn = string_is_affirmative (prop->value());
2272 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2273 tact->set_active (!yn);
2274 tact->set_active (yn);
2276 set_mouse_mode(mouse_mode, true);
2279 if ((prop = node.property ("edit-point"))) {
2280 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2283 if ((prop = node.property ("show-measures"))) {
2284 bool yn = string_is_affirmative (prop->value());
2285 _show_measures = yn;
2288 if ((prop = node.property ("follow-playhead"))) {
2289 bool yn = string_is_affirmative (prop->value());
2290 set_follow_playhead (yn);
2293 if ((prop = node.property ("stationary-playhead"))) {
2294 bool yn = string_is_affirmative (prop->value());
2295 set_stationary_playhead (yn);
2298 if ((prop = node.property ("region-list-sort-type"))) {
2299 RegionListSortType st;
2300 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2303 if ((prop = node.property ("show-editor-mixer"))) {
2305 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2308 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2309 bool yn = string_is_affirmative (prop->value());
2311 /* do it twice to force the change */
2313 tact->set_active (!yn);
2314 tact->set_active (yn);
2317 if ((prop = node.property ("show-editor-list"))) {
2319 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2322 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2323 bool yn = string_is_affirmative (prop->value());
2325 /* do it twice to force the change */
2327 tact->set_active (!yn);
2328 tact->set_active (yn);
2331 if ((prop = node.property (X_("editor-list-page")))) {
2332 _the_notebook.set_current_page (atoi (prop->value ()));
2335 if ((prop = node.property (X_("show-marker-lines")))) {
2336 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2338 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2339 bool yn = string_is_affirmative (prop->value ());
2341 tact->set_active (!yn);
2342 tact->set_active (yn);
2345 XMLNodeList children = node.children ();
2346 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2347 selection->set_state (**i, Stateful::current_state_version);
2348 _regions->set_state (**i);
2351 if ((prop = node.property ("maximised"))) {
2352 bool yn = string_is_affirmative (prop->value());
2353 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2355 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2356 bool fs = tact && tact->get_active();
2358 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2362 if ((prop = node.property ("nudge-clock-value"))) {
2364 sscanf (prop->value().c_str(), "%" PRId64, &f);
2365 nudge_clock->set (f);
2367 nudge_clock->set_mode (AudioClock::Timecode);
2368 nudge_clock->set (_session->frame_rate() * 5, true);
2373 * Not all properties may have been in XML, but
2374 * those that are linked to a private variable may need changing
2379 act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2381 yn = _show_measures;
2382 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2383 /* do it twice to force the change */
2384 tact->set_active (!yn);
2385 tact->set_active (yn);
2388 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2389 yn = _follow_playhead;
2391 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2392 if (tact->get_active() != yn) {
2393 tact->set_active (yn);
2397 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2398 yn = _stationary_playhead;
2400 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2401 if (tact->get_active() != yn) {
2402 tact->set_active (yn);
2411 Editor::get_state ()
2413 XMLNode* node = new XMLNode (X_("Editor"));
2416 id().print (buf, sizeof (buf));
2417 node->add_property ("id", buf);
2419 node->add_child_nocopy (Tabbable::get_state());
2421 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2422 node->add_property("edit-horizontal-pane-pos", string(buf));
2423 node->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2424 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2425 node->add_property("edit-vertical-pane-pos", string(buf));
2427 maybe_add_mixer_strip_width (*node);
2429 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2431 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2432 node->add_property ("zoom", buf);
2433 node->add_property ("snap-to", enum_2_string (_snap_type));
2434 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2435 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2436 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2437 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2438 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2439 node->add_property ("edit-point", enum_2_string (_edit_point));
2440 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2441 node->add_property ("visible-track-count", buf);
2443 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2444 node->add_property ("playhead", buf);
2445 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2446 node->add_property ("left-frame", buf);
2447 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2448 node->add_property ("y-origin", buf);
2450 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2451 node->add_property ("maximised", _maximised ? "yes" : "no");
2452 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2453 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2454 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2455 node->add_property ("mouse-mode", enum2str(mouse_mode));
2456 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2458 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2460 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2461 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2464 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2466 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2467 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2470 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2471 node->add_property (X_("editor-list-page"), buf);
2473 if (button_bindings) {
2474 XMLNode* bb = new XMLNode (X_("Buttons"));
2475 button_bindings->save (*bb);
2476 node->add_child_nocopy (*bb);
2479 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2481 node->add_child_nocopy (selection->get_state ());
2482 node->add_child_nocopy (_regions->get_state ());
2484 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2485 node->add_property ("nudge-clock-value", buf);
2490 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2491 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2493 * @return pair: TimeAxisView that y is over, layer index.
2495 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2496 * in stacked or expanded region display mode, otherwise 0.
2498 std::pair<TimeAxisView *, double>
2499 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2501 if (!trackview_relative_offset) {
2502 y -= _trackview_group->canvas_origin().y;
2506 return std::make_pair ( (TimeAxisView *) 0, 0);
2509 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2511 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2518 return std::make_pair ( (TimeAxisView *) 0, 0);
2521 /** Snap a position to the grid, if appropriate, taking into account current
2522 * grid settings and also the state of any snap modifier keys that may be pressed.
2523 * @param start Position to snap.
2524 * @param event Event to get current key modifier information from, or 0.
2527 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, RoundMode direction, bool for_mark)
2529 if (!_session || !event) {
2533 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2534 if (_snap_mode == SnapOff) {
2535 snap_to_internal (start, direction, for_mark);
2538 if (_snap_mode != SnapOff) {
2539 snap_to_internal (start, direction, for_mark);
2540 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2541 /* SnapOff, but we pressed the snap_delta modifier */
2542 snap_to_internal (start, direction, for_mark);
2548 Editor::snap_to (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2550 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2554 snap_to_internal (start, direction, for_mark, ensure_snap);
2558 Editor::timecode_snap_to_internal (framepos_t& start, RoundMode direction, bool /*for_mark*/)
2560 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2561 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2563 switch (_snap_type) {
2564 case SnapToTimecodeFrame:
2565 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2566 fmod((double)start, (double)_session->frames_per_timecode_frame()) == 0) {
2567 /* start is already on a whole timecode frame, do nothing */
2568 } else if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2569 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2571 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2575 case SnapToTimecodeSeconds:
2576 if (_session->config.get_timecode_offset_negative()) {
2577 start += _session->config.get_timecode_offset ();
2579 start -= _session->config.get_timecode_offset ();
2581 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2582 (start % one_timecode_second == 0)) {
2583 /* start is already on a whole second, do nothing */
2584 } else if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2585 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2587 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2590 if (_session->config.get_timecode_offset_negative()) {
2591 start -= _session->config.get_timecode_offset ();
2593 start += _session->config.get_timecode_offset ();
2597 case SnapToTimecodeMinutes:
2598 if (_session->config.get_timecode_offset_negative()) {
2599 start += _session->config.get_timecode_offset ();
2601 start -= _session->config.get_timecode_offset ();
2603 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2604 (start % one_timecode_minute == 0)) {
2605 /* start is already on a whole minute, do nothing */
2606 } else if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2607 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2609 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2611 if (_session->config.get_timecode_offset_negative()) {
2612 start -= _session->config.get_timecode_offset ();
2614 start += _session->config.get_timecode_offset ();
2618 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2619 abort(); /*NOTREACHED*/
2624 Editor::snap_to_internal (framepos_t& start, RoundMode direction, bool for_mark, bool ensure_snap)
2626 const framepos_t one_second = _session->frame_rate();
2627 const framepos_t one_minute = _session->frame_rate() * 60;
2628 framepos_t presnap = start;
2632 switch (_snap_type) {
2633 case SnapToTimecodeFrame:
2634 case SnapToTimecodeSeconds:
2635 case SnapToTimecodeMinutes:
2636 return timecode_snap_to_internal (start, direction, for_mark);
2639 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2640 start % (one_second/75) == 0) {
2641 /* start is already on a whole CD frame, do nothing */
2642 } else if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2643 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2645 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2650 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2651 start % one_second == 0) {
2652 /* start is already on a whole second, do nothing */
2653 } else if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2654 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2656 start = (framepos_t) floor ((double) start / one_second) * one_second;
2661 if ((direction == RoundUpMaybe || direction == RoundDownMaybe) &&
2662 start % one_minute == 0) {
2663 /* start is already on a whole minute, do nothing */
2664 } else if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2665 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2667 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2672 start = _session->tempo_map().round_to_bar (start, direction);
2676 start = _session->tempo_map().round_to_beat (start, direction);
2679 case SnapToBeatDiv128:
2680 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2682 case SnapToBeatDiv64:
2683 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2685 case SnapToBeatDiv32:
2686 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2688 case SnapToBeatDiv28:
2689 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2691 case SnapToBeatDiv24:
2692 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2694 case SnapToBeatDiv20:
2695 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2697 case SnapToBeatDiv16:
2698 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2700 case SnapToBeatDiv14:
2701 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2703 case SnapToBeatDiv12:
2704 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2706 case SnapToBeatDiv10:
2707 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2709 case SnapToBeatDiv8:
2710 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2712 case SnapToBeatDiv7:
2713 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2715 case SnapToBeatDiv6:
2716 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2718 case SnapToBeatDiv5:
2719 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2721 case SnapToBeatDiv4:
2722 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2724 case SnapToBeatDiv3:
2725 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2727 case SnapToBeatDiv2:
2728 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2736 _session->locations()->marks_either_side (start, before, after);
2738 if (before == max_framepos && after == max_framepos) {
2739 /* No marks to snap to, so just don't snap */
2741 } else if (before == max_framepos) {
2743 } else if (after == max_framepos) {
2745 } else if (before != max_framepos && after != max_framepos) {
2746 /* have before and after */
2747 if ((start - before) < (after - start)) {
2756 case SnapToRegionStart:
2757 case SnapToRegionEnd:
2758 case SnapToRegionSync:
2759 case SnapToRegionBoundary:
2760 if (!region_boundary_cache.empty()) {
2762 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2763 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2765 if (direction > 0) {
2766 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2768 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2771 if (next != region_boundary_cache.begin ()) {
2776 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2777 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2779 if (start > (p + n) / 2) {
2788 switch (_snap_mode) {
2798 if (presnap > start) {
2799 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2803 } else if (presnap < start) {
2804 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2810 /* handled at entry */
2818 Editor::setup_toolbar ()
2820 HBox* mode_box = manage(new HBox);
2821 mode_box->set_border_width (2);
2822 mode_box->set_spacing(2);
2824 HBox* mouse_mode_box = manage (new HBox);
2825 HBox* mouse_mode_hbox = manage (new HBox);
2826 VBox* mouse_mode_vbox = manage (new VBox);
2827 Alignment* mouse_mode_align = manage (new Alignment);
2829 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2830 mouse_mode_size_group->add_widget (smart_mode_button);
2831 mouse_mode_size_group->add_widget (mouse_move_button);
2832 mouse_mode_size_group->add_widget (mouse_cut_button);
2833 mouse_mode_size_group->add_widget (mouse_select_button);
2834 mouse_mode_size_group->add_widget (mouse_timefx_button);
2835 mouse_mode_size_group->add_widget (mouse_audition_button);
2836 mouse_mode_size_group->add_widget (mouse_draw_button);
2837 mouse_mode_size_group->add_widget (mouse_content_button);
2839 mouse_mode_size_group->add_widget (zoom_in_button);
2840 mouse_mode_size_group->add_widget (zoom_out_button);
2841 mouse_mode_size_group->add_widget (zoom_preset_selector);
2842 mouse_mode_size_group->add_widget (zoom_out_full_button);
2843 mouse_mode_size_group->add_widget (zoom_focus_selector);
2845 mouse_mode_size_group->add_widget (tav_shrink_button);
2846 mouse_mode_size_group->add_widget (tav_expand_button);
2847 mouse_mode_size_group->add_widget (visible_tracks_selector);
2849 mouse_mode_size_group->add_widget (snap_type_selector);
2850 mouse_mode_size_group->add_widget (snap_mode_selector);
2852 mouse_mode_size_group->add_widget (edit_point_selector);
2853 mouse_mode_size_group->add_widget (edit_mode_selector);
2855 mouse_mode_size_group->add_widget (*nudge_clock);
2856 mouse_mode_size_group->add_widget (nudge_forward_button);
2857 mouse_mode_size_group->add_widget (nudge_backward_button);
2859 mouse_mode_hbox->set_spacing (2);
2861 if (!ARDOUR::Profile->get_trx()) {
2862 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2865 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2866 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2868 if (!ARDOUR::Profile->get_mixbus()) {
2869 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2872 if (!ARDOUR::Profile->get_trx()) {
2873 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2874 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2875 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2876 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2879 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2881 mouse_mode_align->add (*mouse_mode_vbox);
2882 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2884 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2886 edit_mode_selector.set_name ("mouse mode button");
2888 if (!ARDOUR::Profile->get_trx()) {
2889 mode_box->pack_start (edit_mode_selector, false, false);
2891 mode_box->pack_start (*mouse_mode_box, false, false);
2893 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2894 _mouse_mode_tearoff->set_name ("MouseModeBase");
2895 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2897 if (Profile->get_sae() || Profile->get_mixbus() ) {
2898 _mouse_mode_tearoff->set_can_be_torn_off (false);
2901 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2902 &_mouse_mode_tearoff->tearoff_window()));
2903 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2904 &_mouse_mode_tearoff->tearoff_window(), 1));
2905 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2906 &_mouse_mode_tearoff->tearoff_window()));
2907 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2908 &_mouse_mode_tearoff->tearoff_window(), 1));
2912 _zoom_box.set_spacing (2);
2913 _zoom_box.set_border_width (2);
2917 zoom_preset_selector.set_name ("zoom button");
2918 zoom_preset_selector.set_image(::get_icon ("time_exp"));
2919 zoom_preset_selector.set_size_request (42, -1);
2921 zoom_in_button.set_name ("zoom button");
2922 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
2923 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2924 zoom_in_button.set_related_action (act);
2926 zoom_out_button.set_name ("zoom button");
2927 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
2928 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2929 zoom_out_button.set_related_action (act);
2931 zoom_out_full_button.set_name ("zoom button");
2932 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
2933 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2934 zoom_out_full_button.set_related_action (act);
2936 zoom_focus_selector.set_name ("zoom button");
2938 if (ARDOUR::Profile->get_mixbus()) {
2939 _zoom_box.pack_start (zoom_preset_selector, false, false);
2940 } else if (ARDOUR::Profile->get_trx()) {
2941 mode_box->pack_start (zoom_out_button, false, false);
2942 mode_box->pack_start (zoom_in_button, false, false);
2944 _zoom_box.pack_start (zoom_out_button, false, false);
2945 _zoom_box.pack_start (zoom_in_button, false, false);
2946 _zoom_box.pack_start (zoom_out_full_button, false, false);
2947 _zoom_box.pack_start (zoom_focus_selector, false, false);
2950 /* Track zoom buttons */
2951 visible_tracks_selector.set_name ("zoom button");
2952 if (Profile->get_mixbus()) {
2953 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2954 visible_tracks_selector.set_size_request (42, -1);
2956 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
2959 tav_expand_button.set_name ("zoom button");
2960 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
2961 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2962 tav_expand_button.set_related_action (act);
2964 tav_shrink_button.set_name ("zoom button");
2965 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
2966 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2967 tav_shrink_button.set_related_action (act);
2969 if (ARDOUR::Profile->get_mixbus()) {
2970 _zoom_box.pack_start (visible_tracks_selector);
2971 } else if (ARDOUR::Profile->get_trx()) {
2972 _zoom_box.pack_start (tav_shrink_button);
2973 _zoom_box.pack_start (tav_expand_button);
2975 _zoom_box.pack_start (visible_tracks_selector);
2976 _zoom_box.pack_start (tav_shrink_button);
2977 _zoom_box.pack_start (tav_expand_button);
2980 if (!ARDOUR::Profile->get_trx()) {
2981 _zoom_tearoff = manage (new TearOff (_zoom_box));
2983 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2984 &_zoom_tearoff->tearoff_window()));
2985 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2986 &_zoom_tearoff->tearoff_window(), 0));
2987 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2988 &_zoom_tearoff->tearoff_window()));
2989 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2990 &_zoom_tearoff->tearoff_window(), 0));
2993 if (Profile->get_sae() || Profile->get_mixbus() ) {
2994 _zoom_tearoff->set_can_be_torn_off (false);
2997 snap_box.set_spacing (2);
2998 snap_box.set_border_width (2);
3000 snap_type_selector.set_name ("mouse mode button");
3002 snap_mode_selector.set_name ("mouse mode button");
3004 edit_point_selector.set_name ("mouse mode button");
3006 snap_box.pack_start (snap_mode_selector, false, false);
3007 snap_box.pack_start (snap_type_selector, false, false);
3008 snap_box.pack_start (edit_point_selector, false, false);
3012 HBox *nudge_box = manage (new HBox);
3013 nudge_box->set_spacing (2);
3014 nudge_box->set_border_width (2);
3016 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3017 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3019 nudge_box->pack_start (nudge_backward_button, false, false);
3020 nudge_box->pack_start (nudge_forward_button, false, false);
3021 nudge_box->pack_start (*nudge_clock, false, false);
3024 /* Pack everything in... */
3026 HBox* hbox = manage (new HBox);
3027 hbox->set_spacing(2);
3029 _tools_tearoff = manage (new TearOff (*hbox));
3030 _tools_tearoff->set_name ("MouseModeBase");
3031 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3033 if (Profile->get_sae() || Profile->get_mixbus()) {
3034 _tools_tearoff->set_can_be_torn_off (false);
3037 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3038 &_tools_tearoff->tearoff_window()));
3039 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3040 &_tools_tearoff->tearoff_window(), 0));
3041 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3042 &_tools_tearoff->tearoff_window()));
3043 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3044 &_tools_tearoff->tearoff_window(), 0));
3046 toolbar_hbox.set_spacing (2);
3047 toolbar_hbox.set_border_width (1);
3049 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3050 if (!ARDOUR::Profile->get_trx()) {
3051 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3052 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3055 if (!ARDOUR::Profile->get_trx()) {
3056 hbox->pack_start (snap_box, false, false);
3057 hbox->pack_start (*nudge_box, false, false);
3059 hbox->pack_start (panic_box, false, false);
3063 toolbar_base.set_name ("ToolBarBase");
3064 toolbar_base.add (toolbar_hbox);
3066 _toolbar_viewport.add (toolbar_base);
3067 /* stick to the required height but allow width to vary if there's not enough room */
3068 _toolbar_viewport.set_size_request (1, -1);
3070 toolbar_frame.set_shadow_type (SHADOW_OUT);
3071 toolbar_frame.set_name ("BaseFrame");
3072 toolbar_frame.add (_toolbar_viewport);
3076 Editor::build_edit_point_menu ()
3078 using namespace Menu_Helpers;
3080 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3081 if(!Profile->get_mixbus())
3082 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3083 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3085 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3089 Editor::build_edit_mode_menu ()
3091 using namespace Menu_Helpers;
3093 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3094 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3095 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3096 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3098 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3102 Editor::build_snap_mode_menu ()
3104 using namespace Menu_Helpers;
3106 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3107 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3108 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3110 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3114 Editor::build_snap_type_menu ()
3116 using namespace Menu_Helpers;
3118 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3119 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3120 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3121 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3122 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3123 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3124 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3125 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3126 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3127 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3128 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3129 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3130 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3131 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3132 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3133 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3134 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3135 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3136 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3137 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3138 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3139 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3140 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3141 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3142 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3143 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3144 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3145 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3146 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3147 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3149 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3154 Editor::setup_tooltips ()
3156 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3157 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3158 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3159 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3160 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3161 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3162 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3163 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3164 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3165 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3166 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3167 set_tooltip (zoom_in_button, _("Zoom In"));
3168 set_tooltip (zoom_out_button, _("Zoom Out"));
3169 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3170 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3171 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3172 set_tooltip (tav_expand_button, _("Expand Tracks"));
3173 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3174 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3175 set_tooltip (snap_type_selector, _("Snap/Grid Units"));
3176 set_tooltip (snap_mode_selector, _("Snap/Grid Mode"));
3177 set_tooltip (edit_point_selector, _("Edit Point"));
3178 set_tooltip (edit_mode_selector, _("Edit Mode"));
3179 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3183 Editor::convert_drop_to_paths (
3184 vector<string>& paths,
3185 const RefPtr<Gdk::DragContext>& /*context*/,
3188 const SelectionData& data,
3192 if (_session == 0) {
3196 vector<string> uris = data.get_uris();
3200 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3201 are actually URI lists. So do it by hand.
3204 if (data.get_target() != "text/plain") {
3208 /* Parse the "uri-list" format that Nautilus provides,
3209 where each pathname is delimited by \r\n.
3211 THERE MAY BE NO NULL TERMINATING CHAR!!!
3214 string txt = data.get_text();
3218 p = (char *) malloc (txt.length() + 1);
3219 txt.copy (p, txt.length(), 0);
3220 p[txt.length()] = '\0';
3226 while (g_ascii_isspace (*p))
3230 while (*q && (*q != '\n') && (*q != '\r')) {
3237 while (q > p && g_ascii_isspace (*q))
3242 uris.push_back (string (p, q - p + 1));
3246 p = strchr (p, '\n');
3258 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3259 if ((*i).substr (0,7) == "file://") {
3260 paths.push_back (Glib::filename_from_uri (*i));
3268 Editor::new_tempo_section ()
3273 Editor::map_transport_state ()
3275 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3277 if (_session && _session->transport_stopped()) {
3278 have_pending_keyboard_selection = false;
3281 update_loop_range_view ();
3287 Editor::begin_selection_op_history ()
3289 selection_op_cmd_depth = 0;
3290 selection_op_history_it = 0;
3292 while(!selection_op_history.empty()) {
3293 delete selection_op_history.front();
3294 selection_op_history.pop_front();
3297 selection_undo_action->set_sensitive (false);
3298 selection_redo_action->set_sensitive (false);
3299 selection_op_history.push_front (&_selection_memento->get_state ());
3303 Editor::begin_reversible_selection_op (string name)
3306 //cerr << name << endl;
3307 /* begin/commit pairs can be nested */
3308 selection_op_cmd_depth++;
3313 Editor::commit_reversible_selection_op ()
3316 if (selection_op_cmd_depth == 1) {
3318 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3320 The user has undone some selection ops and then made a new one,
3321 making anything earlier in the list invalid.
3324 list<XMLNode *>::iterator it = selection_op_history.begin();
3325 list<XMLNode *>::iterator e_it = it;
3326 advance (e_it, selection_op_history_it);
3328 for ( ; it != e_it; ++it) {
3331 selection_op_history.erase (selection_op_history.begin(), e_it);
3334 selection_op_history.push_front (&_selection_memento->get_state ());
3335 selection_op_history_it = 0;
3337 selection_undo_action->set_sensitive (true);
3338 selection_redo_action->set_sensitive (false);
3341 if (selection_op_cmd_depth > 0) {
3342 selection_op_cmd_depth--;
3348 Editor::undo_selection_op ()
3351 selection_op_history_it++;
3353 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3354 if (n == selection_op_history_it) {
3355 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3356 selection_redo_action->set_sensitive (true);
3360 /* is there an earlier entry? */
3361 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3362 selection_undo_action->set_sensitive (false);
3368 Editor::redo_selection_op ()
3371 if (selection_op_history_it > 0) {
3372 selection_op_history_it--;
3375 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3376 if (n == selection_op_history_it) {
3377 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3378 selection_undo_action->set_sensitive (true);
3383 if (selection_op_history_it == 0) {
3384 selection_redo_action->set_sensitive (false);
3390 Editor::begin_reversible_command (string name)
3393 before.push_back (&_selection_memento->get_state ());
3394 _session->begin_reversible_command (name);
3399 Editor::begin_reversible_command (GQuark q)
3402 before.push_back (&_selection_memento->get_state ());
3403 _session->begin_reversible_command (q);
3408 Editor::abort_reversible_command ()
3411 while(!before.empty()) {
3412 delete before.front();
3415 _session->abort_reversible_command ();
3420 Editor::commit_reversible_command ()
3423 if (before.size() == 1) {
3424 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3425 redo_action->set_sensitive(false);
3426 undo_action->set_sensitive(true);
3427 begin_selection_op_history ();
3430 if (before.empty()) {
3431 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3436 _session->commit_reversible_command ();
3441 Editor::history_changed ()
3445 if (undo_action && _session) {
3446 if (_session->undo_depth() == 0) {
3447 label = S_("Command|Undo");
3449 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3451 undo_action->property_label() = label;
3454 if (redo_action && _session) {
3455 if (_session->redo_depth() == 0) {
3457 redo_action->set_sensitive (false);
3459 label = string_compose(_("Redo (%1)"), _session->next_redo());
3460 redo_action->set_sensitive (true);
3462 redo_action->property_label() = label;
3467 Editor::duplicate_range (bool with_dialog)
3471 RegionSelection rs = get_regions_from_selection_and_entered ();
3473 if ( selection->time.length() == 0 && rs.empty()) {
3479 ArdourDialog win (_("Duplicate"));
3480 Label label (_("Number of duplications:"));
3481 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3482 SpinButton spinner (adjustment, 0.0, 1);
3485 win.get_vbox()->set_spacing (12);
3486 win.get_vbox()->pack_start (hbox);
3487 hbox.set_border_width (6);
3488 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3490 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3491 place, visually. so do this by hand.
3494 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3495 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3496 spinner.grab_focus();
3502 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3503 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3504 win.set_default_response (RESPONSE_ACCEPT);
3506 spinner.grab_focus ();
3508 switch (win.run ()) {
3509 case RESPONSE_ACCEPT:
3515 times = adjustment.get_value();
3518 if ((current_mouse_mode() == Editing::MouseRange)) {
3519 if (selection->time.length()) {
3520 duplicate_selection (times);
3522 } else if (get_smart_mode()) {
3523 if (selection->time.length()) {
3524 duplicate_selection (times);
3526 duplicate_some_regions (rs, times);
3528 duplicate_some_regions (rs, times);
3533 Editor::set_edit_mode (EditMode m)
3535 Config->set_edit_mode (m);
3539 Editor::cycle_edit_mode ()
3541 switch (Config->get_edit_mode()) {
3543 if (Profile->get_sae()) {
3544 Config->set_edit_mode (Lock);
3546 Config->set_edit_mode (Ripple);
3551 Config->set_edit_mode (Lock);
3554 Config->set_edit_mode (Slide);
3560 Editor::edit_mode_selection_done ( EditMode m )
3562 Config->set_edit_mode ( m );
3566 Editor::snap_type_selection_done (SnapType snaptype)
3568 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3570 ract->set_active ();
3575 Editor::snap_mode_selection_done (SnapMode mode)
3577 RefPtr<RadioAction> ract = snap_mode_action (mode);
3580 ract->set_active (true);
3585 Editor::cycle_edit_point (bool with_marker)
3587 if(Profile->get_mixbus())
3588 with_marker = false;
3590 switch (_edit_point) {
3592 set_edit_point_preference (EditAtPlayhead);
3594 case EditAtPlayhead:
3596 set_edit_point_preference (EditAtSelectedMarker);
3598 set_edit_point_preference (EditAtMouse);
3601 case EditAtSelectedMarker:
3602 set_edit_point_preference (EditAtMouse);
3608 Editor::edit_point_selection_done (EditPoint ep)
3610 set_edit_point_preference ( ep );
3614 Editor::build_zoom_focus_menu ()
3616 using namespace Menu_Helpers;
3618 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3619 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3620 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3621 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3622 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3623 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3625 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3629 Editor::zoom_focus_selection_done ( ZoomFocus f )
3631 RefPtr<RadioAction> ract = zoom_focus_action (f);
3633 ract->set_active ();
3638 Editor::build_track_count_menu ()
3640 using namespace Menu_Helpers;
3642 if (!Profile->get_mixbus()) {
3643 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3644 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3645 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3646 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3647 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3648 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3649 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3650 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3651 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3652 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3653 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3654 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3655 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3657 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3658 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3659 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3660 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3661 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3662 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3663 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3664 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3665 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3666 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3668 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3669 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3670 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3671 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3672 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3673 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3674 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3675 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3676 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3677 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3678 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3683 Editor::set_zoom_preset (int64_t ms)
3686 temporal_zoom_session();
3690 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3691 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3695 Editor::set_visible_track_count (int32_t n)
3697 _visible_track_count = n;
3699 /* if the canvas hasn't really been allocated any size yet, just
3700 record the desired number of visible tracks and return. when canvas
3701 allocation happens, we will get called again and then we can do the
3705 if (_visible_canvas_height <= 1) {
3711 DisplaySuspender ds;
3713 if (_visible_track_count > 0) {
3714 h = trackviews_height() / _visible_track_count;
3715 std::ostringstream s;
3716 s << _visible_track_count;
3718 } else if (_visible_track_count == 0) {
3720 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3721 if ((*i)->marked_for_display()) {
3725 h = trackviews_height() / n;
3728 /* negative value means that the visible track count has
3729 been overridden by explicit track height changes.
3731 visible_tracks_selector.set_text (X_("*"));
3735 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3736 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3739 if (str != visible_tracks_selector.get_text()) {
3740 visible_tracks_selector.set_text (str);
3745 Editor::override_visible_track_count ()
3747 _visible_track_count = -1;
3748 visible_tracks_selector.set_text ( _("*") );
3752 Editor::edit_controls_button_release (GdkEventButton* ev)
3754 if (Keyboard::is_context_menu_event (ev)) {
3755 ARDOUR_UI::instance()->add_route (current_toplevel());
3756 } else if (ev->button == 1) {
3757 selection->clear_tracks ();
3764 Editor::mouse_select_button_release (GdkEventButton* ev)
3766 /* this handles just right-clicks */
3768 if (ev->button != 3) {
3776 Editor::set_zoom_focus (ZoomFocus f)
3778 string str = zoom_focus_strings[(int)f];
3780 if (str != zoom_focus_selector.get_text()) {
3781 zoom_focus_selector.set_text (str);
3784 if (zoom_focus != f) {
3791 Editor::cycle_zoom_focus ()
3793 switch (zoom_focus) {
3795 set_zoom_focus (ZoomFocusRight);
3797 case ZoomFocusRight:
3798 set_zoom_focus (ZoomFocusCenter);
3800 case ZoomFocusCenter:
3801 set_zoom_focus (ZoomFocusPlayhead);
3803 case ZoomFocusPlayhead:
3804 set_zoom_focus (ZoomFocusMouse);
3806 case ZoomFocusMouse:
3807 set_zoom_focus (ZoomFocusEdit);
3810 set_zoom_focus (ZoomFocusLeft);
3816 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3818 /* recover or initialize pane positions. do this here rather than earlier because
3819 we don't want the positions to change the child allocations, which they seem to do.
3825 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3834 XMLNode* geometry = find_named_node (*node, "geometry");
3836 if (which == static_cast<Paned*> (&edit_pane)) {
3838 if (done & Horizontal) {
3842 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3843 _notebook_shrunk = string_is_affirmative (prop->value ());
3846 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3847 /* initial allocation is 90% to canvas, 10% to notebook */
3848 pos = (int) floor (alloc.get_width() * 0.90f);
3849 snprintf (buf, sizeof(buf), "%d", pos);
3851 pos = atoi (prop->value());
3854 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3855 edit_pane.set_position (pos);
3858 done = (Pane) (done | Horizontal);
3860 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3862 if (done & Vertical) {
3866 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3867 /* initial allocation is 90% to canvas, 10% to summary */
3868 pos = (int) floor (alloc.get_height() * 0.90f);
3869 snprintf (buf, sizeof(buf), "%d", pos);
3872 pos = atoi (prop->value());
3875 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3876 editor_summary_pane.set_position (pos);
3879 done = (Pane) (done | Vertical);
3884 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3886 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3887 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3888 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3889 top_hbox.remove (toolbar_frame);
3894 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3896 if (toolbar_frame.get_parent() == 0) {
3897 top_hbox.pack_end (toolbar_frame);
3902 Editor::set_show_measures (bool yn)
3904 if (_show_measures != yn) {
3907 if ((_show_measures = yn) == true) {
3909 tempo_lines->show();
3912 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3913 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3915 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3916 draw_measures (begin, end);
3924 Editor::toggle_follow_playhead ()
3926 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3928 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3929 set_follow_playhead (tact->get_active());
3933 /** @param yn true to follow playhead, otherwise false.
3934 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3937 Editor::set_follow_playhead (bool yn, bool catch_up)
3939 if (_follow_playhead != yn) {
3940 if ((_follow_playhead = yn) == true && catch_up) {
3942 reset_x_origin_to_follow_playhead ();
3949 Editor::toggle_stationary_playhead ()
3951 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3953 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3954 set_stationary_playhead (tact->get_active());
3959 Editor::set_stationary_playhead (bool yn)
3961 if (_stationary_playhead != yn) {
3962 if ((_stationary_playhead = yn) == true) {
3964 // FIXME need a 3.0 equivalent of this 2.X call
3965 // update_current_screen ();
3972 Editor::playlist_selector () const
3974 return *_playlist_selector;
3978 Editor::get_paste_offset (framepos_t pos, unsigned paste_count, framecnt_t duration)
3980 if (paste_count == 0) {
3981 /* don't bother calculating an offset that will be zero anyway */
3985 /* calculate basic unsnapped multi-paste offset */
3986 framecnt_t offset = paste_count * duration;
3988 /* snap offset so pos + offset is aligned to the grid */
3989 framepos_t offset_pos = pos + offset;
3990 snap_to(offset_pos, RoundUpMaybe);
3991 offset = offset_pos - pos;
3997 Editor::get_grid_beat_divisions(framepos_t position)
3999 switch (_snap_type) {
4000 case SnapToBeatDiv128: return 128;
4001 case SnapToBeatDiv64: return 64;
4002 case SnapToBeatDiv32: return 32;
4003 case SnapToBeatDiv28: return 28;
4004 case SnapToBeatDiv24: return 24;
4005 case SnapToBeatDiv20: return 20;
4006 case SnapToBeatDiv16: return 16;
4007 case SnapToBeatDiv14: return 14;
4008 case SnapToBeatDiv12: return 12;
4009 case SnapToBeatDiv10: return 10;
4010 case SnapToBeatDiv8: return 8;
4011 case SnapToBeatDiv7: return 7;
4012 case SnapToBeatDiv6: return 6;
4013 case SnapToBeatDiv5: return 5;
4014 case SnapToBeatDiv4: return 4;
4015 case SnapToBeatDiv3: return 3;
4016 case SnapToBeatDiv2: return 2;
4023 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
4027 const unsigned divisions = get_grid_beat_divisions(position);
4029 return Evoral::Beats(1.0 / (double)get_grid_beat_divisions(position));
4032 switch (_snap_type) {
4034 return Evoral::Beats(1.0);
4037 return Evoral::Beats(_session->tempo_map().meter_at (position).divisions_per_bar());
4045 return Evoral::Beats();
4049 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
4053 ret = nudge_clock->current_duration (pos);
4054 next = ret + 1; /* XXXX fix me */
4060 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4062 ArdourDialog dialog (_("Playlist Deletion"));
4063 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4064 "If it is kept, its audio files will not be cleaned.\n"
4065 "If it is deleted, audio files used by it alone will be cleaned."),
4068 dialog.set_position (WIN_POS_CENTER);
4069 dialog.get_vbox()->pack_start (label);
4073 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4074 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4075 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4076 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4077 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4079 // by default gtk uses the left most button
4080 keep->grab_focus ();
4082 switch (dialog.run ()) {
4084 /* keep this and all remaining ones */
4089 /* delete this and all others */
4093 case RESPONSE_ACCEPT:
4094 /* delete the playlist */
4098 case RESPONSE_REJECT:
4099 /* keep the playlist */
4111 Editor::audio_region_selection_covers (framepos_t where)
4113 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4114 if ((*a)->region()->covers (where)) {
4123 Editor::prepare_for_cleanup ()
4125 cut_buffer->clear_regions ();
4126 cut_buffer->clear_playlists ();
4128 selection->clear_regions ();
4129 selection->clear_playlists ();
4131 _regions->suspend_redisplay ();
4135 Editor::finish_cleanup ()
4137 _regions->resume_redisplay ();
4141 Editor::transport_loop_location()
4144 return _session->locations()->auto_loop_location();
4151 Editor::transport_punch_location()
4154 return _session->locations()->auto_punch_location();
4161 Editor::control_layout_scroll (GdkEventScroll* ev)
4163 /* Just forward to the normal canvas scroll method. The coordinate
4164 systems are different but since the canvas is always larger than the
4165 track headers, and aligned with the trackview area, this will work.
4167 In the not too distant future this layout is going away anyway and
4168 headers will be on the canvas.
4170 return canvas_scroll_event (ev, false);
4174 Editor::session_state_saved (string)
4177 _snapshots->redisplay ();
4181 Editor::update_tearoff_visibility()
4183 bool visible = UIConfiguration::instance().get_keep_tearoffs();
4184 _mouse_mode_tearoff->set_visible (visible);
4185 _tools_tearoff->set_visible (visible);
4186 if (_zoom_tearoff) {
4187 _zoom_tearoff->set_visible (visible);
4192 Editor::reattach_all_tearoffs ()
4194 if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
4195 if (_tools_tearoff) _tools_tearoff->put_it_back ();
4196 if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
4200 Editor::maximise_editing_space ()
4206 current_toplevel()->fullscreen ();
4212 Editor::restore_editing_space ()
4218 current_toplevel()->unfullscreen();
4224 * Make new playlists for a given track and also any others that belong
4225 * to the same active route group with the `select' property.
4230 Editor::new_playlists (TimeAxisView* v)
4232 begin_reversible_command (_("new playlists"));
4233 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4234 _session->playlists->get (playlists);
4235 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4236 commit_reversible_command ();
4240 * Use a copy of the current playlist for a given track and also any others that belong
4241 * to the same active route group with the `select' property.
4246 Editor::copy_playlists (TimeAxisView* v)
4248 begin_reversible_command (_("copy playlists"));
4249 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4250 _session->playlists->get (playlists);
4251 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4252 commit_reversible_command ();
4255 /** Clear the current playlist for a given track and also any others that belong
4256 * to the same active route group with the `select' property.
4261 Editor::clear_playlists (TimeAxisView* v)
4263 begin_reversible_command (_("clear playlists"));
4264 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4265 _session->playlists->get (playlists);
4266 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4267 commit_reversible_command ();
4271 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4273 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4277 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4279 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4283 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4285 atv.clear_playlist ();
4289 Editor::get_y_origin () const
4291 return vertical_adjustment.get_value ();
4294 /** Queue up a change to the viewport x origin.
4295 * @param frame New x origin.
4298 Editor::reset_x_origin (framepos_t frame)
4300 pending_visual_change.add (VisualChange::TimeOrigin);
4301 pending_visual_change.time_origin = frame;
4302 ensure_visual_change_idle_handler ();
4306 Editor::reset_y_origin (double y)
4308 pending_visual_change.add (VisualChange::YOrigin);
4309 pending_visual_change.y_origin = y;
4310 ensure_visual_change_idle_handler ();
4314 Editor::reset_zoom (framecnt_t spp)
4316 if (spp == samples_per_pixel) {
4320 pending_visual_change.add (VisualChange::ZoomLevel);
4321 pending_visual_change.samples_per_pixel = spp;
4322 ensure_visual_change_idle_handler ();
4326 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4328 reset_x_origin (frame);
4331 if (!no_save_visual) {
4332 undo_visual_stack.push_back (current_visual_state(false));
4336 Editor::VisualState::VisualState (bool with_tracks)
4337 : gui_state (with_tracks ? new GUIObjectState : 0)
4341 Editor::VisualState::~VisualState ()
4346 Editor::VisualState*
4347 Editor::current_visual_state (bool with_tracks)
4349 VisualState* vs = new VisualState (with_tracks);
4350 vs->y_position = vertical_adjustment.get_value();
4351 vs->samples_per_pixel = samples_per_pixel;
4352 vs->leftmost_frame = leftmost_frame;
4353 vs->zoom_focus = zoom_focus;
4356 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4363 Editor::undo_visual_state ()
4365 if (undo_visual_stack.empty()) {
4369 VisualState* vs = undo_visual_stack.back();
4370 undo_visual_stack.pop_back();
4373 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4376 use_visual_state (*vs);
4381 Editor::redo_visual_state ()
4383 if (redo_visual_stack.empty()) {
4387 VisualState* vs = redo_visual_stack.back();
4388 redo_visual_stack.pop_back();
4390 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4391 // why do we check here?
4392 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4395 use_visual_state (*vs);
4400 Editor::swap_visual_state ()
4402 if (undo_visual_stack.empty()) {
4403 redo_visual_state ();
4405 undo_visual_state ();
4410 Editor::use_visual_state (VisualState& vs)
4412 PBD::Unwinder<bool> nsv (no_save_visual, true);
4413 DisplaySuspender ds;
4415 vertical_adjustment.set_value (vs.y_position);
4417 set_zoom_focus (vs.zoom_focus);
4418 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4421 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4423 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4424 (*i)->clear_property_cache();
4425 (*i)->reset_visual_state ();
4429 _routes->update_visibility ();
4432 /** This is the core function that controls the zoom level of the canvas. It is called
4433 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4434 * @param spp new number of samples per pixel
4437 Editor::set_samples_per_pixel (framecnt_t spp)
4443 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4444 const framecnt_t lots_of_pixels = 4000;
4446 /* if the zoom level is greater than what you'd get trying to display 3
4447 * days of audio on a really big screen, then it's too big.
4450 if (spp * lots_of_pixels > three_days) {
4454 samples_per_pixel = spp;
4457 tempo_lines->tempo_map_changed();
4460 bool const showing_time_selection = selection->time.length() > 0;
4462 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4463 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4464 (*i)->reshow_selection (selection->time);
4468 ZoomChanged (); /* EMIT_SIGNAL */
4470 ArdourCanvas::GtkCanvasViewport* c;
4472 c = get_track_canvas();
4474 c->canvas()->zoomed ();
4477 if (playhead_cursor) {
4478 playhead_cursor->set_position (playhead_cursor->current_frame ());
4481 refresh_location_display();
4482 _summary->set_overlays_dirty ();
4484 update_marker_labels ();
4490 Editor::queue_visual_videotimeline_update ()
4493 * pending_visual_change.add (VisualChange::VideoTimeline);
4494 * or maybe even more specific: which videotimeline-image
4495 * currently it calls update_video_timeline() to update
4496 * _all outdated_ images on the video-timeline.
4497 * see 'exposeimg()' in video_image_frame.cc
4499 ensure_visual_change_idle_handler ();
4503 Editor::ensure_visual_change_idle_handler ()
4505 if (pending_visual_change.idle_handler_id < 0) {
4506 // see comment in add_to_idle_resize above.
4507 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4508 pending_visual_change.being_handled = false;
4513 Editor::_idle_visual_changer (void* arg)
4515 return static_cast<Editor*>(arg)->idle_visual_changer ();
4519 Editor::idle_visual_changer ()
4521 /* set_horizontal_position() below (and maybe other calls) call
4522 gtk_main_iteration(), so it's possible that a signal will be handled
4523 half-way through this method. If this signal wants an
4524 idle_visual_changer we must schedule another one after this one, so
4525 mark the idle_handler_id as -1 here to allow that. Also make a note
4526 that we are doing the visual change, so that changes in response to
4527 super-rapid-screen-update can be dropped if we are still processing
4531 pending_visual_change.idle_handler_id = -1;
4532 pending_visual_change.being_handled = true;
4534 VisualChange vc = pending_visual_change;
4536 pending_visual_change.pending = (VisualChange::Type) 0;
4538 visual_changer (vc);
4540 pending_visual_change.being_handled = false;
4542 return 0; /* this is always a one-shot call */
4546 Editor::visual_changer (const VisualChange& vc)
4548 double const last_time_origin = horizontal_position ();
4550 if (vc.pending & VisualChange::ZoomLevel) {
4551 set_samples_per_pixel (vc.samples_per_pixel);
4553 compute_fixed_ruler_scale ();
4555 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4556 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4558 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4559 current_bbt_points_begin, current_bbt_points_end);
4560 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4561 current_bbt_points_begin, current_bbt_points_end);
4562 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4564 update_video_timeline();
4567 if (vc.pending & VisualChange::TimeOrigin) {
4568 set_horizontal_position (vc.time_origin / samples_per_pixel);
4571 if (vc.pending & VisualChange::YOrigin) {
4572 vertical_adjustment.set_value (vc.y_origin);
4575 if (last_time_origin == horizontal_position ()) {
4576 /* changed signal not emitted */
4577 update_fixed_rulers ();
4578 redisplay_tempo (true);
4581 if (!(vc.pending & VisualChange::ZoomLevel)) {
4582 update_video_timeline();
4585 _summary->set_overlays_dirty ();
4588 struct EditorOrderTimeAxisSorter {
4589 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4590 return a->order () < b->order ();
4595 Editor::sort_track_selection (TrackViewList& sel)
4597 EditorOrderTimeAxisSorter cmp;
4602 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4605 framepos_t where = 0;
4606 EditPoint ep = _edit_point;
4608 if (Profile->get_mixbus())
4609 if (ep == EditAtSelectedMarker)
4610 ep = EditAtPlayhead;
4612 if (from_outside_canvas && (ep == EditAtMouse)) {
4613 ep = EditAtPlayhead;
4614 } else if (from_context_menu && (ep == EditAtMouse)) {
4615 return canvas_event_sample (&context_click_event, 0, 0);
4618 if (entered_marker) {
4619 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4620 return entered_marker->position();
4623 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4624 ep = EditAtSelectedMarker;
4627 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4628 ep = EditAtPlayhead;
4632 case EditAtPlayhead:
4633 if (_dragging_playhead) {
4634 where = *_control_scroll_target;
4636 where = _session->audible_frame();
4638 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4641 case EditAtSelectedMarker:
4642 if (!selection->markers.empty()) {
4644 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4647 where = loc->start();
4651 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4659 if (!mouse_frame (where, ignored)) {
4660 /* XXX not right but what can we do ? */
4664 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4672 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4674 if (!_session) return;
4676 begin_reversible_command (cmd);
4680 if ((tll = transport_loop_location()) == 0) {
4681 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4682 XMLNode &before = _session->locations()->get_state();
4683 _session->locations()->add (loc, true);
4684 _session->set_auto_loop_location (loc);
4685 XMLNode &after = _session->locations()->get_state();
4686 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4688 XMLNode &before = tll->get_state();
4689 tll->set_hidden (false, this);
4690 tll->set (start, end);
4691 XMLNode &after = tll->get_state();
4692 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4695 commit_reversible_command ();
4699 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4701 if (!_session) return;
4703 begin_reversible_command (cmd);
4707 if ((tpl = transport_punch_location()) == 0) {
4708 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4709 XMLNode &before = _session->locations()->get_state();
4710 _session->locations()->add (loc, true);
4711 _session->set_auto_punch_location (loc);
4712 XMLNode &after = _session->locations()->get_state();
4713 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4715 XMLNode &before = tpl->get_state();
4716 tpl->set_hidden (false, this);
4717 tpl->set (start, end);
4718 XMLNode &after = tpl->get_state();
4719 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4722 commit_reversible_command ();
4725 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4726 * @param rs List to which found regions are added.
4727 * @param where Time to look at.
4728 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4731 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4733 const TrackViewList* tracks;
4736 tracks = &track_views;
4741 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4743 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4746 boost::shared_ptr<Track> tr;
4747 boost::shared_ptr<Playlist> pl;
4749 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4751 boost::shared_ptr<RegionList> regions = pl->regions_at (
4752 (framepos_t) floor ( (double) where * tr->speed()));
4754 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4755 RegionView* rv = rtv->view()->find_view (*i);
4766 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4768 const TrackViewList* tracks;
4771 tracks = &track_views;
4776 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4777 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4779 boost::shared_ptr<Track> tr;
4780 boost::shared_ptr<Playlist> pl;
4782 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4784 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4785 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4787 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4789 RegionView* rv = rtv->view()->find_view (*i);
4800 /** Get regions using the following method:
4802 * Make a region list using:
4803 * (a) any selected regions
4804 * (b) the intersection of any selected tracks and the edit point(*)
4805 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4807 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4809 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4813 Editor::get_regions_from_selection_and_edit_point ()
4815 RegionSelection regions;
4817 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4818 regions.add (entered_regionview);
4820 regions = selection->regions;
4823 if ( regions.empty() ) {
4824 TrackViewList tracks = selection->tracks;
4826 if (!tracks.empty()) {
4827 /* no region selected or entered, but some selected tracks:
4828 * act on all regions on the selected tracks at the edit point
4830 framepos_t const where = get_preferred_edit_position ();
4831 get_regions_at(regions, where, tracks);
4838 /** Get regions using the following method:
4840 * Make a region list using:
4841 * (a) any selected regions
4842 * (b) the intersection of any selected tracks and the edit point(*)
4843 * (c) if neither exists, then whatever region is under the mouse
4845 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4847 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4850 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4852 RegionSelection regions;
4854 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4855 regions.add (entered_regionview);
4857 regions = selection->regions;
4860 if ( regions.empty() ) {
4861 TrackViewList tracks = selection->tracks;
4863 if (!tracks.empty()) {
4864 /* no region selected or entered, but some selected tracks:
4865 * act on all regions on the selected tracks at the edit point
4867 get_regions_at(regions, pos, tracks);
4874 /** Start with regions that are selected, or the entered regionview if none are selected.
4875 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4876 * of the regions that we started with.
4880 Editor::get_regions_from_selection_and_entered ()
4882 RegionSelection regions = selection->regions;
4884 if (regions.empty() && entered_regionview) {
4885 regions.add (entered_regionview);
4892 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4894 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4895 RouteTimeAxisView* rtav;
4897 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4898 boost::shared_ptr<Playlist> pl;
4899 std::vector<boost::shared_ptr<Region> > results;
4900 boost::shared_ptr<Track> tr;
4902 if ((tr = rtav->track()) == 0) {
4907 if ((pl = (tr->playlist())) != 0) {
4908 boost::shared_ptr<Region> r = pl->region_by_id (id);
4910 RegionView* rv = rtav->view()->find_view (r);
4912 regions.push_back (rv);
4921 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4924 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4925 MidiTimeAxisView* mtav;
4927 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4929 mtav->get_per_region_note_selection (selection);
4936 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4938 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4940 RouteTimeAxisView* tatv;
4942 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4944 boost::shared_ptr<Playlist> pl;
4945 vector<boost::shared_ptr<Region> > results;
4947 boost::shared_ptr<Track> tr;
4949 if ((tr = tatv->track()) == 0) {
4954 if ((pl = (tr->playlist())) != 0) {
4955 if (src_comparison) {
4956 pl->get_source_equivalent_regions (region, results);
4958 pl->get_region_list_equivalent_regions (region, results);
4962 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4963 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4964 regions.push_back (marv);
4973 Editor::show_rhythm_ferret ()
4975 if (rhythm_ferret == 0) {
4976 rhythm_ferret = new RhythmFerret(*this);
4979 rhythm_ferret->set_session (_session);
4980 rhythm_ferret->show ();
4981 rhythm_ferret->present ();
4985 Editor::first_idle ()
4987 MessageDialog* dialog = 0;
4989 if (track_views.size() > 1) {
4990 Timers::TimerSuspender t;
4991 dialog = new MessageDialog (
4992 *current_toplevel(),
4993 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4997 ARDOUR_UI::instance()->flush_pending ();
5000 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5004 // first idle adds route children (automation tracks), so we need to redisplay here
5005 _routes->redisplay ();
5009 if (_session->undo_depth() == 0) {
5010 undo_action->set_sensitive(false);
5012 redo_action->set_sensitive(false);
5013 begin_selection_op_history ();
5019 Editor::_idle_resize (gpointer arg)
5021 return ((Editor*)arg)->idle_resize ();
5025 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5027 if (resize_idle_id < 0) {
5028 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5029 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5030 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5032 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5033 _pending_resize_amount = 0;
5036 /* make a note of the smallest resulting height, so that we can clamp the
5037 lower limit at TimeAxisView::hSmall */
5039 int32_t min_resulting = INT32_MAX;
5041 _pending_resize_amount += h;
5042 _pending_resize_view = view;
5044 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5046 if (selection->tracks.contains (_pending_resize_view)) {
5047 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5048 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5052 if (min_resulting < 0) {
5057 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5058 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5062 /** Handle pending resizing of tracks */
5064 Editor::idle_resize ()
5066 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5068 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5069 selection->tracks.contains (_pending_resize_view)) {
5071 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5072 if (*i != _pending_resize_view) {
5073 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5078 _pending_resize_amount = 0;
5079 _group_tabs->set_dirty ();
5080 resize_idle_id = -1;
5088 ENSURE_GUI_THREAD (*this, &Editor::located);
5091 playhead_cursor->set_position (_session->audible_frame ());
5092 if (_follow_playhead && !_pending_initial_locate) {
5093 reset_x_origin_to_follow_playhead ();
5097 _pending_locate_request = false;
5098 _pending_initial_locate = false;
5102 Editor::region_view_added (RegionView * rv)
5104 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5105 if (rv->region ()->id () == (*pr)) {
5106 selection->add (rv);
5107 selection->regions.pending.erase (pr);
5112 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5114 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5115 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5116 if (rv->region()->id () == (*rnote).first) {
5117 mrv->select_notes ((*rnote).second);
5118 selection->pending_midi_note_selection.erase(rnote);
5124 _summary->set_background_dirty ();
5128 Editor::region_view_removed ()
5130 _summary->set_background_dirty ();
5134 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5136 TrackViewList::const_iterator j = track_views.begin ();
5137 while (j != track_views.end()) {
5138 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5139 if (rtv && rtv->route() == r) {
5150 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5154 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5155 TimeAxisView* tv = axis_view_from_route (*i);
5165 Editor::suspend_route_redisplay ()
5168 _routes->suspend_redisplay();
5173 Editor::resume_route_redisplay ()
5176 _routes->redisplay(); // queue redisplay
5177 _routes->resume_redisplay();
5182 Editor::add_routes (RouteList& routes)
5184 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5186 RouteTimeAxisView *rtv;
5187 list<RouteTimeAxisView*> new_views;
5188 TrackViewList new_selection;
5189 bool from_scratch = (track_views.size() == 0);
5191 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5192 boost::shared_ptr<Route> route = (*x);
5194 if (route->is_auditioner() || route->is_monitor()) {
5198 DataType dt = route->input()->default_type();
5200 if (dt == ARDOUR::DataType::AUDIO) {
5201 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5202 rtv->set_route (route);
5203 } else if (dt == ARDOUR::DataType::MIDI) {
5204 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5205 rtv->set_route (route);
5207 throw unknown_type();
5210 new_views.push_back (rtv);
5211 track_views.push_back (rtv);
5212 new_selection.push_back (rtv);
5214 rtv->effective_gain_display ();
5216 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5217 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5220 if (new_views.size() > 0) {
5221 _routes->routes_added (new_views);
5222 _summary->routes_added (new_views);
5225 if (!from_scratch) {
5226 selection->tracks.clear();
5227 selection->add (new_selection);
5228 begin_selection_op_history();
5231 if (show_editor_mixer_when_tracks_arrive) {
5232 show_editor_mixer (true);
5235 editor_list_button.set_sensitive (true);
5239 Editor::timeaxisview_deleted (TimeAxisView *tv)
5241 if (tv == entered_track) {
5245 if (_session && _session->deletion_in_progress()) {
5246 /* the situation is under control */
5250 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5252 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5254 _routes->route_removed (tv);
5256 TimeAxisView::Children c = tv->get_child_list ();
5257 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5258 if (entered_track == i->get()) {
5263 /* remove it from the list of track views */
5265 TrackViewList::iterator i;
5267 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5268 i = track_views.erase (i);
5271 /* update whatever the current mixer strip is displaying, if revelant */
5273 boost::shared_ptr<Route> route;
5276 route = rtav->route ();
5279 if (current_mixer_strip && current_mixer_strip->route() == route) {
5281 TimeAxisView* next_tv;
5283 if (track_views.empty()) {
5285 } else if (i == track_views.end()) {
5286 next_tv = track_views.front();
5293 set_selected_mixer_strip (*next_tv);
5295 /* make the editor mixer strip go away setting the
5296 * button to inactive (which also unticks the menu option)
5299 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5305 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5307 if (apply_to_selection) {
5308 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5310 TrackSelection::iterator j = i;
5313 hide_track_in_display (*i, false);
5318 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5320 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5321 // this will hide the mixer strip
5322 set_selected_mixer_strip (*tv);
5325 _routes->hide_track_in_display (*tv);
5330 Editor::sync_track_view_list_and_routes ()
5332 track_views = TrackViewList (_routes->views ());
5334 _summary->set_background_dirty();
5335 _group_tabs->set_dirty ();
5337 return false; // do not call again (until needed)
5341 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5343 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5348 /** Find a RouteTimeAxisView by the ID of its route */
5350 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5352 RouteTimeAxisView* v;
5354 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5355 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5356 if(v->route()->id() == id) {
5366 Editor::fit_route_group (RouteGroup *g)
5368 TrackViewList ts = axis_views_from_routes (g->route_list ());
5373 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5375 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5378 _session->cancel_audition ();
5382 if (_session->is_auditioning()) {
5383 _session->cancel_audition ();
5384 if (r == last_audition_region) {
5389 _session->audition_region (r);
5390 last_audition_region = r;
5395 Editor::hide_a_region (boost::shared_ptr<Region> r)
5397 r->set_hidden (true);
5401 Editor::show_a_region (boost::shared_ptr<Region> r)
5403 r->set_hidden (false);
5407 Editor::audition_region_from_region_list ()
5409 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5413 Editor::hide_region_from_region_list ()
5415 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5419 Editor::show_region_in_region_list ()
5421 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5425 Editor::step_edit_status_change (bool yn)
5428 start_step_editing ();
5430 stop_step_editing ();
5435 Editor::start_step_editing ()
5437 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5441 Editor::stop_step_editing ()
5443 step_edit_connection.disconnect ();
5447 Editor::check_step_edit ()
5449 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5450 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5452 mtv->check_step_edit ();
5456 return true; // do it again, till we stop
5460 Editor::scroll_press (Direction dir)
5462 ++_scroll_callbacks;
5464 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5465 /* delay the first auto-repeat */
5471 scroll_backward (1);
5479 scroll_up_one_track ();
5483 scroll_down_one_track ();
5487 /* do hacky auto-repeat */
5488 if (!_scroll_connection.connected ()) {
5490 _scroll_connection = Glib::signal_timeout().connect (
5491 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5494 _scroll_callbacks = 0;
5501 Editor::scroll_release ()
5503 _scroll_connection.disconnect ();
5506 /** Queue a change for the Editor viewport x origin to follow the playhead */
5508 Editor::reset_x_origin_to_follow_playhead ()
5510 framepos_t const frame = playhead_cursor->current_frame ();
5512 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5514 if (_session->transport_speed() < 0) {
5516 if (frame > (current_page_samples() / 2)) {
5517 center_screen (frame-(current_page_samples()/2));
5519 center_screen (current_page_samples()/2);
5526 if (frame < leftmost_frame) {
5528 if (_session->transport_rolling()) {
5529 /* rolling; end up with the playhead at the right of the page */
5530 l = frame - current_page_samples ();
5532 /* not rolling: end up with the playhead 1/4 of the way along the page */
5533 l = frame - current_page_samples() / 4;
5537 if (_session->transport_rolling()) {
5538 /* rolling: end up with the playhead on the left of the page */
5541 /* not rolling: end up with the playhead 3/4 of the way along the page */
5542 l = frame - 3 * current_page_samples() / 4;
5550 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5556 Editor::super_rapid_screen_update ()
5558 if (!_session || !_session->engine().running()) {
5562 /* METERING / MIXER STRIPS */
5564 /* update track meters, if required */
5565 if (contents().is_mapped() && meters_running) {
5566 RouteTimeAxisView* rtv;
5567 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5568 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5569 rtv->fast_update ();
5574 /* and any current mixer strip */
5575 if (current_mixer_strip) {
5576 current_mixer_strip->fast_update ();
5579 /* PLAYHEAD AND VIEWPORT */
5581 framepos_t const frame = _session->audible_frame();
5583 /* There are a few reasons why we might not update the playhead / viewport stuff:
5585 * 1. we don't update things when there's a pending locate request, otherwise
5586 * when the editor requests a locate there is a chance that this method
5587 * will move the playhead before the locate request is processed, causing
5589 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5590 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5593 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5595 last_update_frame = frame;
5597 if (!_dragging_playhead) {
5598 playhead_cursor->set_position (frame);
5601 if (!_stationary_playhead) {
5603 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5604 /* We only do this if we aren't already
5605 handling a visual change (ie if
5606 pending_visual_change.being_handled is
5607 false) so that these requests don't stack
5608 up there are too many of them to handle in
5611 reset_x_origin_to_follow_playhead ();
5616 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5617 framepos_t const frame = playhead_cursor->current_frame ();
5618 double target = ((double)frame - (double)current_page_samples()/2.0);
5619 if (target <= 0.0) {
5622 // compare to EditorCursor::set_position()
5623 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5624 double const new_pos = sample_to_pixel_unrounded (target);
5625 if (rint (new_pos) != rint (old_pos)) {
5626 reset_x_origin (pixel_to_sample (floor (new_pos)));
5637 Editor::session_going_away ()
5639 _have_idled = false;
5641 _session_connections.drop_connections ();
5643 super_rapid_screen_update_connection.disconnect ();
5645 selection->clear ();
5646 cut_buffer->clear ();
5648 clicked_regionview = 0;
5649 clicked_axisview = 0;
5650 clicked_routeview = 0;
5651 entered_regionview = 0;
5653 last_update_frame = 0;
5656 playhead_cursor->hide ();
5658 /* rip everything out of the list displays */
5662 _route_groups->clear ();
5664 /* do this first so that deleting a track doesn't reset cms to null
5665 and thus cause a leak.
5668 if (current_mixer_strip) {
5669 if (current_mixer_strip->get_parent() != 0) {
5670 global_hpacker.remove (*current_mixer_strip);
5672 delete current_mixer_strip;
5673 current_mixer_strip = 0;
5676 /* delete all trackviews */
5678 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5681 track_views.clear ();
5683 nudge_clock->set_session (0);
5685 editor_list_button.set_active(false);
5686 editor_list_button.set_sensitive(false);
5688 /* clear tempo/meter rulers */
5689 remove_metric_marks ();
5691 clear_marker_display ();
5693 stop_step_editing ();
5697 /* get rid of any existing editor mixer strip */
5699 WindowTitle title(Glib::get_application_name());
5700 title += _("Editor");
5702 own_window()->set_title (title.get_string());
5705 SessionHandlePtr::session_going_away ();
5710 Editor::show_editor_list (bool yn)
5713 _the_notebook.show ();
5715 _the_notebook.hide ();
5720 Editor::change_region_layering_order (bool from_context_menu)
5722 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5724 if (!clicked_routeview) {
5725 if (layering_order_editor) {
5726 layering_order_editor->hide ();
5731 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5737 boost::shared_ptr<Playlist> pl = track->playlist();
5743 if (layering_order_editor == 0) {
5744 layering_order_editor = new RegionLayeringOrderEditor (*this);
5747 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5748 layering_order_editor->maybe_present ();
5752 Editor::update_region_layering_order_editor ()
5754 if (layering_order_editor && layering_order_editor->is_visible ()) {
5755 change_region_layering_order (true);
5760 Editor::setup_fade_images ()
5762 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5763 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5764 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5765 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5766 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5768 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5769 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5770 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5771 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5772 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5774 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5775 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5776 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5777 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5778 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5780 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5781 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5782 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5783 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5784 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5788 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5790 Editor::action_menu_item (std::string const & name)
5792 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5795 return *manage (a->create_menu_item ());
5799 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5801 EventBox* b = manage (new EventBox);
5802 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5803 Label* l = manage (new Label (name));
5807 _the_notebook.append_page (widget, *b);
5811 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5813 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5814 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5817 if (ev->type == GDK_2BUTTON_PRESS) {
5819 /* double-click on a notebook tab shrinks or expands the notebook */
5821 if (_notebook_shrunk) {
5822 if (pre_notebook_shrink_pane_width) {
5823 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5825 _notebook_shrunk = false;
5827 pre_notebook_shrink_pane_width = edit_pane.get_position();
5829 /* this expands the LHS of the edit pane to cover the notebook
5830 PAGE but leaves the tabs visible.
5832 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5833 _notebook_shrunk = true;
5841 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5843 using namespace Menu_Helpers;
5845 MenuList& items = _control_point_context_menu.items ();
5848 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5849 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5850 if (!can_remove_control_point (item)) {
5851 items.back().set_sensitive (false);
5854 _control_point_context_menu.popup (event->button.button, event->button.time);
5858 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5860 using namespace Menu_Helpers;
5862 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5867 /* We need to get the selection here and pass it to the operations, since
5868 popping up the menu will cause a region leave event which clears
5869 entered_regionview. */
5871 MidiRegionView& mrv = note->region_view();
5872 const RegionSelection rs = get_regions_from_selection_and_entered ();
5873 const uint32_t sel_size = mrv.selection_size ();
5875 MenuList& items = _note_context_menu.items();
5879 items.push_back(MenuElem(_("Delete"),
5880 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5883 items.push_back(MenuElem(_("Edit..."),
5884 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5885 if (sel_size != 1) {
5886 items.back().set_sensitive (false);
5889 items.push_back(MenuElem(_("Transpose..."),
5890 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5893 items.push_back(MenuElem(_("Legatize"),
5894 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5896 items.back().set_sensitive (false);
5899 items.push_back(MenuElem(_("Quantize..."),
5900 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5902 items.push_back(MenuElem(_("Remove Overlap"),
5903 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5905 items.back().set_sensitive (false);
5908 items.push_back(MenuElem(_("Transform..."),
5909 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5911 _note_context_menu.popup (event->button.button, event->button.time);
5915 Editor::zoom_vertical_modifier_released()
5917 _stepping_axis_view = 0;
5921 Editor::ui_parameter_changed (string parameter)
5923 if (parameter == "icon-set") {
5924 while (!_cursor_stack.empty()) {
5925 _cursor_stack.pop_back();
5927 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5928 _cursor_stack.push_back(_cursors->grabber);
5929 } else if (parameter == "draggable-playhead") {
5930 if (_verbose_cursor) {
5931 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5937 Editor::use_own_window (bool and_fill_it)
5939 bool new_window = !own_window();
5941 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5943 if (win && new_window) {
5944 win->set_name ("EditorWindow");
5946 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5948 // win->signal_realize().connect (*this, &Editor::on_realize);
5949 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
5950 win->set_data ("ardour-bindings", &key_bindings);
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");