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 Gtk::Window* toplevel = current_toplevel();
4209 toplevel->fullscreen ();
4215 Editor::restore_editing_space ()
4221 Gtk::Window* toplevel = current_toplevel();
4224 toplevel->unfullscreen();
4230 * Make new playlists for a given track and also any others that belong
4231 * to the same active route group with the `select' property.
4236 Editor::new_playlists (TimeAxisView* v)
4238 begin_reversible_command (_("new playlists"));
4239 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4240 _session->playlists->get (playlists);
4241 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4242 commit_reversible_command ();
4246 * Use a copy of the current playlist for a given track and also any others that belong
4247 * to the same active route group with the `select' property.
4252 Editor::copy_playlists (TimeAxisView* v)
4254 begin_reversible_command (_("copy playlists"));
4255 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4256 _session->playlists->get (playlists);
4257 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4258 commit_reversible_command ();
4261 /** Clear the current playlist for a given track and also any others that belong
4262 * to the same active route group with the `select' property.
4267 Editor::clear_playlists (TimeAxisView* v)
4269 begin_reversible_command (_("clear playlists"));
4270 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4271 _session->playlists->get (playlists);
4272 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4273 commit_reversible_command ();
4277 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4279 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4283 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4285 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4289 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4291 atv.clear_playlist ();
4295 Editor::get_y_origin () const
4297 return vertical_adjustment.get_value ();
4300 /** Queue up a change to the viewport x origin.
4301 * @param frame New x origin.
4304 Editor::reset_x_origin (framepos_t frame)
4306 pending_visual_change.add (VisualChange::TimeOrigin);
4307 pending_visual_change.time_origin = frame;
4308 ensure_visual_change_idle_handler ();
4312 Editor::reset_y_origin (double y)
4314 pending_visual_change.add (VisualChange::YOrigin);
4315 pending_visual_change.y_origin = y;
4316 ensure_visual_change_idle_handler ();
4320 Editor::reset_zoom (framecnt_t spp)
4322 if (spp == samples_per_pixel) {
4326 pending_visual_change.add (VisualChange::ZoomLevel);
4327 pending_visual_change.samples_per_pixel = spp;
4328 ensure_visual_change_idle_handler ();
4332 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4334 reset_x_origin (frame);
4337 if (!no_save_visual) {
4338 undo_visual_stack.push_back (current_visual_state(false));
4342 Editor::VisualState::VisualState (bool with_tracks)
4343 : gui_state (with_tracks ? new GUIObjectState : 0)
4347 Editor::VisualState::~VisualState ()
4352 Editor::VisualState*
4353 Editor::current_visual_state (bool with_tracks)
4355 VisualState* vs = new VisualState (with_tracks);
4356 vs->y_position = vertical_adjustment.get_value();
4357 vs->samples_per_pixel = samples_per_pixel;
4358 vs->leftmost_frame = leftmost_frame;
4359 vs->zoom_focus = zoom_focus;
4362 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4369 Editor::undo_visual_state ()
4371 if (undo_visual_stack.empty()) {
4375 VisualState* vs = undo_visual_stack.back();
4376 undo_visual_stack.pop_back();
4379 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4382 use_visual_state (*vs);
4387 Editor::redo_visual_state ()
4389 if (redo_visual_stack.empty()) {
4393 VisualState* vs = redo_visual_stack.back();
4394 redo_visual_stack.pop_back();
4396 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4397 // why do we check here?
4398 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4401 use_visual_state (*vs);
4406 Editor::swap_visual_state ()
4408 if (undo_visual_stack.empty()) {
4409 redo_visual_state ();
4411 undo_visual_state ();
4416 Editor::use_visual_state (VisualState& vs)
4418 PBD::Unwinder<bool> nsv (no_save_visual, true);
4419 DisplaySuspender ds;
4421 vertical_adjustment.set_value (vs.y_position);
4423 set_zoom_focus (vs.zoom_focus);
4424 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4427 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4429 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4430 (*i)->clear_property_cache();
4431 (*i)->reset_visual_state ();
4435 _routes->update_visibility ();
4438 /** This is the core function that controls the zoom level of the canvas. It is called
4439 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4440 * @param spp new number of samples per pixel
4443 Editor::set_samples_per_pixel (framecnt_t spp)
4449 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4450 const framecnt_t lots_of_pixels = 4000;
4452 /* if the zoom level is greater than what you'd get trying to display 3
4453 * days of audio on a really big screen, then it's too big.
4456 if (spp * lots_of_pixels > three_days) {
4460 samples_per_pixel = spp;
4463 tempo_lines->tempo_map_changed();
4466 bool const showing_time_selection = selection->time.length() > 0;
4468 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4469 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4470 (*i)->reshow_selection (selection->time);
4474 ZoomChanged (); /* EMIT_SIGNAL */
4476 ArdourCanvas::GtkCanvasViewport* c;
4478 c = get_track_canvas();
4480 c->canvas()->zoomed ();
4483 if (playhead_cursor) {
4484 playhead_cursor->set_position (playhead_cursor->current_frame ());
4487 refresh_location_display();
4488 _summary->set_overlays_dirty ();
4490 update_marker_labels ();
4496 Editor::queue_visual_videotimeline_update ()
4499 * pending_visual_change.add (VisualChange::VideoTimeline);
4500 * or maybe even more specific: which videotimeline-image
4501 * currently it calls update_video_timeline() to update
4502 * _all outdated_ images on the video-timeline.
4503 * see 'exposeimg()' in video_image_frame.cc
4505 ensure_visual_change_idle_handler ();
4509 Editor::ensure_visual_change_idle_handler ()
4511 if (pending_visual_change.idle_handler_id < 0) {
4512 // see comment in add_to_idle_resize above.
4513 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4514 pending_visual_change.being_handled = false;
4519 Editor::_idle_visual_changer (void* arg)
4521 return static_cast<Editor*>(arg)->idle_visual_changer ();
4525 Editor::idle_visual_changer ()
4527 /* set_horizontal_position() below (and maybe other calls) call
4528 gtk_main_iteration(), so it's possible that a signal will be handled
4529 half-way through this method. If this signal wants an
4530 idle_visual_changer we must schedule another one after this one, so
4531 mark the idle_handler_id as -1 here to allow that. Also make a note
4532 that we are doing the visual change, so that changes in response to
4533 super-rapid-screen-update can be dropped if we are still processing
4537 pending_visual_change.idle_handler_id = -1;
4538 pending_visual_change.being_handled = true;
4540 VisualChange vc = pending_visual_change;
4542 pending_visual_change.pending = (VisualChange::Type) 0;
4544 visual_changer (vc);
4546 pending_visual_change.being_handled = false;
4548 return 0; /* this is always a one-shot call */
4552 Editor::visual_changer (const VisualChange& vc)
4554 double const last_time_origin = horizontal_position ();
4556 if (vc.pending & VisualChange::ZoomLevel) {
4557 set_samples_per_pixel (vc.samples_per_pixel);
4559 compute_fixed_ruler_scale ();
4561 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4562 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4564 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4565 current_bbt_points_begin, current_bbt_points_end);
4566 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4567 current_bbt_points_begin, current_bbt_points_end);
4568 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4570 update_video_timeline();
4573 if (vc.pending & VisualChange::TimeOrigin) {
4574 set_horizontal_position (vc.time_origin / samples_per_pixel);
4577 if (vc.pending & VisualChange::YOrigin) {
4578 vertical_adjustment.set_value (vc.y_origin);
4581 if (last_time_origin == horizontal_position ()) {
4582 /* changed signal not emitted */
4583 update_fixed_rulers ();
4584 redisplay_tempo (true);
4587 if (!(vc.pending & VisualChange::ZoomLevel)) {
4588 update_video_timeline();
4591 _summary->set_overlays_dirty ();
4594 struct EditorOrderTimeAxisSorter {
4595 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4596 return a->order () < b->order ();
4601 Editor::sort_track_selection (TrackViewList& sel)
4603 EditorOrderTimeAxisSorter cmp;
4608 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4611 framepos_t where = 0;
4612 EditPoint ep = _edit_point;
4614 if (Profile->get_mixbus())
4615 if (ep == EditAtSelectedMarker)
4616 ep = EditAtPlayhead;
4618 if (from_outside_canvas && (ep == EditAtMouse)) {
4619 ep = EditAtPlayhead;
4620 } else if (from_context_menu && (ep == EditAtMouse)) {
4621 return canvas_event_sample (&context_click_event, 0, 0);
4624 if (entered_marker) {
4625 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4626 return entered_marker->position();
4629 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4630 ep = EditAtSelectedMarker;
4633 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4634 ep = EditAtPlayhead;
4638 case EditAtPlayhead:
4639 if (_dragging_playhead) {
4640 where = *_control_scroll_target;
4642 where = _session->audible_frame();
4644 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4647 case EditAtSelectedMarker:
4648 if (!selection->markers.empty()) {
4650 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4653 where = loc->start();
4657 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4665 if (!mouse_frame (where, ignored)) {
4666 /* XXX not right but what can we do ? */
4670 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4678 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4680 if (!_session) return;
4682 begin_reversible_command (cmd);
4686 if ((tll = transport_loop_location()) == 0) {
4687 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4688 XMLNode &before = _session->locations()->get_state();
4689 _session->locations()->add (loc, true);
4690 _session->set_auto_loop_location (loc);
4691 XMLNode &after = _session->locations()->get_state();
4692 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4694 XMLNode &before = tll->get_state();
4695 tll->set_hidden (false, this);
4696 tll->set (start, end);
4697 XMLNode &after = tll->get_state();
4698 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4701 commit_reversible_command ();
4705 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4707 if (!_session) return;
4709 begin_reversible_command (cmd);
4713 if ((tpl = transport_punch_location()) == 0) {
4714 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4715 XMLNode &before = _session->locations()->get_state();
4716 _session->locations()->add (loc, true);
4717 _session->set_auto_punch_location (loc);
4718 XMLNode &after = _session->locations()->get_state();
4719 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4721 XMLNode &before = tpl->get_state();
4722 tpl->set_hidden (false, this);
4723 tpl->set (start, end);
4724 XMLNode &after = tpl->get_state();
4725 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4728 commit_reversible_command ();
4731 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4732 * @param rs List to which found regions are added.
4733 * @param where Time to look at.
4734 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4737 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4739 const TrackViewList* tracks;
4742 tracks = &track_views;
4747 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4749 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4752 boost::shared_ptr<Track> tr;
4753 boost::shared_ptr<Playlist> pl;
4755 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4757 boost::shared_ptr<RegionList> regions = pl->regions_at (
4758 (framepos_t) floor ( (double) where * tr->speed()));
4760 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4761 RegionView* rv = rtv->view()->find_view (*i);
4772 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4774 const TrackViewList* tracks;
4777 tracks = &track_views;
4782 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4783 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4785 boost::shared_ptr<Track> tr;
4786 boost::shared_ptr<Playlist> pl;
4788 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4790 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4791 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4793 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4795 RegionView* rv = rtv->view()->find_view (*i);
4806 /** Get regions using the following method:
4808 * Make a region list using:
4809 * (a) any selected regions
4810 * (b) the intersection of any selected tracks and the edit point(*)
4811 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4813 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4815 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4819 Editor::get_regions_from_selection_and_edit_point ()
4821 RegionSelection regions;
4823 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4824 regions.add (entered_regionview);
4826 regions = selection->regions;
4829 if ( regions.empty() ) {
4830 TrackViewList tracks = selection->tracks;
4832 if (!tracks.empty()) {
4833 /* no region selected or entered, but some selected tracks:
4834 * act on all regions on the selected tracks at the edit point
4836 framepos_t const where = get_preferred_edit_position ();
4837 get_regions_at(regions, where, tracks);
4844 /** Get regions using the following method:
4846 * Make a region list using:
4847 * (a) any selected regions
4848 * (b) the intersection of any selected tracks and the edit point(*)
4849 * (c) if neither exists, then whatever region is under the mouse
4851 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4853 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4856 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4858 RegionSelection regions;
4860 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4861 regions.add (entered_regionview);
4863 regions = selection->regions;
4866 if ( regions.empty() ) {
4867 TrackViewList tracks = selection->tracks;
4869 if (!tracks.empty()) {
4870 /* no region selected or entered, but some selected tracks:
4871 * act on all regions on the selected tracks at the edit point
4873 get_regions_at(regions, pos, tracks);
4880 /** Start with regions that are selected, or the entered regionview if none are selected.
4881 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4882 * of the regions that we started with.
4886 Editor::get_regions_from_selection_and_entered ()
4888 RegionSelection regions = selection->regions;
4890 if (regions.empty() && entered_regionview) {
4891 regions.add (entered_regionview);
4898 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4900 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4901 RouteTimeAxisView* rtav;
4903 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4904 boost::shared_ptr<Playlist> pl;
4905 std::vector<boost::shared_ptr<Region> > results;
4906 boost::shared_ptr<Track> tr;
4908 if ((tr = rtav->track()) == 0) {
4913 if ((pl = (tr->playlist())) != 0) {
4914 boost::shared_ptr<Region> r = pl->region_by_id (id);
4916 RegionView* rv = rtav->view()->find_view (r);
4918 regions.push_back (rv);
4927 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > > &selection) const
4930 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4931 MidiTimeAxisView* mtav;
4933 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4935 mtav->get_per_region_note_selection (selection);
4942 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4944 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4946 RouteTimeAxisView* tatv;
4948 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4950 boost::shared_ptr<Playlist> pl;
4951 vector<boost::shared_ptr<Region> > results;
4953 boost::shared_ptr<Track> tr;
4955 if ((tr = tatv->track()) == 0) {
4960 if ((pl = (tr->playlist())) != 0) {
4961 if (src_comparison) {
4962 pl->get_source_equivalent_regions (region, results);
4964 pl->get_region_list_equivalent_regions (region, results);
4968 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4969 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4970 regions.push_back (marv);
4979 Editor::show_rhythm_ferret ()
4981 if (rhythm_ferret == 0) {
4982 rhythm_ferret = new RhythmFerret(*this);
4985 rhythm_ferret->set_session (_session);
4986 rhythm_ferret->show ();
4987 rhythm_ferret->present ();
4991 Editor::first_idle ()
4993 MessageDialog* dialog = 0;
4995 if (track_views.size() > 1) {
4996 Timers::TimerSuspender t;
4997 dialog = new MessageDialog (
4998 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5002 ARDOUR_UI::instance()->flush_pending ();
5005 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5009 // first idle adds route children (automation tracks), so we need to redisplay here
5010 _routes->redisplay ();
5014 if (_session->undo_depth() == 0) {
5015 undo_action->set_sensitive(false);
5017 redo_action->set_sensitive(false);
5018 begin_selection_op_history ();
5024 Editor::_idle_resize (gpointer arg)
5026 return ((Editor*)arg)->idle_resize ();
5030 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5032 if (resize_idle_id < 0) {
5033 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5034 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5035 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5037 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5038 _pending_resize_amount = 0;
5041 /* make a note of the smallest resulting height, so that we can clamp the
5042 lower limit at TimeAxisView::hSmall */
5044 int32_t min_resulting = INT32_MAX;
5046 _pending_resize_amount += h;
5047 _pending_resize_view = view;
5049 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5051 if (selection->tracks.contains (_pending_resize_view)) {
5052 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5053 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5057 if (min_resulting < 0) {
5062 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5063 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5067 /** Handle pending resizing of tracks */
5069 Editor::idle_resize ()
5071 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5073 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5074 selection->tracks.contains (_pending_resize_view)) {
5076 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5077 if (*i != _pending_resize_view) {
5078 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5083 _pending_resize_amount = 0;
5084 _group_tabs->set_dirty ();
5085 resize_idle_id = -1;
5093 ENSURE_GUI_THREAD (*this, &Editor::located);
5096 playhead_cursor->set_position (_session->audible_frame ());
5097 if (_follow_playhead && !_pending_initial_locate) {
5098 reset_x_origin_to_follow_playhead ();
5102 _pending_locate_request = false;
5103 _pending_initial_locate = false;
5107 Editor::region_view_added (RegionView * rv)
5109 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5110 if (rv->region ()->id () == (*pr)) {
5111 selection->add (rv);
5112 selection->regions.pending.erase (pr);
5117 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5119 list<pair<PBD::ID const, list<boost::shared_ptr<Evoral::Note<Evoral::Beats> > > > >::iterator rnote;
5120 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5121 if (rv->region()->id () == (*rnote).first) {
5122 mrv->select_notes ((*rnote).second);
5123 selection->pending_midi_note_selection.erase(rnote);
5129 _summary->set_background_dirty ();
5133 Editor::region_view_removed ()
5135 _summary->set_background_dirty ();
5139 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
5141 TrackViewList::const_iterator j = track_views.begin ();
5142 while (j != track_views.end()) {
5143 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
5144 if (rtv && rtv->route() == r) {
5155 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5159 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5160 TimeAxisView* tv = axis_view_from_route (*i);
5170 Editor::suspend_route_redisplay ()
5173 _routes->suspend_redisplay();
5178 Editor::resume_route_redisplay ()
5181 _routes->redisplay(); // queue redisplay
5182 _routes->resume_redisplay();
5187 Editor::add_routes (RouteList& routes)
5189 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
5191 RouteTimeAxisView *rtv;
5192 list<RouteTimeAxisView*> new_views;
5193 TrackViewList new_selection;
5194 bool from_scratch = (track_views.size() == 0);
5196 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
5197 boost::shared_ptr<Route> route = (*x);
5199 if (route->is_auditioner() || route->is_monitor()) {
5203 DataType dt = route->input()->default_type();
5205 if (dt == ARDOUR::DataType::AUDIO) {
5206 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5207 rtv->set_route (route);
5208 } else if (dt == ARDOUR::DataType::MIDI) {
5209 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5210 rtv->set_route (route);
5212 throw unknown_type();
5215 new_views.push_back (rtv);
5216 track_views.push_back (rtv);
5217 new_selection.push_back (rtv);
5219 rtv->effective_gain_display ();
5221 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5222 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5225 if (new_views.size() > 0) {
5226 _routes->routes_added (new_views);
5227 _summary->routes_added (new_views);
5230 if (!from_scratch) {
5231 selection->tracks.clear();
5232 selection->add (new_selection);
5233 begin_selection_op_history();
5236 if (show_editor_mixer_when_tracks_arrive) {
5237 show_editor_mixer (true);
5240 editor_list_button.set_sensitive (true);
5244 Editor::timeaxisview_deleted (TimeAxisView *tv)
5246 if (tv == entered_track) {
5250 if (_session && _session->deletion_in_progress()) {
5251 /* the situation is under control */
5255 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5257 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5259 _routes->route_removed (tv);
5261 TimeAxisView::Children c = tv->get_child_list ();
5262 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5263 if (entered_track == i->get()) {
5268 /* remove it from the list of track views */
5270 TrackViewList::iterator i;
5272 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5273 i = track_views.erase (i);
5276 /* update whatever the current mixer strip is displaying, if revelant */
5278 boost::shared_ptr<Route> route;
5281 route = rtav->route ();
5284 if (current_mixer_strip && current_mixer_strip->route() == route) {
5286 TimeAxisView* next_tv;
5288 if (track_views.empty()) {
5290 } else if (i == track_views.end()) {
5291 next_tv = track_views.front();
5298 set_selected_mixer_strip (*next_tv);
5300 /* make the editor mixer strip go away setting the
5301 * button to inactive (which also unticks the menu option)
5304 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5310 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5312 if (apply_to_selection) {
5313 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5315 TrackSelection::iterator j = i;
5318 hide_track_in_display (*i, false);
5323 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5325 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5326 // this will hide the mixer strip
5327 set_selected_mixer_strip (*tv);
5330 _routes->hide_track_in_display (*tv);
5335 Editor::sync_track_view_list_and_routes ()
5337 track_views = TrackViewList (_routes->views ());
5339 _summary->set_background_dirty();
5340 _group_tabs->set_dirty ();
5342 return false; // do not call again (until needed)
5346 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5348 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5353 /** Find a RouteTimeAxisView by the ID of its route */
5355 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5357 RouteTimeAxisView* v;
5359 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5360 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5361 if(v->route()->id() == id) {
5371 Editor::fit_route_group (RouteGroup *g)
5373 TrackViewList ts = axis_views_from_routes (g->route_list ());
5378 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5380 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5383 _session->cancel_audition ();
5387 if (_session->is_auditioning()) {
5388 _session->cancel_audition ();
5389 if (r == last_audition_region) {
5394 _session->audition_region (r);
5395 last_audition_region = r;
5400 Editor::hide_a_region (boost::shared_ptr<Region> r)
5402 r->set_hidden (true);
5406 Editor::show_a_region (boost::shared_ptr<Region> r)
5408 r->set_hidden (false);
5412 Editor::audition_region_from_region_list ()
5414 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5418 Editor::hide_region_from_region_list ()
5420 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5424 Editor::show_region_in_region_list ()
5426 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5430 Editor::step_edit_status_change (bool yn)
5433 start_step_editing ();
5435 stop_step_editing ();
5440 Editor::start_step_editing ()
5442 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5446 Editor::stop_step_editing ()
5448 step_edit_connection.disconnect ();
5452 Editor::check_step_edit ()
5454 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5455 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5457 mtv->check_step_edit ();
5461 return true; // do it again, till we stop
5465 Editor::scroll_press (Direction dir)
5467 ++_scroll_callbacks;
5469 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5470 /* delay the first auto-repeat */
5476 scroll_backward (1);
5484 scroll_up_one_track ();
5488 scroll_down_one_track ();
5492 /* do hacky auto-repeat */
5493 if (!_scroll_connection.connected ()) {
5495 _scroll_connection = Glib::signal_timeout().connect (
5496 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5499 _scroll_callbacks = 0;
5506 Editor::scroll_release ()
5508 _scroll_connection.disconnect ();
5511 /** Queue a change for the Editor viewport x origin to follow the playhead */
5513 Editor::reset_x_origin_to_follow_playhead ()
5515 framepos_t const frame = playhead_cursor->current_frame ();
5517 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5519 if (_session->transport_speed() < 0) {
5521 if (frame > (current_page_samples() / 2)) {
5522 center_screen (frame-(current_page_samples()/2));
5524 center_screen (current_page_samples()/2);
5531 if (frame < leftmost_frame) {
5533 if (_session->transport_rolling()) {
5534 /* rolling; end up with the playhead at the right of the page */
5535 l = frame - current_page_samples ();
5537 /* not rolling: end up with the playhead 1/4 of the way along the page */
5538 l = frame - current_page_samples() / 4;
5542 if (_session->transport_rolling()) {
5543 /* rolling: end up with the playhead on the left of the page */
5546 /* not rolling: end up with the playhead 3/4 of the way along the page */
5547 l = frame - 3 * current_page_samples() / 4;
5555 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5561 Editor::super_rapid_screen_update ()
5563 if (!_session || !_session->engine().running()) {
5567 /* METERING / MIXER STRIPS */
5569 /* update track meters, if required */
5570 if (contents().is_mapped() && meters_running) {
5571 RouteTimeAxisView* rtv;
5572 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5573 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5574 rtv->fast_update ();
5579 /* and any current mixer strip */
5580 if (current_mixer_strip) {
5581 current_mixer_strip->fast_update ();
5584 /* PLAYHEAD AND VIEWPORT */
5586 framepos_t const frame = _session->audible_frame();
5588 /* There are a few reasons why we might not update the playhead / viewport stuff:
5590 * 1. we don't update things when there's a pending locate request, otherwise
5591 * when the editor requests a locate there is a chance that this method
5592 * will move the playhead before the locate request is processed, causing
5594 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5595 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5598 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5600 last_update_frame = frame;
5602 if (!_dragging_playhead) {
5603 playhead_cursor->set_position (frame);
5606 if (!_stationary_playhead) {
5608 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5609 /* We only do this if we aren't already
5610 handling a visual change (ie if
5611 pending_visual_change.being_handled is
5612 false) so that these requests don't stack
5613 up there are too many of them to handle in
5616 reset_x_origin_to_follow_playhead ();
5621 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5622 framepos_t const frame = playhead_cursor->current_frame ();
5623 double target = ((double)frame - (double)current_page_samples()/2.0);
5624 if (target <= 0.0) {
5627 // compare to EditorCursor::set_position()
5628 double const old_pos = sample_to_pixel_unrounded (leftmost_frame);
5629 double const new_pos = sample_to_pixel_unrounded (target);
5630 if (rint (new_pos) != rint (old_pos)) {
5631 reset_x_origin (pixel_to_sample (floor (new_pos)));
5642 Editor::session_going_away ()
5644 _have_idled = false;
5646 _session_connections.drop_connections ();
5648 super_rapid_screen_update_connection.disconnect ();
5650 selection->clear ();
5651 cut_buffer->clear ();
5653 clicked_regionview = 0;
5654 clicked_axisview = 0;
5655 clicked_routeview = 0;
5656 entered_regionview = 0;
5658 last_update_frame = 0;
5661 playhead_cursor->hide ();
5663 /* rip everything out of the list displays */
5667 _route_groups->clear ();
5669 /* do this first so that deleting a track doesn't reset cms to null
5670 and thus cause a leak.
5673 if (current_mixer_strip) {
5674 if (current_mixer_strip->get_parent() != 0) {
5675 global_hpacker.remove (*current_mixer_strip);
5677 delete current_mixer_strip;
5678 current_mixer_strip = 0;
5681 /* delete all trackviews */
5683 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5686 track_views.clear ();
5688 nudge_clock->set_session (0);
5690 editor_list_button.set_active(false);
5691 editor_list_button.set_sensitive(false);
5693 /* clear tempo/meter rulers */
5694 remove_metric_marks ();
5696 clear_marker_display ();
5698 stop_step_editing ();
5702 /* get rid of any existing editor mixer strip */
5704 WindowTitle title(Glib::get_application_name());
5705 title += _("Editor");
5707 own_window()->set_title (title.get_string());
5710 SessionHandlePtr::session_going_away ();
5715 Editor::show_editor_list (bool yn)
5718 _the_notebook.show ();
5720 _the_notebook.hide ();
5725 Editor::change_region_layering_order (bool from_context_menu)
5727 const framepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5729 if (!clicked_routeview) {
5730 if (layering_order_editor) {
5731 layering_order_editor->hide ();
5736 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5742 boost::shared_ptr<Playlist> pl = track->playlist();
5748 if (layering_order_editor == 0) {
5749 layering_order_editor = new RegionLayeringOrderEditor (*this);
5752 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5753 layering_order_editor->maybe_present ();
5757 Editor::update_region_layering_order_editor ()
5759 if (layering_order_editor && layering_order_editor->is_visible ()) {
5760 change_region_layering_order (true);
5765 Editor::setup_fade_images ()
5767 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5768 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5769 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5770 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5771 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5773 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5774 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5775 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5776 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5777 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5779 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5780 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5781 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5782 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5783 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5785 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5786 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5787 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5788 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5789 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5793 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5795 Editor::action_menu_item (std::string const & name)
5797 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5800 return *manage (a->create_menu_item ());
5804 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5806 EventBox* b = manage (new EventBox);
5807 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5808 Label* l = manage (new Label (name));
5812 _the_notebook.append_page (widget, *b);
5816 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5818 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5819 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5822 if (ev->type == GDK_2BUTTON_PRESS) {
5824 /* double-click on a notebook tab shrinks or expands the notebook */
5826 if (_notebook_shrunk) {
5827 if (pre_notebook_shrink_pane_width) {
5828 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5830 _notebook_shrunk = false;
5832 pre_notebook_shrink_pane_width = edit_pane.get_position();
5834 /* this expands the LHS of the edit pane to cover the notebook
5835 PAGE but leaves the tabs visible.
5837 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5838 _notebook_shrunk = true;
5846 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5848 using namespace Menu_Helpers;
5850 MenuList& items = _control_point_context_menu.items ();
5853 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5854 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5855 if (!can_remove_control_point (item)) {
5856 items.back().set_sensitive (false);
5859 _control_point_context_menu.popup (event->button.button, event->button.time);
5863 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5865 using namespace Menu_Helpers;
5867 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
5872 /* We need to get the selection here and pass it to the operations, since
5873 popping up the menu will cause a region leave event which clears
5874 entered_regionview. */
5876 MidiRegionView& mrv = note->region_view();
5877 const RegionSelection rs = get_regions_from_selection_and_entered ();
5878 const uint32_t sel_size = mrv.selection_size ();
5880 MenuList& items = _note_context_menu.items();
5884 items.push_back(MenuElem(_("Delete"),
5885 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
5888 items.push_back(MenuElem(_("Edit..."),
5889 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
5890 if (sel_size != 1) {
5891 items.back().set_sensitive (false);
5894 items.push_back(MenuElem(_("Transpose..."),
5895 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
5898 items.push_back(MenuElem(_("Legatize"),
5899 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
5901 items.back().set_sensitive (false);
5904 items.push_back(MenuElem(_("Quantize..."),
5905 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
5907 items.push_back(MenuElem(_("Remove Overlap"),
5908 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
5910 items.back().set_sensitive (false);
5913 items.push_back(MenuElem(_("Transform..."),
5914 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
5916 _note_context_menu.popup (event->button.button, event->button.time);
5920 Editor::zoom_vertical_modifier_released()
5922 _stepping_axis_view = 0;
5926 Editor::ui_parameter_changed (string parameter)
5928 if (parameter == "icon-set") {
5929 while (!_cursor_stack.empty()) {
5930 _cursor_stack.pop_back();
5932 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
5933 _cursor_stack.push_back(_cursors->grabber);
5934 } else if (parameter == "draggable-playhead") {
5935 if (_verbose_cursor) {
5936 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
5942 Editor::use_own_window (bool and_fill_it)
5944 bool new_window = !own_window();
5946 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
5948 if (win && new_window) {
5949 win->set_name ("EditorWindow");
5951 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
5953 // win->signal_realize().connect (*this, &Editor::on_realize);
5954 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
5955 win->set_data ("ardour-bindings", &key_bindings);
5960 DisplaySuspender ds;
5961 contents().show_all ();
5963 /* XXX: this is a bit unfortunate; it would probably
5964 be nicer if we could just call show () above rather
5965 than needing the show_all ()
5968 /* re-hide stuff if necessary */
5969 editor_list_button_toggled ();
5970 parameter_changed ("show-summary");
5971 parameter_changed ("show-group-tabs");
5972 parameter_changed ("show-zoom-tools");
5974 /* now reset all audio_time_axis heights, because widgets might need
5980 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5981 tv = (static_cast<TimeAxisView*>(*i));
5982 tv->reset_height ();
5985 if (current_mixer_strip) {
5986 current_mixer_strip->hide_things ();
5987 current_mixer_strip->parameter_changed ("mixer-element-visibility");