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/location.h"
72 #include "ardour/profile.h"
73 #include "ardour/route_group.h"
74 #include "ardour/session_playlists.h"
75 #include "ardour/tempo.h"
76 #include "ardour/utils.h"
78 #include "canvas/debug.h"
79 #include "canvas/text.h"
81 #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_time_axis.h"
111 #include "mixer_strip.h"
112 #include "mixer_ui.h"
113 #include "mouse_cursors.h"
114 #include "playlist_selector.h"
115 #include "public_editor.h"
116 #include "region_layering_order_editor.h"
117 #include "rgb_macros.h"
118 #include "rhythm_ferret.h"
119 #include "selection.h"
121 #include "tempo_lines.h"
122 #include "time_axis_view.h"
124 #include "verbose_cursor.h"
129 using namespace ARDOUR;
130 using namespace ARDOUR_UI_UTILS;
133 using namespace Glib;
134 using namespace Gtkmm2ext;
135 using namespace Editing;
137 using PBD::internationalize;
139 using Gtkmm2ext::Keyboard;
141 const double Editor::timebar_height = 15.0;
143 static const gchar *_snap_type_strings[] = {
177 static const gchar *_snap_mode_strings[] = {
184 static const gchar *_edit_point_strings[] = {
191 static const gchar *_edit_mode_strings[] = {
199 static const gchar *_zoom_focus_strings[] = {
209 #ifdef USE_RUBBERBAND
210 static const gchar *_rb_opt_strings[] = {
213 N_("Balanced multitimbral mixture"),
214 N_("Unpitched percussion with stable notes"),
215 N_("Crisp monophonic instrumental"),
216 N_("Unpitched solo percussion"),
217 N_("Resample without preserving pitch"),
223 pane_size_watcher (Paned* pane)
225 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
229 Quartz: impossible to access
231 so stop that by preventing it from ever getting too narrow. 35
232 pixels is basically a rough guess at the tab width.
237 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
239 gint pos = pane->get_position ();
241 if (pos > max_width_of_lhs) {
242 pane->set_position (max_width_of_lhs);
247 : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
249 /* time display buttons */
250 , minsec_label (_("Mins:Secs"))
251 , bbt_label (_("Bars:Beats"))
252 , timecode_label (_("Timecode"))
253 , samples_label (_("Samples"))
254 , tempo_label (_("Tempo"))
255 , meter_label (_("Meter"))
256 , mark_label (_("Location Markers"))
257 , range_mark_label (_("Range Markers"))
258 , transport_mark_label (_("Loop/Punch Ranges"))
259 , cd_mark_label (_("CD Markers"))
260 , videotl_label (_("Video Timeline"))
261 , edit_packer (4, 4, true)
263 /* the values here don't matter: layout widgets
264 reset them as needed.
267 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
268 , horizontal_adjustment (0.0, 0.0, 1e16)
269 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
271 , controls_layout (unused_adjustment, vertical_adjustment)
273 /* tool bar related */
275 , toolbar_selection_clock_table (2,3)
276 , _mouse_mode_tearoff (0)
277 , automation_mode_button (_("mode"))
281 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
285 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
286 , meters_running(false)
287 , _pending_locate_request (false)
288 , _pending_initial_locate (false)
289 , _last_cut_copy_source_track (0)
291 , _region_selection_change_updates_region_list (true)
292 , _following_mixer_selection (false)
293 , _control_point_toggled_on_press (false)
294 , _stepping_axis_view (0)
298 /* we are a singleton */
300 PublicEditor::_instance = this;
304 selection = new Selection (this);
305 cut_buffer = new Selection (this);
307 clicked_regionview = 0;
308 clicked_axisview = 0;
309 clicked_routeview = 0;
310 clicked_control_point = 0;
311 last_update_frame = 0;
312 pre_press_cursor = 0;
313 _drags = new DragManager (this);
316 current_mixer_strip = 0;
319 snap_type_strings = I18N (_snap_type_strings);
320 snap_mode_strings = I18N (_snap_mode_strings);
321 zoom_focus_strings = I18N (_zoom_focus_strings);
322 edit_mode_strings = I18N (_edit_mode_strings);
323 edit_point_strings = I18N (_edit_point_strings);
324 #ifdef USE_RUBBERBAND
325 rb_opt_strings = I18N (_rb_opt_strings);
329 build_edit_mode_menu();
330 build_zoom_focus_menu();
331 build_track_count_menu();
332 build_snap_mode_menu();
333 build_snap_type_menu();
334 build_edit_point_menu();
336 snap_threshold = 5.0;
337 bbt_beat_subdivision = 4;
338 _visible_canvas_width = 0;
339 _visible_canvas_height = 0;
340 autoscroll_horizontal_allowed = false;
341 autoscroll_vertical_allowed = false;
346 current_interthread_info = 0;
347 _show_measures = true;
349 show_gain_after_trim = false;
351 have_pending_keyboard_selection = false;
352 _follow_playhead = true;
353 _stationary_playhead = false;
354 editor_ruler_menu = 0;
355 no_ruler_shown_update = false;
357 range_marker_menu = 0;
358 marker_menu_item = 0;
359 tempo_or_meter_marker_menu = 0;
360 transport_marker_menu = 0;
361 new_transport_marker_menu = 0;
362 editor_mixer_strip_width = Wide;
363 show_editor_mixer_when_tracks_arrive = false;
364 region_edit_menu_split_multichannel_item = 0;
365 region_edit_menu_split_item = 0;
368 current_stepping_trackview = 0;
370 entered_regionview = 0;
372 clear_entered_track = false;
375 button_release_can_deselect = true;
376 _dragging_playhead = false;
377 _dragging_edit_point = false;
378 select_new_marker = false;
380 layering_order_editor = 0;
381 no_save_visual = false;
383 within_track_canvas = false;
385 scrubbing_direction = 0;
389 location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
390 location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
391 location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
392 location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
393 location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
395 zoom_focus = ZoomFocusLeft;
396 _edit_point = EditAtMouse;
397 _internal_editing = false;
398 current_canvas_cursor = 0;
399 _visible_track_count = 16;
401 samples_per_pixel = 2048; /* too early to use reset_zoom () */
403 _scroll_callbacks = 0;
405 bbt_label.set_name ("EditorRulerLabel");
406 bbt_label.set_size_request (-1, (int)timebar_height);
407 bbt_label.set_alignment (1.0, 0.5);
408 bbt_label.set_padding (5,0);
410 bbt_label.set_no_show_all();
411 minsec_label.set_name ("EditorRulerLabel");
412 minsec_label.set_size_request (-1, (int)timebar_height);
413 minsec_label.set_alignment (1.0, 0.5);
414 minsec_label.set_padding (5,0);
415 minsec_label.hide ();
416 minsec_label.set_no_show_all();
417 timecode_label.set_name ("EditorRulerLabel");
418 timecode_label.set_size_request (-1, (int)timebar_height);
419 timecode_label.set_alignment (1.0, 0.5);
420 timecode_label.set_padding (5,0);
421 timecode_label.hide ();
422 timecode_label.set_no_show_all();
423 samples_label.set_name ("EditorRulerLabel");
424 samples_label.set_size_request (-1, (int)timebar_height);
425 samples_label.set_alignment (1.0, 0.5);
426 samples_label.set_padding (5,0);
427 samples_label.hide ();
428 samples_label.set_no_show_all();
430 tempo_label.set_name ("EditorRulerLabel");
431 tempo_label.set_size_request (-1, (int)timebar_height);
432 tempo_label.set_alignment (1.0, 0.5);
433 tempo_label.set_padding (5,0);
435 tempo_label.set_no_show_all();
437 meter_label.set_name ("EditorRulerLabel");
438 meter_label.set_size_request (-1, (int)timebar_height);
439 meter_label.set_alignment (1.0, 0.5);
440 meter_label.set_padding (5,0);
442 meter_label.set_no_show_all();
444 if (Profile->get_trx()) {
445 mark_label.set_text (_("Markers"));
447 mark_label.set_name ("EditorRulerLabel");
448 mark_label.set_size_request (-1, (int)timebar_height);
449 mark_label.set_alignment (1.0, 0.5);
450 mark_label.set_padding (5,0);
452 mark_label.set_no_show_all();
454 cd_mark_label.set_name ("EditorRulerLabel");
455 cd_mark_label.set_size_request (-1, (int)timebar_height);
456 cd_mark_label.set_alignment (1.0, 0.5);
457 cd_mark_label.set_padding (5,0);
458 cd_mark_label.hide();
459 cd_mark_label.set_no_show_all();
461 videotl_bar_height = 4;
462 videotl_label.set_name ("EditorRulerLabel");
463 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
464 videotl_label.set_alignment (1.0, 0.5);
465 videotl_label.set_padding (5,0);
466 videotl_label.hide();
467 videotl_label.set_no_show_all();
469 range_mark_label.set_name ("EditorRulerLabel");
470 range_mark_label.set_size_request (-1, (int)timebar_height);
471 range_mark_label.set_alignment (1.0, 0.5);
472 range_mark_label.set_padding (5,0);
473 range_mark_label.hide();
474 range_mark_label.set_no_show_all();
476 transport_mark_label.set_name ("EditorRulerLabel");
477 transport_mark_label.set_size_request (-1, (int)timebar_height);
478 transport_mark_label.set_alignment (1.0, 0.5);
479 transport_mark_label.set_padding (5,0);
480 transport_mark_label.hide();
481 transport_mark_label.set_no_show_all();
483 initialize_canvas ();
485 _summary = new EditorSummary (this);
487 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
488 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
490 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
492 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
493 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
495 edit_controls_vbox.set_spacing (0);
496 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
497 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
499 HBox* h = manage (new HBox);
500 _group_tabs = new EditorGroupTabs (this);
501 if (!ARDOUR::Profile->get_trx()) {
502 h->pack_start (*_group_tabs, PACK_SHRINK);
504 h->pack_start (edit_controls_vbox);
505 controls_layout.add (*h);
507 controls_layout.set_name ("EditControlsBase");
508 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
509 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
510 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
512 _cursors = new MouseCursors;
513 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
514 cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
516 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
518 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
519 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
520 pad_line_1->set_outline_color (0xFF0000FF);
526 edit_packer.set_col_spacings (0);
527 edit_packer.set_row_spacings (0);
528 edit_packer.set_homogeneous (false);
529 edit_packer.set_border_width (0);
530 edit_packer.set_name ("EditorWindow");
532 time_bars_event_box.add (time_bars_vbox);
533 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
534 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
536 /* labels for the time bars */
537 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
539 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
541 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
543 bottom_hbox.set_border_width (2);
544 bottom_hbox.set_spacing (3);
546 _route_groups = new EditorRouteGroups (this);
547 _routes = new EditorRoutes (this);
548 _regions = new EditorRegions (this);
549 _snapshots = new EditorSnapshots (this);
550 _locations = new EditorLocations (this);
552 add_notebook_page (_("Regions"), _regions->widget ());
553 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
554 add_notebook_page (_("Snapshots"), _snapshots->widget ());
555 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
556 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
558 _the_notebook.set_show_tabs (true);
559 _the_notebook.set_scrollable (true);
560 _the_notebook.popup_disable ();
561 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
562 _the_notebook.show_all ();
564 _notebook_shrunk = false;
566 editor_summary_pane.pack1(edit_packer);
568 Button* summary_arrows_left_left = manage (new Button);
569 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
570 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
571 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
573 Button* summary_arrows_left_right = manage (new Button);
574 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
575 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
576 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
578 VBox* summary_arrows_left = manage (new VBox);
579 summary_arrows_left->pack_start (*summary_arrows_left_left);
580 summary_arrows_left->pack_start (*summary_arrows_left_right);
582 Button* summary_arrows_right_up = manage (new Button);
583 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
584 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
585 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
587 Button* summary_arrows_right_down = manage (new Button);
588 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
589 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
590 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
592 VBox* summary_arrows_right = manage (new VBox);
593 summary_arrows_right->pack_start (*summary_arrows_right_up);
594 summary_arrows_right->pack_start (*summary_arrows_right_down);
596 Frame* summary_frame = manage (new Frame);
597 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
599 summary_frame->add (*_summary);
600 summary_frame->show ();
602 _summary_hbox.pack_start (*summary_arrows_left, false, false);
603 _summary_hbox.pack_start (*summary_frame, true, true);
604 _summary_hbox.pack_start (*summary_arrows_right, false, false);
606 if (!ARDOUR::Profile->get_trx()) {
607 editor_summary_pane.pack2 (_summary_hbox);
610 edit_pane.pack1 (editor_summary_pane, true, true);
611 if (!ARDOUR::Profile->get_trx()) {
612 edit_pane.pack2 (_the_notebook, false, true);
615 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
617 /* XXX: editor_summary_pane might need similar to the edit_pane */
619 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
621 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
622 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
624 top_hbox.pack_start (toolbar_frame);
626 HBox *hbox = manage (new HBox);
627 hbox->pack_start (edit_pane, true, true);
629 global_vpacker.pack_start (top_hbox, false, false);
630 global_vpacker.pack_start (*hbox, true, true);
632 global_hpacker.pack_start (global_vpacker, true, true);
634 set_name ("EditorWindow");
635 add_accel_group (ActionManager::ui_manager->get_accel_group());
637 status_bar_hpacker.show ();
639 vpacker.pack_end (status_bar_hpacker, false, false);
640 vpacker.pack_end (global_hpacker, true, true);
642 /* register actions now so that set_state() can find them and set toggles/checks etc */
645 /* when we start using our own keybinding system for the editor, this
646 * will be uncommented
652 set_zoom_focus (zoom_focus);
653 set_visible_track_count (_visible_track_count);
654 _snap_type = SnapToBeat;
655 set_snap_to (_snap_type);
656 _snap_mode = SnapOff;
657 set_snap_mode (_snap_mode);
658 set_mouse_mode (MouseObject, true);
659 pre_internal_mouse_mode = MouseObject;
660 pre_internal_snap_type = _snap_type;
661 pre_internal_snap_mode = _snap_mode;
662 internal_snap_type = _snap_type;
663 internal_snap_mode = _snap_mode;
664 set_edit_point_preference (EditAtMouse, true);
666 _playlist_selector = new PlaylistSelector();
667 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
669 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
673 nudge_forward_button.set_name ("nudge button");
674 // nudge_forward_button.add_elements (ArdourButton::Inset);
675 nudge_forward_button.set_image(::get_icon("nudge_right"));
677 nudge_backward_button.set_name ("nudge button");
678 // nudge_backward_button.add_elements (ArdourButton::Inset);
679 nudge_backward_button.set_image(::get_icon("nudge_left"));
681 fade_context_menu.set_name ("ArdourContextMenu");
683 /* icons, titles, WM stuff */
685 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
686 Glib::RefPtr<Gdk::Pixbuf> icon;
688 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
689 window_icons.push_back (icon);
691 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
692 window_icons.push_back (icon);
694 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
695 window_icons.push_back (icon);
697 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
698 window_icons.push_back (icon);
700 if (!window_icons.empty()) {
701 // set_icon_list (window_icons);
702 set_default_icon_list (window_icons);
705 WindowTitle title(Glib::get_application_name());
706 title += _("Editor");
707 set_title (title.get_string());
708 set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
711 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
713 signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
714 signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
716 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
718 /* allow external control surfaces/protocols to do various things */
720 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
721 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
722 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
723 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
724 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
725 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
726 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
727 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
728 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
729 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
730 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
731 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
732 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
733 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
735 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
736 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
737 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
738 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
739 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
741 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
743 /* problematic: has to return a value and thus cannot be x-thread */
745 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
747 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
748 ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
750 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
752 _ignore_region_action = false;
753 _last_region_menu_was_main = false;
754 _popup_region_menu_item = 0;
756 _ignore_follow_edits = false;
758 _show_marker_lines = false;
760 /* Button bindings */
762 button_bindings = new Bindings;
764 XMLNode* node = button_settings();
766 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
767 button_bindings->load (**i);
773 /* grab current parameter state */
774 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
775 ARDOUR_UI::config()->map_parameters (pc);
777 setup_fade_images ();
784 delete button_bindings;
786 delete _route_groups;
787 delete _track_canvas_viewport;
792 Editor::button_settings () const
794 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
795 XMLNode* node = find_named_node (*settings, X_("Buttons"));
798 node = new XMLNode (X_("Buttons"));
805 Editor::add_toplevel_controls (Container& cont)
807 vpacker.pack_start (cont, false, false);
812 Editor::get_smart_mode () const
814 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
818 Editor::catch_vanishing_regionview (RegionView *rv)
820 /* note: the selection will take care of the vanishing
821 audioregionview by itself.
824 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
828 if (clicked_regionview == rv) {
829 clicked_regionview = 0;
832 if (entered_regionview == rv) {
833 set_entered_regionview (0);
836 if (!_all_region_actions_sensitized) {
837 sensitize_all_region_actions (true);
842 Editor::set_entered_regionview (RegionView* rv)
844 if (rv == entered_regionview) {
848 if (entered_regionview) {
849 entered_regionview->exited ();
852 entered_regionview = rv;
854 if (entered_regionview != 0) {
855 entered_regionview->entered (internal_editing ());
858 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
859 /* This RegionView entry might have changed what region actions
860 are allowed, so sensitize them all in case a key is pressed.
862 sensitize_all_region_actions (true);
867 Editor::set_entered_track (TimeAxisView* tav)
870 entered_track->exited ();
876 entered_track->entered ();
881 Editor::show_window ()
883 if (!is_visible ()) {
886 /* XXX: this is a bit unfortunate; it would probably
887 be nicer if we could just call show () above rather
888 than needing the show_all ()
891 /* re-hide stuff if necessary */
892 editor_list_button_toggled ();
893 parameter_changed ("show-summary");
894 parameter_changed ("show-group-tabs");
895 parameter_changed ("show-zoom-tools");
897 /* now reset all audio_time_axis heights, because widgets might need
903 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
904 tv = (static_cast<TimeAxisView*>(*i));
908 if (current_mixer_strip) {
909 current_mixer_strip->hide_things ();
910 current_mixer_strip->parameter_changed ("mixer-strip-visibility");
918 Editor::instant_save ()
920 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
925 _session->add_instant_xml(get_state());
927 Config->add_instant_xml(get_state());
932 Editor::control_vertical_zoom_in_all ()
934 tav_zoom_smooth (false, true);
938 Editor::control_vertical_zoom_out_all ()
940 tav_zoom_smooth (true, true);
944 Editor::control_vertical_zoom_in_selected ()
946 tav_zoom_smooth (false, false);
950 Editor::control_vertical_zoom_out_selected ()
952 tav_zoom_smooth (true, false);
956 Editor::control_view (uint32_t view)
958 goto_visual_state (view);
962 Editor::control_unselect ()
964 selection->clear_tracks ();
968 Editor::control_select (uint32_t rid, Selection::Operation op)
970 /* handles the (static) signal from the ControlProtocol class that
971 * requests setting the selected track to a given RID
978 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
984 TimeAxisView* tav = axis_view_from_route (r);
989 selection->add (tav);
991 case Selection::Toggle:
992 selection->toggle (tav);
994 case Selection::Extend:
997 selection->set (tav);
1001 selection->clear_tracks ();
1006 Editor::control_step_tracks_up ()
1008 scroll_tracks_up_line ();
1012 Editor::control_step_tracks_down ()
1014 scroll_tracks_down_line ();
1018 Editor::control_scroll (float fraction)
1020 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1026 double step = fraction * current_page_samples();
1029 _control_scroll_target is an optional<T>
1031 it acts like a pointer to an framepos_t, with
1032 a operator conversion to boolean to check
1033 that it has a value could possibly use
1034 playhead_cursor->current_frame to store the
1035 value and a boolean in the class to know
1036 when it's out of date
1039 if (!_control_scroll_target) {
1040 _control_scroll_target = _session->transport_frame();
1041 _dragging_playhead = true;
1044 if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
1045 *_control_scroll_target = 0;
1046 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1047 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1049 *_control_scroll_target += (framepos_t) floor (step);
1052 /* move visuals, we'll catch up with it later */
1054 playhead_cursor->set_position (*_control_scroll_target);
1055 UpdateAllTransportClocks (*_control_scroll_target);
1057 if (*_control_scroll_target > (current_page_samples() / 2)) {
1058 /* try to center PH in window */
1059 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1065 Now we do a timeout to actually bring the session to the right place
1066 according to the playhead. This is to avoid reading disk buffers on every
1067 call to control_scroll, which is driven by ScrollTimeline and therefore
1068 probably by a control surface wheel which can generate lots of events.
1070 /* cancel the existing timeout */
1072 control_scroll_connection.disconnect ();
1074 /* add the next timeout */
1076 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1080 Editor::deferred_control_scroll (framepos_t /*target*/)
1082 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1083 // reset for next stream
1084 _control_scroll_target = boost::none;
1085 _dragging_playhead = false;
1090 Editor::access_action (std::string action_group, std::string action_item)
1096 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1099 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1107 Editor::on_realize ()
1109 Window::on_realize ();
1112 if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1113 start_lock_event_timing ();
1116 signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
1120 Editor::start_lock_event_timing ()
1122 /* check if we should lock the GUI every 30 seconds */
1124 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1128 Editor::generic_event_handler (GdkEvent* ev)
1131 case GDK_BUTTON_PRESS:
1132 case GDK_BUTTON_RELEASE:
1133 case GDK_MOTION_NOTIFY:
1135 case GDK_KEY_RELEASE:
1136 gettimeofday (&last_event_time, 0);
1145 Editor::lock_timeout_callback ()
1147 struct timeval now, delta;
1149 gettimeofday (&now, 0);
1151 timersub (&now, &last_event_time, &delta);
1153 if (delta.tv_sec > ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1155 /* don't call again. Returning false will effectively
1156 disconnect us from the timer callback.
1158 unlock() will call start_lock_event_timing() to get things
1168 Editor::map_position_change (framepos_t frame)
1170 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1172 if (_session == 0) {
1176 if (_follow_playhead) {
1177 center_screen (frame);
1180 playhead_cursor->set_position (frame);
1184 Editor::center_screen (framepos_t frame)
1186 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1188 /* if we're off the page, then scroll.
1191 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1192 center_screen_internal (frame, page);
1197 Editor::center_screen_internal (framepos_t frame, float page)
1202 frame -= (framepos_t) page;
1207 reset_x_origin (frame);
1212 Editor::update_title ()
1214 ENSURE_GUI_THREAD (*this, &Editor::update_title)
1217 bool dirty = _session->dirty();
1219 string session_name;
1221 if (_session->snap_name() != _session->name()) {
1222 session_name = _session->snap_name();
1224 session_name = _session->name();
1228 session_name = "*" + session_name;
1231 WindowTitle title(session_name);
1232 title += Glib::get_application_name();
1233 set_title (title.get_string());
1235 /* ::session_going_away() will have taken care of it */
1240 Editor::set_session (Session *t)
1242 SessionHandlePtr::set_session (t);
1248 _playlist_selector->set_session (_session);
1249 nudge_clock->set_session (_session);
1250 _summary->set_session (_session);
1251 _group_tabs->set_session (_session);
1252 _route_groups->set_session (_session);
1253 _regions->set_session (_session);
1254 _snapshots->set_session (_session);
1255 _routes->set_session (_session);
1256 _locations->set_session (_session);
1258 if (rhythm_ferret) {
1259 rhythm_ferret->set_session (_session);
1262 if (analysis_window) {
1263 analysis_window->set_session (_session);
1267 sfbrowser->set_session (_session);
1270 compute_fixed_ruler_scale ();
1272 /* Make sure we have auto loop and auto punch ranges */
1274 Location* loc = _session->locations()->auto_loop_location();
1276 loc->set_name (_("Loop"));
1279 loc = _session->locations()->auto_punch_location();
1282 loc->set_name (_("Punch"));
1285 refresh_location_display ();
1287 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1288 the selected Marker; this needs the LocationMarker list to be available.
1290 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1291 set_state (*node, Stateful::loading_state_version);
1293 /* catch up with the playhead */
1295 _session->request_locate (playhead_cursor->current_frame ());
1296 _pending_initial_locate = true;
1300 /* These signals can all be emitted by a non-GUI thread. Therefore the
1301 handlers for them must not attempt to directly interact with the GUI,
1302 but use PBD::Signal<T>::connect() which accepts an event loop
1303 ("context") where the handler will be asked to run.
1306 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1307 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1308 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1309 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1310 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1311 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1312 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1313 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1314 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1315 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1316 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1317 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1318 _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1319 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1321 playhead_cursor->show ();
1323 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1324 Config->map_parameters (pc);
1325 _session->config.map_parameters (pc);
1327 restore_ruler_visibility ();
1328 //tempo_map_changed (PropertyChange (0));
1329 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1331 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1332 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1335 super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1336 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1339 switch (_snap_type) {
1340 case SnapToRegionStart:
1341 case SnapToRegionEnd:
1342 case SnapToRegionSync:
1343 case SnapToRegionBoundary:
1344 build_region_boundary_cache ();
1351 /* register for undo history */
1352 _session->register_with_memento_command_factory(id(), this);
1354 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1356 start_updating_meters ();
1360 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1362 if (a->get_name() == "RegionMenu") {
1363 /* When the main menu's region menu is opened, we setup the actions so that they look right
1364 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1365 so we resensitize all region actions when the entered regionview or the region selection
1366 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1367 happens after the region context menu is opened. So we set a flag here, too.
1371 sensitize_the_right_region_actions ();
1372 _last_region_menu_was_main = true;
1377 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1379 using namespace Menu_Helpers;
1381 void (Editor::*emf)(FadeShape);
1382 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1385 images = &_xfade_in_images;
1386 emf = &Editor::set_fade_in_shape;
1388 images = &_xfade_out_images;
1389 emf = &Editor::set_fade_out_shape;
1394 _("Linear (for highly correlated material)"),
1395 *(*images)[FadeLinear],
1396 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1400 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1404 _("Constant power"),
1405 *(*images)[FadeConstantPower],
1406 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1409 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1414 *(*images)[FadeSymmetric],
1415 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1419 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1424 *(*images)[FadeSlow],
1425 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1428 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1433 *(*images)[FadeFast],
1434 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1437 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1440 /** Pop up a context menu for when the user clicks on a start crossfade */
1442 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1444 using namespace Menu_Helpers;
1445 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1448 MenuList& items (xfade_in_context_menu.items());
1451 if (arv->audio_region()->fade_in_active()) {
1452 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1454 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1457 items.push_back (SeparatorElem());
1458 fill_xfade_menu (items, true);
1460 xfade_in_context_menu.popup (button, time);
1463 /** Pop up a context menu for when the user clicks on an end crossfade */
1465 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1467 using namespace Menu_Helpers;
1468 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1471 MenuList& items (xfade_out_context_menu.items());
1474 if (arv->audio_region()->fade_out_active()) {
1475 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1477 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1480 items.push_back (SeparatorElem());
1481 fill_xfade_menu (items, false);
1483 xfade_out_context_menu.popup (button, time);
1487 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1489 using namespace Menu_Helpers;
1490 Menu* (Editor::*build_menu_function)();
1493 switch (item_type) {
1495 case RegionViewName:
1496 case RegionViewNameHighlight:
1497 case LeftFrameHandle:
1498 case RightFrameHandle:
1499 if (with_selection) {
1500 build_menu_function = &Editor::build_track_selection_context_menu;
1502 build_menu_function = &Editor::build_track_region_context_menu;
1507 if (with_selection) {
1508 build_menu_function = &Editor::build_track_selection_context_menu;
1510 build_menu_function = &Editor::build_track_context_menu;
1515 if (clicked_routeview->track()) {
1516 build_menu_function = &Editor::build_track_context_menu;
1518 build_menu_function = &Editor::build_track_bus_context_menu;
1523 /* probably shouldn't happen but if it does, we don't care */
1527 menu = (this->*build_menu_function)();
1528 menu->set_name ("ArdourContextMenu");
1530 /* now handle specific situations */
1532 switch (item_type) {
1534 case RegionViewName:
1535 case RegionViewNameHighlight:
1536 case LeftFrameHandle:
1537 case RightFrameHandle:
1538 if (!with_selection) {
1539 if (region_edit_menu_split_item) {
1540 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1541 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1543 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1546 if (region_edit_menu_split_multichannel_item) {
1547 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1548 region_edit_menu_split_multichannel_item->set_sensitive (true);
1550 region_edit_menu_split_multichannel_item->set_sensitive (false);
1563 /* probably shouldn't happen but if it does, we don't care */
1567 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1569 /* Bounce to disk */
1571 using namespace Menu_Helpers;
1572 MenuList& edit_items = menu->items();
1574 edit_items.push_back (SeparatorElem());
1576 switch (clicked_routeview->audio_track()->freeze_state()) {
1577 case AudioTrack::NoFreeze:
1578 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1581 case AudioTrack::Frozen:
1582 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1585 case AudioTrack::UnFrozen:
1586 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1592 if (item_type == StreamItem && clicked_routeview) {
1593 clicked_routeview->build_underlay_menu(menu);
1596 /* When the region menu is opened, we setup the actions so that they look right
1599 sensitize_the_right_region_actions ();
1600 _last_region_menu_was_main = false;
1602 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1603 menu->popup (button, time);
1607 Editor::build_track_context_menu ()
1609 using namespace Menu_Helpers;
1611 MenuList& edit_items = track_context_menu.items();
1614 add_dstream_context_items (edit_items);
1615 return &track_context_menu;
1619 Editor::build_track_bus_context_menu ()
1621 using namespace Menu_Helpers;
1623 MenuList& edit_items = track_context_menu.items();
1626 add_bus_context_items (edit_items);
1627 return &track_context_menu;
1631 Editor::build_track_region_context_menu ()
1633 using namespace Menu_Helpers;
1634 MenuList& edit_items = track_region_context_menu.items();
1637 /* we've just cleared the track region context menu, so the menu that these
1638 two items were on will have disappeared; stop them dangling.
1640 region_edit_menu_split_item = 0;
1641 region_edit_menu_split_multichannel_item = 0;
1643 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1646 boost::shared_ptr<Track> tr;
1647 boost::shared_ptr<Playlist> pl;
1649 if ((tr = rtv->track())) {
1650 add_region_context_items (edit_items, tr);
1654 add_dstream_context_items (edit_items);
1656 return &track_region_context_menu;
1660 Editor::analyze_region_selection ()
1662 if (analysis_window == 0) {
1663 analysis_window = new AnalysisWindow();
1666 analysis_window->set_session(_session);
1668 analysis_window->show_all();
1671 analysis_window->set_regionmode();
1672 analysis_window->analyze();
1674 analysis_window->present();
1678 Editor::analyze_range_selection()
1680 if (analysis_window == 0) {
1681 analysis_window = new AnalysisWindow();
1684 analysis_window->set_session(_session);
1686 analysis_window->show_all();
1689 analysis_window->set_rangemode();
1690 analysis_window->analyze();
1692 analysis_window->present();
1696 Editor::build_track_selection_context_menu ()
1698 using namespace Menu_Helpers;
1699 MenuList& edit_items = track_selection_context_menu.items();
1700 edit_items.clear ();
1702 add_selection_context_items (edit_items);
1703 // edit_items.push_back (SeparatorElem());
1704 // add_dstream_context_items (edit_items);
1706 return &track_selection_context_menu;
1710 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1712 using namespace Menu_Helpers;
1714 /* OK, stick the region submenu at the top of the list, and then add
1718 RegionSelection rs = get_regions_from_selection_and_entered ();
1720 string::size_type pos = 0;
1721 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1723 /* we have to hack up the region name because "_" has a special
1724 meaning for menu titles.
1727 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1728 menu_item_name.replace (pos, 1, "__");
1732 if (_popup_region_menu_item == 0) {
1733 _popup_region_menu_item = new MenuItem (menu_item_name);
1734 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1735 _popup_region_menu_item->show ();
1737 _popup_region_menu_item->set_label (menu_item_name);
1740 const framepos_t position = get_preferred_edit_position (false, true);
1742 edit_items.push_back (*_popup_region_menu_item);
1743 if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1744 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1746 edit_items.push_back (SeparatorElem());
1749 /** Add context menu items relevant to selection ranges.
1750 * @param edit_items List to add the items to.
1753 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1755 using namespace Menu_Helpers;
1757 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1758 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1760 edit_items.push_back (SeparatorElem());
1761 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1763 edit_items.push_back (SeparatorElem());
1765 edit_items.push_back (
1767 _("Move Range Start to Previous Region Boundary"),
1768 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1772 edit_items.push_back (
1774 _("Move Range Start to Next Region Boundary"),
1775 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1779 edit_items.push_back (
1781 _("Move Range End to Previous Region Boundary"),
1782 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1786 edit_items.push_back (
1788 _("Move Range End to Next Region Boundary"),
1789 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1793 edit_items.push_back (SeparatorElem());
1794 edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1795 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1797 edit_items.push_back (SeparatorElem());
1798 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1800 edit_items.push_back (SeparatorElem());
1801 edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1802 edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1804 edit_items.push_back (SeparatorElem());
1805 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1807 edit_items.push_back (SeparatorElem());
1808 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1809 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1810 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1812 edit_items.push_back (SeparatorElem());
1813 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1814 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1815 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1816 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1817 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1818 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1819 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1825 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1827 using namespace Menu_Helpers;
1831 Menu *play_menu = manage (new Menu);
1832 MenuList& play_items = play_menu->items();
1833 play_menu->set_name ("ArdourContextMenu");
1835 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1836 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1837 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1838 play_items.push_back (SeparatorElem());
1839 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1841 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1845 Menu *select_menu = manage (new Menu);
1846 MenuList& select_items = select_menu->items();
1847 select_menu->set_name ("ArdourContextMenu");
1849 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1850 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1851 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1852 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1853 select_items.push_back (SeparatorElem());
1854 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1855 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1856 select_items.push_back (SeparatorElem());
1857 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1858 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1859 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1860 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1861 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1862 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1863 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1865 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1869 Menu *cutnpaste_menu = manage (new Menu);
1870 MenuList& cutnpaste_items = cutnpaste_menu->items();
1871 cutnpaste_menu->set_name ("ArdourContextMenu");
1873 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1874 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1875 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1877 cutnpaste_items.push_back (SeparatorElem());
1879 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1880 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1882 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1884 /* Adding new material */
1886 edit_items.push_back (SeparatorElem());
1887 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1888 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1892 Menu *nudge_menu = manage (new Menu());
1893 MenuList& nudge_items = nudge_menu->items();
1894 nudge_menu->set_name ("ArdourContextMenu");
1896 edit_items.push_back (SeparatorElem());
1897 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1898 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1899 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1900 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1902 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1906 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1908 using namespace Menu_Helpers;
1912 Menu *play_menu = manage (new Menu);
1913 MenuList& play_items = play_menu->items();
1914 play_menu->set_name ("ArdourContextMenu");
1916 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1917 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1918 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1922 Menu *select_menu = manage (new Menu);
1923 MenuList& select_items = select_menu->items();
1924 select_menu->set_name ("ArdourContextMenu");
1926 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1927 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1928 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1929 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1930 select_items.push_back (SeparatorElem());
1931 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1932 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1933 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1934 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1936 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1940 Menu *cutnpaste_menu = manage (new Menu);
1941 MenuList& cutnpaste_items = cutnpaste_menu->items();
1942 cutnpaste_menu->set_name ("ArdourContextMenu");
1944 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1945 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1946 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1948 Menu *nudge_menu = manage (new Menu());
1949 MenuList& nudge_items = nudge_menu->items();
1950 nudge_menu->set_name ("ArdourContextMenu");
1952 edit_items.push_back (SeparatorElem());
1953 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1954 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1955 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1956 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1958 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1962 Editor::snap_type() const
1968 Editor::snap_mode() const
1974 Editor::set_snap_to (SnapType st)
1976 unsigned int snap_ind = (unsigned int)st;
1980 if (snap_ind > snap_type_strings.size() - 1) {
1982 _snap_type = (SnapType)snap_ind;
1985 string str = snap_type_strings[snap_ind];
1987 if (str != snap_type_selector.get_text()) {
1988 snap_type_selector.set_text (str);
1993 switch (_snap_type) {
1994 case SnapToBeatDiv128:
1995 case SnapToBeatDiv64:
1996 case SnapToBeatDiv32:
1997 case SnapToBeatDiv28:
1998 case SnapToBeatDiv24:
1999 case SnapToBeatDiv20:
2000 case SnapToBeatDiv16:
2001 case SnapToBeatDiv14:
2002 case SnapToBeatDiv12:
2003 case SnapToBeatDiv10:
2004 case SnapToBeatDiv8:
2005 case SnapToBeatDiv7:
2006 case SnapToBeatDiv6:
2007 case SnapToBeatDiv5:
2008 case SnapToBeatDiv4:
2009 case SnapToBeatDiv3:
2010 case SnapToBeatDiv2: {
2011 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2012 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2014 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2015 current_bbt_points_begin, current_bbt_points_end);
2016 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2017 current_bbt_points_begin, current_bbt_points_end);
2018 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2022 case SnapToRegionStart:
2023 case SnapToRegionEnd:
2024 case SnapToRegionSync:
2025 case SnapToRegionBoundary:
2026 build_region_boundary_cache ();
2034 SnapChanged (); /* EMIT SIGNAL */
2038 Editor::set_snap_mode (SnapMode mode)
2040 string str = snap_mode_strings[(int)mode];
2042 if (_internal_editing) {
2043 internal_snap_mode = mode;
2045 pre_internal_snap_mode = mode;
2050 if (str != snap_mode_selector.get_text ()) {
2051 snap_mode_selector.set_text (str);
2057 Editor::set_edit_point_preference (EditPoint ep, bool force)
2059 bool changed = (_edit_point != ep);
2062 string str = edit_point_strings[(int)ep];
2064 if (Profile->get_mixbus())
2065 if (ep == EditAtSelectedMarker)
2066 ep = EditAtPlayhead;
2068 if (str != edit_point_selector.get_text ()) {
2069 edit_point_selector.set_text (str);
2072 reset_canvas_cursor ();
2074 if (!force && !changed) {
2078 const char* action=NULL;
2080 switch (_edit_point) {
2081 case EditAtPlayhead:
2082 action = "edit-at-playhead";
2084 case EditAtSelectedMarker:
2085 action = "edit-at-marker";
2088 action = "edit-at-mouse";
2092 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2094 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2098 bool in_track_canvas;
2100 if (!mouse_frame (foo, in_track_canvas)) {
2101 in_track_canvas = false;
2104 reset_canvas_action_sensitivity (in_track_canvas);
2110 Editor::set_state (const XMLNode& node, int /*version*/)
2112 const XMLProperty* prop;
2119 g.base_width = default_width;
2120 g.base_height = default_height;
2124 if ((geometry = find_named_node (node, "geometry")) != 0) {
2128 if ((prop = geometry->property("x_size")) == 0) {
2129 prop = geometry->property ("x-size");
2132 g.base_width = atoi(prop->value());
2134 if ((prop = geometry->property("y_size")) == 0) {
2135 prop = geometry->property ("y-size");
2138 g.base_height = atoi(prop->value());
2141 if ((prop = geometry->property ("x_pos")) == 0) {
2142 prop = geometry->property ("x-pos");
2145 x = atoi (prop->value());
2148 if ((prop = geometry->property ("y_pos")) == 0) {
2149 prop = geometry->property ("y-pos");
2152 y = atoi (prop->value());
2156 set_default_size (g.base_width, g.base_height);
2159 if (_session && (prop = node.property ("playhead"))) {
2161 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2162 playhead_cursor->set_position (pos);
2164 playhead_cursor->set_position (0);
2167 if ((prop = node.property ("mixer-width"))) {
2168 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2171 if ((prop = node.property ("zoom-focus"))) {
2172 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2175 if ((prop = node.property ("zoom"))) {
2176 /* older versions of ardour used floating point samples_per_pixel */
2177 double f = PBD::atof (prop->value());
2178 reset_zoom (llrintf (f));
2180 reset_zoom (samples_per_pixel);
2183 if ((prop = node.property ("visible-track-count"))) {
2184 set_visible_track_count (PBD::atoi (prop->value()));
2187 if ((prop = node.property ("snap-to"))) {
2188 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2191 if ((prop = node.property ("snap-mode"))) {
2192 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2195 if ((prop = node.property ("internal-snap-to"))) {
2196 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2199 if ((prop = node.property ("internal-snap-mode"))) {
2200 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2203 if ((prop = node.property ("pre-internal-snap-to"))) {
2204 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2208 if ((prop = node.property ("pre-internal-snap-mode"))) {
2209 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2212 if ((prop = node.property ("mouse-mode"))) {
2213 MouseMode m = str2mousemode(prop->value());
2214 set_mouse_mode (m, true);
2216 set_mouse_mode (MouseObject, true);
2219 if ((prop = node.property ("left-frame")) != 0) {
2221 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2225 reset_x_origin (pos);
2229 if ((prop = node.property ("y-origin")) != 0) {
2230 reset_y_origin (atof (prop->value ()));
2233 if ((prop = node.property ("internal-edit"))) {
2234 bool yn = string_is_affirmative (prop->value());
2235 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2237 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2238 tact->set_active (!yn);
2239 tact->set_active (yn);
2243 if ((prop = node.property ("join-object-range"))) {
2244 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2245 bool yn = string_is_affirmative (prop->value());
2247 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2248 tact->set_active (!yn);
2249 tact->set_active (yn);
2251 set_mouse_mode(mouse_mode, true);
2254 if ((prop = node.property ("edit-point"))) {
2255 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2258 if ((prop = node.property ("show-measures"))) {
2259 bool yn = string_is_affirmative (prop->value());
2260 _show_measures = yn;
2261 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2263 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2264 /* do it twice to force the change */
2265 tact->set_active (!yn);
2266 tact->set_active (yn);
2270 if ((prop = node.property ("follow-playhead"))) {
2271 bool yn = string_is_affirmative (prop->value());
2272 set_follow_playhead (yn);
2273 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2275 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2276 if (tact->get_active() != yn) {
2277 tact->set_active (yn);
2282 if ((prop = node.property ("stationary-playhead"))) {
2283 bool yn = string_is_affirmative (prop->value());
2284 set_stationary_playhead (yn);
2285 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2287 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2288 if (tact->get_active() != yn) {
2289 tact->set_active (yn);
2294 if ((prop = node.property ("region-list-sort-type"))) {
2295 RegionListSortType st;
2296 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2299 if ((prop = node.property ("show-editor-mixer"))) {
2301 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2304 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2305 bool yn = string_is_affirmative (prop->value());
2307 /* do it twice to force the change */
2309 tact->set_active (!yn);
2310 tact->set_active (yn);
2313 if ((prop = node.property ("show-editor-list"))) {
2315 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2318 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2319 bool yn = string_is_affirmative (prop->value());
2321 /* do it twice to force the change */
2323 tact->set_active (!yn);
2324 tact->set_active (yn);
2327 if ((prop = node.property (X_("editor-list-page")))) {
2328 _the_notebook.set_current_page (atoi (prop->value ()));
2331 if ((prop = node.property (X_("show-marker-lines")))) {
2332 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2334 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2335 bool yn = string_is_affirmative (prop->value ());
2337 tact->set_active (!yn);
2338 tact->set_active (yn);
2341 XMLNodeList children = node.children ();
2342 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2343 selection->set_state (**i, Stateful::current_state_version);
2344 _regions->set_state (**i);
2347 if ((prop = node.property ("maximised"))) {
2348 bool yn = string_is_affirmative (prop->value());
2349 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2351 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2352 bool fs = tact && tact->get_active();
2354 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2358 if ((prop = node.property ("nudge-clock-value"))) {
2360 sscanf (prop->value().c_str(), "%" PRId64, &f);
2361 nudge_clock->set (f);
2363 nudge_clock->set_mode (AudioClock::Timecode);
2364 nudge_clock->set (_session->frame_rate() * 5, true);
2371 Editor::get_state ()
2373 XMLNode* node = new XMLNode ("Editor");
2376 id().print (buf, sizeof (buf));
2377 node->add_property ("id", buf);
2379 if (is_realized()) {
2380 Glib::RefPtr<Gdk::Window> win = get_window();
2382 int x, y, width, height;
2383 win->get_root_origin(x, y);
2384 win->get_size(width, height);
2386 XMLNode* geometry = new XMLNode ("geometry");
2388 snprintf(buf, sizeof(buf), "%d", width);
2389 geometry->add_property("x-size", string(buf));
2390 snprintf(buf, sizeof(buf), "%d", height);
2391 geometry->add_property("y-size", string(buf));
2392 snprintf(buf, sizeof(buf), "%d", x);
2393 geometry->add_property("x-pos", string(buf));
2394 snprintf(buf, sizeof(buf), "%d", y);
2395 geometry->add_property("y-pos", string(buf));
2396 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2397 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2398 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2399 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2400 geometry->add_property("edit-vertical-pane-pos", string(buf));
2402 node->add_child_nocopy (*geometry);
2405 maybe_add_mixer_strip_width (*node);
2407 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2409 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2410 node->add_property ("zoom", buf);
2411 node->add_property ("snap-to", enum_2_string (_snap_type));
2412 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2413 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2414 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2415 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2416 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2417 node->add_property ("edit-point", enum_2_string (_edit_point));
2418 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2419 node->add_property ("visible-track-count", buf);
2421 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2422 node->add_property ("playhead", buf);
2423 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2424 node->add_property ("left-frame", buf);
2425 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2426 node->add_property ("y-origin", buf);
2428 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2429 node->add_property ("maximised", _maximised ? "yes" : "no");
2430 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2431 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2432 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2433 node->add_property ("mouse-mode", enum2str(mouse_mode));
2434 node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2435 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2437 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2439 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2440 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2443 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2445 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2446 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2449 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2450 node->add_property (X_("editor-list-page"), buf);
2452 if (button_bindings) {
2453 XMLNode* bb = new XMLNode (X_("Buttons"));
2454 button_bindings->save (*bb);
2455 node->add_child_nocopy (*bb);
2458 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2460 node->add_child_nocopy (selection->get_state ());
2461 node->add_child_nocopy (_regions->get_state ());
2463 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2464 node->add_property ("nudge-clock-value", buf);
2469 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2470 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2472 * @return pair: TimeAxisView that y is over, layer index.
2474 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2475 * in stacked or expanded region display mode, otherwise 0.
2477 std::pair<TimeAxisView *, double>
2478 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2480 if (!trackview_relative_offset) {
2481 y -= _trackview_group->canvas_origin().y;
2485 return std::make_pair ( (TimeAxisView *) 0, 0);
2488 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2490 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2497 return std::make_pair ( (TimeAxisView *) 0, 0);
2500 /** Snap a position to the grid, if appropriate, taking into account current
2501 * grid settings and also the state of any snap modifier keys that may be pressed.
2502 * @param start Position to snap.
2503 * @param event Event to get current key modifier information from, or 0.
2506 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2508 if (!_session || !event) {
2512 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2513 if (_snap_mode == SnapOff) {
2514 snap_to_internal (start, direction, for_mark);
2517 if (_snap_mode != SnapOff) {
2518 snap_to_internal (start, direction, for_mark);
2524 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2526 if (!_session || _snap_mode == SnapOff) {
2530 snap_to_internal (start, direction, for_mark);
2534 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2536 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2537 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2539 switch (_snap_type) {
2540 case SnapToTimecodeFrame:
2541 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2542 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2544 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2548 case SnapToTimecodeSeconds:
2549 if (_session->config.get_timecode_offset_negative()) {
2550 start += _session->config.get_timecode_offset ();
2552 start -= _session->config.get_timecode_offset ();
2554 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2555 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2557 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2560 if (_session->config.get_timecode_offset_negative()) {
2561 start -= _session->config.get_timecode_offset ();
2563 start += _session->config.get_timecode_offset ();
2567 case SnapToTimecodeMinutes:
2568 if (_session->config.get_timecode_offset_negative()) {
2569 start += _session->config.get_timecode_offset ();
2571 start -= _session->config.get_timecode_offset ();
2573 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2574 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2576 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2578 if (_session->config.get_timecode_offset_negative()) {
2579 start -= _session->config.get_timecode_offset ();
2581 start += _session->config.get_timecode_offset ();
2585 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2591 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2593 const framepos_t one_second = _session->frame_rate();
2594 const framepos_t one_minute = _session->frame_rate() * 60;
2595 framepos_t presnap = start;
2599 switch (_snap_type) {
2600 case SnapToTimecodeFrame:
2601 case SnapToTimecodeSeconds:
2602 case SnapToTimecodeMinutes:
2603 return timecode_snap_to_internal (start, direction, for_mark);
2606 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2607 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2609 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2614 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2615 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2617 start = (framepos_t) floor ((double) start / one_second) * one_second;
2622 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2623 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2625 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2630 start = _session->tempo_map().round_to_bar (start, direction);
2634 start = _session->tempo_map().round_to_beat (start, direction);
2637 case SnapToBeatDiv128:
2638 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2640 case SnapToBeatDiv64:
2641 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2643 case SnapToBeatDiv32:
2644 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2646 case SnapToBeatDiv28:
2647 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2649 case SnapToBeatDiv24:
2650 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2652 case SnapToBeatDiv20:
2653 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2655 case SnapToBeatDiv16:
2656 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2658 case SnapToBeatDiv14:
2659 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2661 case SnapToBeatDiv12:
2662 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2664 case SnapToBeatDiv10:
2665 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2667 case SnapToBeatDiv8:
2668 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2670 case SnapToBeatDiv7:
2671 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2673 case SnapToBeatDiv6:
2674 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2676 case SnapToBeatDiv5:
2677 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2679 case SnapToBeatDiv4:
2680 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2682 case SnapToBeatDiv3:
2683 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2685 case SnapToBeatDiv2:
2686 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2694 _session->locations()->marks_either_side (start, before, after);
2696 if (before == max_framepos && after == max_framepos) {
2697 /* No marks to snap to, so just don't snap */
2699 } else if (before == max_framepos) {
2701 } else if (after == max_framepos) {
2703 } else if (before != max_framepos && after != max_framepos) {
2704 /* have before and after */
2705 if ((start - before) < (after - start)) {
2714 case SnapToRegionStart:
2715 case SnapToRegionEnd:
2716 case SnapToRegionSync:
2717 case SnapToRegionBoundary:
2718 if (!region_boundary_cache.empty()) {
2720 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2721 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2723 if (direction > 0) {
2724 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2726 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2729 if (next != region_boundary_cache.begin ()) {
2734 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2735 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2737 if (start > (p + n) / 2) {
2746 switch (_snap_mode) {
2752 if (presnap > start) {
2753 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2757 } else if (presnap < start) {
2758 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2764 /* handled at entry */
2772 Editor::setup_toolbar ()
2774 HBox* mode_box = manage(new HBox);
2775 mode_box->set_border_width (2);
2776 mode_box->set_spacing(2);
2778 HBox* mouse_mode_box = manage (new HBox);
2779 HBox* mouse_mode_hbox = manage (new HBox);
2780 VBox* mouse_mode_vbox = manage (new VBox);
2781 Alignment* mouse_mode_align = manage (new Alignment);
2783 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
2784 //mouse_mode_size_group->add_widget (smart_mode_button);
2785 mouse_mode_size_group->add_widget (mouse_move_button);
2786 mouse_mode_size_group->add_widget (mouse_cut_button);
2787 mouse_mode_size_group->add_widget (mouse_select_button);
2788 mouse_mode_size_group->add_widget (mouse_zoom_button);
2789 mouse_mode_size_group->add_widget (mouse_gain_button);
2790 mouse_mode_size_group->add_widget (mouse_timefx_button);
2791 mouse_mode_size_group->add_widget (mouse_audition_button);
2792 mouse_mode_size_group->add_widget (mouse_draw_button);
2793 mouse_mode_size_group->add_widget (internal_edit_button);
2795 if (!ARDOUR::Profile->get_small_screen()) {
2796 /* make them just a bit bigger */
2797 mouse_move_button.set_size_request (24, 30);
2799 /* make them just a bit taller */
2800 mouse_move_button.set_size_request (-1, 30);
2802 mouse_mode_hbox->set_spacing (2);
2804 if (!ARDOUR::Profile->get_trx()) {
2805 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2808 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2809 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2811 if (!ARDOUR::Profile->get_mixbus()) {
2812 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2813 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2816 if (!ARDOUR::Profile->get_trx()) {
2817 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2818 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2819 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2820 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2821 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 4);
2824 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2826 mouse_mode_align->add (*mouse_mode_vbox);
2827 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2829 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2831 edit_mode_selector.set_name ("mouse mode button");
2832 edit_mode_selector.add_elements (ArdourButton::Inset);
2834 if (!ARDOUR::Profile->get_trx()) {
2835 mode_box->pack_start (edit_mode_selector, false, false);
2837 mode_box->pack_start (*mouse_mode_box, false, false);
2839 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2840 _mouse_mode_tearoff->set_name ("MouseModeBase");
2841 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2843 if (Profile->get_sae() || Profile->get_mixbus() ) {
2844 _mouse_mode_tearoff->set_can_be_torn_off (false);
2847 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2848 &_mouse_mode_tearoff->tearoff_window()));
2849 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2850 &_mouse_mode_tearoff->tearoff_window(), 1));
2851 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2852 &_mouse_mode_tearoff->tearoff_window()));
2853 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2854 &_mouse_mode_tearoff->tearoff_window(), 1));
2858 _zoom_box.set_spacing (2);
2859 _zoom_box.set_border_width (2);
2863 zoom_preset_selector.set_name ("zoom button");
2864 zoom_preset_selector.set_image(::get_icon ("time_exp"));
2865 zoom_preset_selector.set_size_request (42, -1);
2867 zoom_in_button.set_name ("zoom button");
2868 // zoom_in_button.add_elements ( ArdourButton::Inset );
2869 zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2870 zoom_in_button.set_image(::get_icon ("zoom_in"));
2871 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2872 zoom_in_button.set_related_action (act);
2874 zoom_out_button.set_name ("zoom button");
2875 // zoom_out_button.add_elements ( ArdourButton::Inset );
2876 zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2877 zoom_out_button.set_image(::get_icon ("zoom_out"));
2878 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2879 zoom_out_button.set_related_action (act);
2881 zoom_out_full_button.set_name ("zoom button");
2882 // zoom_out_full_button.add_elements ( ArdourButton::Inset );
2883 zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2884 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2885 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2886 zoom_out_full_button.set_related_action (act);
2888 zoom_focus_selector.set_name ("zoom button");
2889 // zoom_focus_selector.add_elements (ArdourButton::Inset);
2891 if (ARDOUR::Profile->get_mixbus()) {
2892 _zoom_box.pack_start (zoom_preset_selector, false, false);
2893 } else if (ARDOUR::Profile->get_trx()) {
2894 mode_box->pack_start (zoom_out_button, false, false);
2895 mode_box->pack_start (zoom_in_button, false, false);
2897 _zoom_box.pack_start (zoom_out_button, false, false);
2898 _zoom_box.pack_start (zoom_in_button, false, false);
2899 _zoom_box.pack_start (zoom_out_full_button, false, false);
2900 _zoom_box.pack_start (zoom_focus_selector, false, false);
2903 /* Track zoom buttons */
2904 visible_tracks_selector.set_name ("zoom button");
2905 // visible_tracks_selector.add_elements ( ArdourButton::Inset );
2906 if (Profile->get_mixbus()) {
2907 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2908 visible_tracks_selector.set_size_request (42, -1);
2910 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 40, 2);
2913 tav_expand_button.set_name ("zoom button");
2914 // tav_expand_button.add_elements ( ArdourButton::FlatFace );
2915 tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2916 tav_expand_button.set_size_request (-1, 20);
2917 tav_expand_button.set_image(::get_icon ("tav_exp"));
2918 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2919 tav_expand_button.set_related_action (act);
2921 tav_shrink_button.set_name ("zoom button");
2922 // tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2923 tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2924 tav_shrink_button.set_size_request (-1, 20);
2925 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2926 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2927 tav_shrink_button.set_related_action (act);
2929 if (ARDOUR::Profile->get_mixbus()) {
2930 _zoom_box.pack_start (visible_tracks_selector);
2931 } else if (ARDOUR::Profile->get_trx()) {
2932 _zoom_box.pack_start (tav_shrink_button);
2933 _zoom_box.pack_start (tav_expand_button);
2935 _zoom_box.pack_start (visible_tracks_selector);
2936 _zoom_box.pack_start (tav_shrink_button);
2937 _zoom_box.pack_start (tav_expand_button);
2940 if (!ARDOUR::Profile->get_trx()) {
2941 _zoom_tearoff = manage (new TearOff (_zoom_box));
2943 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2944 &_zoom_tearoff->tearoff_window()));
2945 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2946 &_zoom_tearoff->tearoff_window(), 0));
2947 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2948 &_zoom_tearoff->tearoff_window()));
2949 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2950 &_zoom_tearoff->tearoff_window(), 0));
2953 if (Profile->get_sae() || Profile->get_mixbus() ) {
2954 _zoom_tearoff->set_can_be_torn_off (false);
2957 snap_box.set_spacing (2);
2958 snap_box.set_border_width (2);
2960 snap_type_selector.set_name ("mouse mode button");
2961 snap_type_selector.add_elements (ArdourButton::Inset);
2963 snap_mode_selector.set_name ("mouse mode button");
2964 snap_mode_selector.add_elements (ArdourButton::Inset);
2966 edit_point_selector.set_name ("mouse mode button");
2967 edit_point_selector.add_elements (ArdourButton::Inset);
2969 snap_box.pack_start (snap_mode_selector, false, false);
2970 snap_box.pack_start (snap_type_selector, false, false);
2971 snap_box.pack_start (edit_point_selector, false, false);
2975 HBox *nudge_box = manage (new HBox);
2976 nudge_box->set_spacing (2);
2977 nudge_box->set_border_width (2);
2979 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
2980 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
2982 nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2983 nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2985 nudge_box->pack_start (nudge_backward_button, false, false);
2986 nudge_box->pack_start (nudge_forward_button, false, false);
2987 nudge_box->pack_start (*nudge_clock, false, false);
2990 /* Pack everything in... */
2992 HBox* hbox = manage (new HBox);
2993 hbox->set_spacing(2);
2995 _tools_tearoff = manage (new TearOff (*hbox));
2996 _tools_tearoff->set_name ("MouseModeBase");
2997 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
2999 if (Profile->get_sae() || Profile->get_mixbus()) {
3000 _tools_tearoff->set_can_be_torn_off (false);
3003 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3004 &_tools_tearoff->tearoff_window()));
3005 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3006 &_tools_tearoff->tearoff_window(), 0));
3007 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3008 &_tools_tearoff->tearoff_window()));
3009 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3010 &_tools_tearoff->tearoff_window(), 0));
3012 toolbar_hbox.set_spacing (2);
3013 toolbar_hbox.set_border_width (1);
3015 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3016 if (!ARDOUR::Profile->get_trx()) {
3017 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3018 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3021 if (!ARDOUR::Profile->get_trx()) {
3022 hbox->pack_start (snap_box, false, false);
3023 if (!Profile->get_small_screen()) {
3024 hbox->pack_start (*nudge_box, false, false);
3026 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3029 hbox->pack_start (panic_box, false, false);
3033 toolbar_base.set_name ("ToolBarBase");
3034 toolbar_base.add (toolbar_hbox);
3036 _toolbar_viewport.add (toolbar_base);
3037 /* stick to the required height but allow width to vary if there's not enough room */
3038 _toolbar_viewport.set_size_request (1, -1);
3040 toolbar_frame.set_shadow_type (SHADOW_OUT);
3041 toolbar_frame.set_name ("BaseFrame");
3042 toolbar_frame.add (_toolbar_viewport);
3046 Editor::build_edit_point_menu ()
3048 using namespace Menu_Helpers;
3050 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3051 if(!Profile->get_mixbus())
3052 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3053 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3055 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, 30, 2);
3059 Editor::build_edit_mode_menu ()
3061 using namespace Menu_Helpers;
3063 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3064 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3065 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3066 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3068 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, 30, 2);
3072 Editor::build_snap_mode_menu ()
3074 using namespace Menu_Helpers;
3076 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3077 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3078 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3080 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, 34, 2);
3084 Editor::build_snap_type_menu ()
3086 using namespace Menu_Helpers;
3088 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3089 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3090 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3091 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3092 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3093 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3094 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3095 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3096 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3097 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3098 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3099 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3100 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3101 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3102 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3103 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3104 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3105 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3106 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3107 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3108 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3109 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3110 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3111 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3112 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3113 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3114 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3115 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3116 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3117 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3119 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, 34, 2);
3124 Editor::setup_tooltips ()
3126 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3127 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3128 ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
3129 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3130 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3131 ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3132 ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3133 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3134 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3135 ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3136 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3137 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3138 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3139 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3140 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3141 ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3142 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3143 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3144 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3145 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3146 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3147 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3148 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3149 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3150 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3151 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3155 Editor::convert_drop_to_paths (
3156 vector<string>& paths,
3157 const RefPtr<Gdk::DragContext>& /*context*/,
3160 const SelectionData& data,
3164 if (_session == 0) {
3168 vector<string> uris = data.get_uris();
3172 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3173 are actually URI lists. So do it by hand.
3176 if (data.get_target() != "text/plain") {
3180 /* Parse the "uri-list" format that Nautilus provides,
3181 where each pathname is delimited by \r\n.
3183 THERE MAY BE NO NULL TERMINATING CHAR!!!
3186 string txt = data.get_text();
3190 p = (char *) malloc (txt.length() + 1);
3191 txt.copy (p, txt.length(), 0);
3192 p[txt.length()] = '\0';
3198 while (g_ascii_isspace (*p))
3202 while (*q && (*q != '\n') && (*q != '\r')) {
3209 while (q > p && g_ascii_isspace (*q))
3214 uris.push_back (string (p, q - p + 1));
3218 p = strchr (p, '\n');
3230 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3231 if ((*i).substr (0,7) == "file://") {
3232 paths.push_back (Glib::filename_from_uri (*i));
3240 Editor::new_tempo_section ()
3245 Editor::map_transport_state ()
3247 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3249 if (_session && _session->transport_stopped()) {
3250 have_pending_keyboard_selection = false;
3253 update_loop_range_view ();
3259 Editor::begin_reversible_command (string name)
3262 _session->begin_reversible_command (name);
3267 Editor::begin_reversible_command (GQuark q)
3270 _session->begin_reversible_command (q);
3275 Editor::commit_reversible_command ()
3278 _session->commit_reversible_command ();
3283 Editor::history_changed ()
3287 if (undo_action && _session) {
3288 if (_session->undo_depth() == 0) {
3289 label = S_("Command|Undo");
3291 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3293 undo_action->property_label() = label;
3296 if (redo_action && _session) {
3297 if (_session->redo_depth() == 0) {
3300 label = string_compose(_("Redo (%1)"), _session->next_redo());
3302 redo_action->property_label() = label;
3307 Editor::duplicate_range (bool with_dialog)
3311 RegionSelection rs = get_regions_from_selection_and_entered ();
3313 if ( selection->time.length() == 0 && rs.empty()) {
3319 ArdourDialog win (_("Duplicate"));
3320 Label label (_("Number of duplications:"));
3321 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3322 SpinButton spinner (adjustment, 0.0, 1);
3325 win.get_vbox()->set_spacing (12);
3326 win.get_vbox()->pack_start (hbox);
3327 hbox.set_border_width (6);
3328 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3330 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3331 place, visually. so do this by hand.
3334 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3335 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3336 spinner.grab_focus();
3342 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3343 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3344 win.set_default_response (RESPONSE_ACCEPT);
3346 spinner.grab_focus ();
3348 switch (win.run ()) {
3349 case RESPONSE_ACCEPT:
3355 times = adjustment.get_value();
3358 if ((current_mouse_mode() == Editing::MouseRange)) {
3359 if (selection->time.length()) {
3360 duplicate_selection (times);
3362 } else if (get_smart_mode()) {
3363 if (selection->time.length()) {
3364 duplicate_selection (times);
3366 duplicate_some_regions (rs, times);
3368 duplicate_some_regions (rs, times);
3373 Editor::set_edit_mode (EditMode m)
3375 Config->set_edit_mode (m);
3379 Editor::cycle_edit_mode ()
3381 switch (Config->get_edit_mode()) {
3383 if (Profile->get_sae()) {
3384 Config->set_edit_mode (Lock);
3386 Config->set_edit_mode (Ripple);
3391 Config->set_edit_mode (Lock);
3394 Config->set_edit_mode (Slide);
3400 Editor::edit_mode_selection_done ( EditMode m )
3402 Config->set_edit_mode ( m );
3406 Editor::snap_type_selection_done (SnapType snaptype)
3408 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3410 ract->set_active ();
3415 Editor::snap_mode_selection_done (SnapMode mode)
3417 RefPtr<RadioAction> ract = snap_mode_action (mode);
3420 ract->set_active (true);
3425 Editor::cycle_edit_point (bool with_marker)
3427 if(Profile->get_mixbus())
3428 with_marker = false;
3430 switch (_edit_point) {
3432 set_edit_point_preference (EditAtPlayhead);
3434 case EditAtPlayhead:
3436 set_edit_point_preference (EditAtSelectedMarker);
3438 set_edit_point_preference (EditAtMouse);
3441 case EditAtSelectedMarker:
3442 set_edit_point_preference (EditAtMouse);
3448 Editor::edit_point_selection_done (EditPoint ep)
3450 set_edit_point_preference ( ep );
3454 Editor::build_zoom_focus_menu ()
3456 using namespace Menu_Helpers;
3458 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3459 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3460 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3461 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3462 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3463 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3465 set_size_request_to_display_given_text (zoom_focus_selector, longest (zoom_focus_strings), 30, 2);
3469 Editor::zoom_focus_selection_done ( ZoomFocus f )
3471 RefPtr<RadioAction> ract = zoom_focus_action (f);
3473 ract->set_active ();
3478 Editor::build_track_count_menu ()
3480 using namespace Menu_Helpers;
3482 if (!Profile->get_mixbus()) {
3483 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3484 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3485 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3486 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3487 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3488 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3489 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3490 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3491 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3492 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3493 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3494 visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3495 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3497 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit current tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3498 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3499 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3500 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3501 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3502 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3503 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3504 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3505 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3507 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), -1)));
3508 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3509 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3510 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3511 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3512 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3513 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3514 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3515 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3516 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3521 Editor::set_zoom_preset (int64_t ms)
3524 temporal_zoom_session();
3528 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3529 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3533 Editor::set_visible_track_count (int32_t n)
3535 _visible_track_count = n;
3537 /* if the canvas hasn't really been allocated any size yet, just
3538 record the desired number of visible tracks and return. when canvas
3539 allocation happens, we will get called again and then we can do the
3543 if (_visible_canvas_height <= 1) {
3550 if (_visible_track_count > 0) {
3551 h = trackviews_height() / _visible_track_count;
3552 std::ostringstream s;
3553 s << _visible_track_count;
3555 } else if (_visible_track_count == 0) {
3557 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3558 if ((*i)->marked_for_display()) {
3562 h = trackviews_height() / n;
3565 /* negative value means that the visible track count has
3566 been overridden by explicit track height changes.
3568 visible_tracks_selector.set_text (X_("*"));
3572 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3573 (*i)->set_height (h);
3576 if (str != visible_tracks_selector.get_text()) {
3577 visible_tracks_selector.set_text (str);
3582 Editor::override_visible_track_count ()
3584 _visible_track_count = -_visible_track_count;
3585 visible_tracks_selector.set_text ( _("*") );
3589 Editor::edit_controls_button_release (GdkEventButton* ev)
3591 if (Keyboard::is_context_menu_event (ev)) {
3592 ARDOUR_UI::instance()->add_route (this);
3593 } else if (ev->button == 1) {
3594 selection->clear_tracks ();
3601 Editor::mouse_select_button_release (GdkEventButton* ev)
3603 /* this handles just right-clicks */
3605 if (ev->button != 3) {
3613 Editor::set_zoom_focus (ZoomFocus f)
3615 string str = zoom_focus_strings[(int)f];
3617 if (str != zoom_focus_selector.get_text()) {
3618 zoom_focus_selector.set_text (str);
3621 if (zoom_focus != f) {
3628 Editor::cycle_zoom_focus ()
3630 switch (zoom_focus) {
3632 set_zoom_focus (ZoomFocusRight);
3634 case ZoomFocusRight:
3635 set_zoom_focus (ZoomFocusCenter);
3637 case ZoomFocusCenter:
3638 set_zoom_focus (ZoomFocusPlayhead);
3640 case ZoomFocusPlayhead:
3641 set_zoom_focus (ZoomFocusMouse);
3643 case ZoomFocusMouse:
3644 set_zoom_focus (ZoomFocusEdit);
3647 set_zoom_focus (ZoomFocusLeft);
3653 Editor::ensure_float (Window& win)
3655 win.set_transient_for (*this);
3659 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3661 /* recover or initialize pane positions. do this here rather than earlier because
3662 we don't want the positions to change the child allocations, which they seem to do.
3668 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3677 XMLNode* geometry = find_named_node (*node, "geometry");
3679 if (which == static_cast<Paned*> (&edit_pane)) {
3681 if (done & Horizontal) {
3685 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3686 _notebook_shrunk = string_is_affirmative (prop->value ());
3689 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3690 /* initial allocation is 90% to canvas, 10% to notebook */
3691 pos = (int) floor (alloc.get_width() * 0.90f);
3692 snprintf (buf, sizeof(buf), "%d", pos);
3694 pos = atoi (prop->value());
3697 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3698 edit_pane.set_position (pos);
3701 done = (Pane) (done | Horizontal);
3703 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3705 if (done & Vertical) {
3709 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3710 /* initial allocation is 90% to canvas, 10% to summary */
3711 pos = (int) floor (alloc.get_height() * 0.90f);
3712 snprintf (buf, sizeof(buf), "%d", pos);
3715 pos = atoi (prop->value());
3718 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3719 editor_summary_pane.set_position (pos);
3722 done = (Pane) (done | Vertical);
3727 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3729 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3730 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3731 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3732 top_hbox.remove (toolbar_frame);
3737 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3739 if (toolbar_frame.get_parent() == 0) {
3740 top_hbox.pack_end (toolbar_frame);
3745 Editor::set_show_measures (bool yn)
3747 if (_show_measures != yn) {
3750 if ((_show_measures = yn) == true) {
3752 tempo_lines->show();
3755 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3756 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3758 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3759 draw_measures (begin, end);
3767 Editor::toggle_follow_playhead ()
3769 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3771 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3772 set_follow_playhead (tact->get_active());
3776 /** @param yn true to follow playhead, otherwise false.
3777 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3780 Editor::set_follow_playhead (bool yn, bool catch_up)
3782 if (_follow_playhead != yn) {
3783 if ((_follow_playhead = yn) == true && catch_up) {
3785 reset_x_origin_to_follow_playhead ();
3792 Editor::toggle_stationary_playhead ()
3794 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3796 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3797 set_stationary_playhead (tact->get_active());
3802 Editor::set_stationary_playhead (bool yn)
3804 if (_stationary_playhead != yn) {
3805 if ((_stationary_playhead = yn) == true) {
3807 // FIXME need a 3.0 equivalent of this 2.X call
3808 // update_current_screen ();
3815 Editor::playlist_selector () const
3817 return *_playlist_selector;
3821 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3825 switch (_snap_type) {
3830 case SnapToBeatDiv128:
3833 case SnapToBeatDiv64:
3836 case SnapToBeatDiv32:
3839 case SnapToBeatDiv28:
3842 case SnapToBeatDiv24:
3845 case SnapToBeatDiv20:
3848 case SnapToBeatDiv16:
3851 case SnapToBeatDiv14:
3854 case SnapToBeatDiv12:
3857 case SnapToBeatDiv10:
3860 case SnapToBeatDiv8:
3863 case SnapToBeatDiv7:
3866 case SnapToBeatDiv6:
3869 case SnapToBeatDiv5:
3872 case SnapToBeatDiv4:
3875 case SnapToBeatDiv3:
3878 case SnapToBeatDiv2:
3884 return _session->tempo_map().meter_at (position).divisions_per_bar();
3889 case SnapToTimecodeFrame:
3890 case SnapToTimecodeSeconds:
3891 case SnapToTimecodeMinutes:
3894 case SnapToRegionStart:
3895 case SnapToRegionEnd:
3896 case SnapToRegionSync:
3897 case SnapToRegionBoundary:
3907 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3911 ret = nudge_clock->current_duration (pos);
3912 next = ret + 1; /* XXXX fix me */
3918 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3920 ArdourDialog dialog (_("Playlist Deletion"));
3921 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3922 "If it is kept, its audio files will not be cleaned.\n"
3923 "If it is deleted, audio files used by it alone will be cleaned."),
3926 dialog.set_position (WIN_POS_CENTER);
3927 dialog.get_vbox()->pack_start (label);
3931 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3932 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3933 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3935 switch (dialog.run ()) {
3936 case RESPONSE_ACCEPT:
3937 /* delete the playlist */
3941 case RESPONSE_REJECT:
3942 /* keep the playlist */
3954 Editor::audio_region_selection_covers (framepos_t where)
3956 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3957 if ((*a)->region()->covers (where)) {
3966 Editor::prepare_for_cleanup ()
3968 cut_buffer->clear_regions ();
3969 cut_buffer->clear_playlists ();
3971 selection->clear_regions ();
3972 selection->clear_playlists ();
3974 _regions->suspend_redisplay ();
3978 Editor::finish_cleanup ()
3980 _regions->resume_redisplay ();
3984 Editor::transport_loop_location()
3987 return _session->locations()->auto_loop_location();
3994 Editor::transport_punch_location()
3997 return _session->locations()->auto_punch_location();
4004 Editor::control_layout_scroll (GdkEventScroll* ev)
4006 /* Just forward to the normal canvas scroll method. The coordinate
4007 systems are different but since the canvas is always larger than the
4008 track headers, and aligned with the trackview area, this will work.
4010 In the not too distant future this layout is going away anyway and
4011 headers will be on the canvas.
4013 return canvas_scroll_event (ev, false);
4017 Editor::session_state_saved (string)
4020 _snapshots->redisplay ();
4024 Editor::update_tearoff_visibility()
4026 bool visible = Config->get_keep_tearoffs();
4027 _mouse_mode_tearoff->set_visible (visible);
4028 _tools_tearoff->set_visible (visible);
4029 if (_zoom_tearoff) {
4030 _zoom_tearoff->set_visible (visible);
4035 Editor::maximise_editing_space ()
4047 Editor::restore_editing_space ()
4059 * Make new playlists for a given track and also any others that belong
4060 * to the same active route group with the `select' property.
4065 Editor::new_playlists (TimeAxisView* v)
4067 begin_reversible_command (_("new playlists"));
4068 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4069 _session->playlists->get (playlists);
4070 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4071 commit_reversible_command ();
4075 * Use a copy of the current playlist for a given track and also any others that belong
4076 * to the same active route group with the `select' property.
4081 Editor::copy_playlists (TimeAxisView* v)
4083 begin_reversible_command (_("copy playlists"));
4084 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4085 _session->playlists->get (playlists);
4086 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4087 commit_reversible_command ();
4090 /** Clear the current playlist for a given track and also any others that belong
4091 * to the same active route group with the `select' property.
4096 Editor::clear_playlists (TimeAxisView* v)
4098 begin_reversible_command (_("clear playlists"));
4099 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4100 _session->playlists->get (playlists);
4101 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4102 commit_reversible_command ();
4106 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4108 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4112 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4114 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4118 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4120 atv.clear_playlist ();
4124 Editor::on_key_press_event (GdkEventKey* ev)
4126 return key_press_focus_accelerator_handler (*this, ev);
4130 Editor::on_key_release_event (GdkEventKey* ev)
4132 return Gtk::Window::on_key_release_event (ev);
4133 // return key_press_focus_accelerator_handler (*this, ev);
4136 /** Queue up a change to the viewport x origin.
4137 * @param frame New x origin.
4140 Editor::reset_x_origin (framepos_t frame)
4142 pending_visual_change.add (VisualChange::TimeOrigin);
4143 pending_visual_change.time_origin = frame;
4144 ensure_visual_change_idle_handler ();
4148 Editor::reset_y_origin (double y)
4150 pending_visual_change.add (VisualChange::YOrigin);
4151 pending_visual_change.y_origin = y;
4152 ensure_visual_change_idle_handler ();
4156 Editor::reset_zoom (framecnt_t spp)
4158 if (spp == samples_per_pixel) {
4162 pending_visual_change.add (VisualChange::ZoomLevel);
4163 pending_visual_change.samples_per_pixel = spp;
4164 ensure_visual_change_idle_handler ();
4168 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4170 reset_x_origin (frame);
4173 if (!no_save_visual) {
4174 undo_visual_stack.push_back (current_visual_state(false));
4178 Editor::VisualState::VisualState (bool with_tracks)
4179 : gui_state (with_tracks ? new GUIObjectState : 0)
4183 Editor::VisualState::~VisualState ()
4188 Editor::VisualState*
4189 Editor::current_visual_state (bool with_tracks)
4191 VisualState* vs = new VisualState (with_tracks);
4192 vs->y_position = vertical_adjustment.get_value();
4193 vs->samples_per_pixel = samples_per_pixel;
4194 vs->leftmost_frame = leftmost_frame;
4195 vs->zoom_focus = zoom_focus;
4198 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4205 Editor::undo_visual_state ()
4207 if (undo_visual_stack.empty()) {
4211 VisualState* vs = undo_visual_stack.back();
4212 undo_visual_stack.pop_back();
4215 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4217 use_visual_state (*vs);
4221 Editor::redo_visual_state ()
4223 if (redo_visual_stack.empty()) {
4227 VisualState* vs = redo_visual_stack.back();
4228 redo_visual_stack.pop_back();
4230 undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4232 use_visual_state (*vs);
4236 Editor::swap_visual_state ()
4238 if (undo_visual_stack.empty()) {
4239 redo_visual_state ();
4241 undo_visual_state ();
4246 Editor::use_visual_state (VisualState& vs)
4248 PBD::Unwinder<bool> nsv (no_save_visual, true);
4249 DisplaySuspender ds;
4251 vertical_adjustment.set_value (vs.y_position);
4253 set_zoom_focus (vs.zoom_focus);
4254 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4257 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4259 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4260 (*i)->reset_visual_state ();
4264 _routes->update_visibility ();
4267 /** This is the core function that controls the zoom level of the canvas. It is called
4268 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4269 * @param spp new number of samples per pixel
4272 Editor::set_samples_per_pixel (framecnt_t spp)
4278 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4279 const framecnt_t lots_of_pixels = 4000;
4281 /* if the zoom level is greater than what you'd get trying to display 3
4282 * days of audio on a really big screen, then it's too big.
4285 if (spp * lots_of_pixels > three_days) {
4289 samples_per_pixel = spp;
4292 tempo_lines->tempo_map_changed();
4295 bool const showing_time_selection = selection->time.length() > 0;
4297 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4298 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4299 (*i)->reshow_selection (selection->time);
4303 ZoomChanged (); /* EMIT_SIGNAL */
4305 ArdourCanvas::GtkCanvasViewport* c;
4307 c = get_track_canvas();
4309 c->canvas()->zoomed ();
4312 if (playhead_cursor) {
4313 playhead_cursor->set_position (playhead_cursor->current_frame ());
4316 refresh_location_display();
4317 _summary->set_overlays_dirty ();
4319 update_marker_labels ();
4325 Editor::queue_visual_videotimeline_update ()
4328 * pending_visual_change.add (VisualChange::VideoTimeline);
4329 * or maybe even more specific: which videotimeline-image
4330 * currently it calls update_video_timeline() to update
4331 * _all outdated_ images on the video-timeline.
4332 * see 'exposeimg()' in video_image_frame.cc
4334 ensure_visual_change_idle_handler ();
4338 Editor::ensure_visual_change_idle_handler ()
4340 if (pending_visual_change.idle_handler_id < 0) {
4341 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4342 pending_visual_change.being_handled = false;
4347 Editor::_idle_visual_changer (void* arg)
4349 return static_cast<Editor*>(arg)->idle_visual_changer ();
4353 Editor::idle_visual_changer ()
4355 /* set_horizontal_position() below (and maybe other calls) call
4356 gtk_main_iteration(), so it's possible that a signal will be handled
4357 half-way through this method. If this signal wants an
4358 idle_visual_changer we must schedule another one after this one, so
4359 mark the idle_handler_id as -1 here to allow that. Also make a note
4360 that we are doing the visual change, so that changes in response to
4361 super-rapid-screen-update can be dropped if we are still processing
4365 pending_visual_change.idle_handler_id = -1;
4366 pending_visual_change.being_handled = true;
4368 VisualChange vc = pending_visual_change;
4370 pending_visual_change.pending = (VisualChange::Type) 0;
4372 visual_changer (vc);
4374 pending_visual_change.being_handled = false;
4376 return 0; /* this is always a one-shot call */
4380 Editor::visual_changer (const VisualChange& vc)
4382 double const last_time_origin = horizontal_position ();
4384 if (vc.pending & VisualChange::ZoomLevel) {
4385 set_samples_per_pixel (vc.samples_per_pixel);
4387 compute_fixed_ruler_scale ();
4389 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4390 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4392 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4393 current_bbt_points_begin, current_bbt_points_end);
4394 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4395 current_bbt_points_begin, current_bbt_points_end);
4396 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4398 update_video_timeline();
4401 if (vc.pending & VisualChange::TimeOrigin) {
4402 set_horizontal_position (vc.time_origin / samples_per_pixel);
4405 if (vc.pending & VisualChange::YOrigin) {
4406 vertical_adjustment.set_value (vc.y_origin);
4409 if (last_time_origin == horizontal_position ()) {
4410 /* changed signal not emitted */
4411 update_fixed_rulers ();
4412 redisplay_tempo (true);
4415 if (!(vc.pending & VisualChange::ZoomLevel)) {
4416 update_video_timeline();
4419 _summary->set_overlays_dirty ();
4422 struct EditorOrderTimeAxisSorter {
4423 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4424 return a->order () < b->order ();
4429 Editor::sort_track_selection (TrackViewList& sel)
4431 EditorOrderTimeAxisSorter cmp;
4436 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4439 framepos_t where = 0;
4440 EditPoint ep = _edit_point;
4442 if(Profile->get_mixbus())
4443 if (ep == EditAtSelectedMarker)
4446 if (from_context_menu && (ep == EditAtMouse)) {
4447 return canvas_event_sample (&context_click_event, 0, 0);
4450 if (entered_marker) {
4451 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4452 return entered_marker->position();
4455 if (ignore_playhead && ep == EditAtPlayhead) {
4456 ep = EditAtSelectedMarker;
4460 case EditAtPlayhead:
4461 where = _session->audible_frame();
4462 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4465 case EditAtSelectedMarker:
4466 if (!selection->markers.empty()) {
4468 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4471 where = loc->start();
4475 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4483 if (!mouse_frame (where, ignored)) {
4484 /* XXX not right but what can we do ? */
4488 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4496 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4498 if (!_session) return;
4500 begin_reversible_command (cmd);
4504 if ((tll = transport_loop_location()) == 0) {
4505 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4506 XMLNode &before = _session->locations()->get_state();
4507 _session->locations()->add (loc, true);
4508 _session->set_auto_loop_location (loc);
4509 XMLNode &after = _session->locations()->get_state();
4510 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4512 XMLNode &before = tll->get_state();
4513 tll->set_hidden (false, this);
4514 tll->set (start, end);
4515 XMLNode &after = tll->get_state();
4516 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4519 commit_reversible_command ();
4523 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4525 if (!_session) return;
4527 begin_reversible_command (cmd);
4531 if ((tpl = transport_punch_location()) == 0) {
4532 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4533 XMLNode &before = _session->locations()->get_state();
4534 _session->locations()->add (loc, true);
4535 _session->set_auto_punch_location (loc);
4536 XMLNode &after = _session->locations()->get_state();
4537 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4540 XMLNode &before = tpl->get_state();
4541 tpl->set_hidden (false, this);
4542 tpl->set (start, end);
4543 XMLNode &after = tpl->get_state();
4544 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4547 commit_reversible_command ();
4550 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4551 * @param rs List to which found regions are added.
4552 * @param where Time to look at.
4553 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4556 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4558 const TrackViewList* tracks;
4561 tracks = &track_views;
4566 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4568 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4571 boost::shared_ptr<Track> tr;
4572 boost::shared_ptr<Playlist> pl;
4574 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4576 boost::shared_ptr<RegionList> regions = pl->regions_at (
4577 (framepos_t) floor ( (double) where * tr->speed()));
4579 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4580 RegionView* rv = rtv->view()->find_view (*i);
4591 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4593 const TrackViewList* tracks;
4596 tracks = &track_views;
4601 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4602 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4604 boost::shared_ptr<Track> tr;
4605 boost::shared_ptr<Playlist> pl;
4607 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4609 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4610 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4612 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4614 RegionView* rv = rtv->view()->find_view (*i);
4625 /** Get regions using the following method:
4627 * Make a region list using:
4628 * (a) any selected regions
4629 * (b) the intersection of any selected tracks and the edit point(*)
4630 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4632 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4634 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4638 Editor::get_regions_from_selection_and_edit_point ()
4640 RegionSelection regions;
4642 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4643 regions.add (entered_regionview);
4645 regions = selection->regions;
4648 if ( regions.empty() ) {
4649 TrackViewList tracks = selection->tracks;
4651 if (!tracks.empty()) {
4652 /* no region selected or entered, but some selected tracks:
4653 * act on all regions on the selected tracks at the edit point
4655 framepos_t const where = get_preferred_edit_position ();
4656 get_regions_at(regions, where, tracks);
4663 /** Get regions using the following method:
4665 * Make a region list using:
4666 * (a) any selected regions
4667 * (b) the intersection of any selected tracks and the edit point(*)
4668 * (c) if neither exists, then whatever region is under the mouse
4670 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4672 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4675 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4677 RegionSelection regions;
4679 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4680 regions.add (entered_regionview);
4682 regions = selection->regions;
4685 if ( regions.empty() ) {
4686 TrackViewList tracks = selection->tracks;
4688 if (!tracks.empty()) {
4689 /* no region selected or entered, but some selected tracks:
4690 * act on all regions on the selected tracks at the edit point
4692 get_regions_at(regions, pos, tracks);
4699 /** Start with regions that are selected, or the entered regionview if none are selected.
4700 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4701 * of the regions that we started with.
4705 Editor::get_regions_from_selection_and_entered ()
4707 RegionSelection regions = selection->regions;
4709 if (regions.empty() && entered_regionview) {
4710 regions.add (entered_regionview);
4717 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4719 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4721 RouteTimeAxisView* tatv;
4723 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4725 boost::shared_ptr<Playlist> pl;
4726 vector<boost::shared_ptr<Region> > results;
4728 boost::shared_ptr<Track> tr;
4730 if ((tr = tatv->track()) == 0) {
4735 if ((pl = (tr->playlist())) != 0) {
4736 if (src_comparison) {
4737 pl->get_source_equivalent_regions (region, results);
4739 pl->get_region_list_equivalent_regions (region, results);
4743 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4744 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4745 regions.push_back (marv);
4754 Editor::show_rhythm_ferret ()
4756 if (rhythm_ferret == 0) {
4757 rhythm_ferret = new RhythmFerret(*this);
4760 rhythm_ferret->set_session (_session);
4761 rhythm_ferret->show ();
4762 rhythm_ferret->present ();
4766 Editor::first_idle ()
4768 MessageDialog* dialog = 0;
4770 if (track_views.size() > 1) {
4771 dialog = new MessageDialog (
4773 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4777 ARDOUR_UI::instance()->flush_pending ();
4780 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4784 // first idle adds route children (automation tracks), so we need to redisplay here
4785 _routes->redisplay ();
4792 Editor::_idle_resize (gpointer arg)
4794 return ((Editor*)arg)->idle_resize ();
4798 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4800 if (resize_idle_id < 0) {
4801 resize_idle_id = g_idle_add (_idle_resize, this);
4802 _pending_resize_amount = 0;
4805 /* make a note of the smallest resulting height, so that we can clamp the
4806 lower limit at TimeAxisView::hSmall */
4808 int32_t min_resulting = INT32_MAX;
4810 _pending_resize_amount += h;
4811 _pending_resize_view = view;
4813 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4815 if (selection->tracks.contains (_pending_resize_view)) {
4816 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4817 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4821 if (min_resulting < 0) {
4826 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4827 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4831 /** Handle pending resizing of tracks */
4833 Editor::idle_resize ()
4835 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4837 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4838 selection->tracks.contains (_pending_resize_view)) {
4840 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4841 if (*i != _pending_resize_view) {
4842 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4847 _pending_resize_amount = 0;
4848 _group_tabs->set_dirty ();
4849 resize_idle_id = -1;
4857 ENSURE_GUI_THREAD (*this, &Editor::located);
4860 playhead_cursor->set_position (_session->audible_frame ());
4861 if (_follow_playhead && !_pending_initial_locate) {
4862 reset_x_origin_to_follow_playhead ();
4866 _pending_locate_request = false;
4867 _pending_initial_locate = false;
4871 Editor::region_view_added (RegionView *)
4873 _summary->set_background_dirty ();
4877 Editor::region_view_removed ()
4879 _summary->set_background_dirty ();
4883 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4885 TrackViewList::const_iterator j = track_views.begin ();
4886 while (j != track_views.end()) {
4887 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4888 if (rtv && rtv->route() == r) {
4899 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4903 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4904 TimeAxisView* tv = axis_view_from_route (*i);
4914 Editor::suspend_route_redisplay ()
4917 _routes->suspend_redisplay();
4922 Editor::resume_route_redisplay ()
4925 _routes->resume_redisplay();
4930 Editor::add_routes (RouteList& routes)
4932 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4934 RouteTimeAxisView *rtv;
4935 list<RouteTimeAxisView*> new_views;
4937 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4938 boost::shared_ptr<Route> route = (*x);
4940 if (route->is_auditioner() || route->is_monitor()) {
4944 DataType dt = route->input()->default_type();
4946 if (dt == ARDOUR::DataType::AUDIO) {
4947 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4948 rtv->set_route (route);
4949 } else if (dt == ARDOUR::DataType::MIDI) {
4950 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
4951 rtv->set_route (route);
4953 throw unknown_type();
4956 new_views.push_back (rtv);
4957 track_views.push_back (rtv);
4959 rtv->effective_gain_display ();
4961 if (internal_editing()) {
4962 rtv->enter_internal_edit_mode ();
4964 rtv->leave_internal_edit_mode ();
4967 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4968 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4971 if (new_views.size() > 0) {
4972 _routes->routes_added (new_views);
4973 _summary->routes_added (new_views);
4976 if (show_editor_mixer_when_tracks_arrive) {
4977 show_editor_mixer (true);
4980 editor_list_button.set_sensitive (true);
4984 Editor::timeaxisview_deleted (TimeAxisView *tv)
4986 if (tv == entered_track) {
4990 if (_session && _session->deletion_in_progress()) {
4991 /* the situation is under control */
4995 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
4997 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
4999 _routes->route_removed (tv);
5001 TimeAxisView::Children c = tv->get_child_list ();
5002 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5003 if (entered_track == i->get()) {
5008 /* remove it from the list of track views */
5010 TrackViewList::iterator i;
5012 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5013 i = track_views.erase (i);
5016 /* update whatever the current mixer strip is displaying, if revelant */
5018 boost::shared_ptr<Route> route;
5021 route = rtav->route ();
5024 if (current_mixer_strip && current_mixer_strip->route() == route) {
5026 TimeAxisView* next_tv;
5028 if (track_views.empty()) {
5030 } else if (i == track_views.end()) {
5031 next_tv = track_views.front();
5038 set_selected_mixer_strip (*next_tv);
5040 /* make the editor mixer strip go away setting the
5041 * button to inactive (which also unticks the menu option)
5044 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5050 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5052 if (apply_to_selection) {
5053 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5055 TrackSelection::iterator j = i;
5058 hide_track_in_display (*i, false);
5063 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5065 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5066 // this will hide the mixer strip
5067 set_selected_mixer_strip (*tv);
5070 _routes->hide_track_in_display (*tv);
5075 Editor::sync_track_view_list_and_routes ()
5077 track_views = TrackViewList (_routes->views ());
5079 _summary->set_dirty ();
5080 _group_tabs->set_dirty ();
5082 return false; // do not call again (until needed)
5086 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5088 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5093 /** Find a RouteTimeAxisView by the ID of its route */
5095 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5097 RouteTimeAxisView* v;
5099 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5100 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5101 if(v->route()->id() == id) {
5111 Editor::fit_route_group (RouteGroup *g)
5113 TrackViewList ts = axis_views_from_routes (g->route_list ());
5118 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5120 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5123 _session->cancel_audition ();
5127 if (_session->is_auditioning()) {
5128 _session->cancel_audition ();
5129 if (r == last_audition_region) {
5134 _session->audition_region (r);
5135 last_audition_region = r;
5140 Editor::hide_a_region (boost::shared_ptr<Region> r)
5142 r->set_hidden (true);
5146 Editor::show_a_region (boost::shared_ptr<Region> r)
5148 r->set_hidden (false);
5152 Editor::audition_region_from_region_list ()
5154 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5158 Editor::hide_region_from_region_list ()
5160 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5164 Editor::show_region_in_region_list ()
5166 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5170 Editor::step_edit_status_change (bool yn)
5173 start_step_editing ();
5175 stop_step_editing ();
5180 Editor::start_step_editing ()
5182 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5186 Editor::stop_step_editing ()
5188 step_edit_connection.disconnect ();
5192 Editor::check_step_edit ()
5194 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5195 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5197 mtv->check_step_edit ();
5201 return true; // do it again, till we stop
5205 Editor::scroll_press (Direction dir)
5207 ++_scroll_callbacks;
5209 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5210 /* delay the first auto-repeat */
5216 scroll_backward (1);
5224 scroll_up_one_track ();
5228 scroll_down_one_track ();
5232 /* do hacky auto-repeat */
5233 if (!_scroll_connection.connected ()) {
5235 _scroll_connection = Glib::signal_timeout().connect (
5236 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5239 _scroll_callbacks = 0;
5246 Editor::scroll_release ()
5248 _scroll_connection.disconnect ();
5251 /** Queue a change for the Editor viewport x origin to follow the playhead */
5253 Editor::reset_x_origin_to_follow_playhead ()
5255 framepos_t const frame = playhead_cursor->current_frame ();
5257 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5259 if (_session->transport_speed() < 0) {
5261 if (frame > (current_page_samples() / 2)) {
5262 center_screen (frame-(current_page_samples()/2));
5264 center_screen (current_page_samples()/2);
5271 if (frame < leftmost_frame) {
5273 if (_session->transport_rolling()) {
5274 /* rolling; end up with the playhead at the right of the page */
5275 l = frame - current_page_samples ();
5277 /* not rolling: end up with the playhead 1/4 of the way along the page */
5278 l = frame - current_page_samples() / 4;
5282 if (_session->transport_rolling()) {
5283 /* rolling: end up with the playhead on the left of the page */
5286 /* not rolling: end up with the playhead 3/4 of the way along the page */
5287 l = frame - 3 * current_page_samples() / 4;
5295 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5301 Editor::super_rapid_screen_update ()
5303 if (!_session || !_session->engine().running()) {
5307 /* METERING / MIXER STRIPS */
5309 /* update track meters, if required */
5310 if (is_mapped() && meters_running) {
5311 RouteTimeAxisView* rtv;
5312 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5313 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5314 rtv->fast_update ();
5319 /* and any current mixer strip */
5320 if (current_mixer_strip) {
5321 current_mixer_strip->fast_update ();
5324 /* PLAYHEAD AND VIEWPORT */
5326 framepos_t const frame = _session->audible_frame();
5328 /* There are a few reasons why we might not update the playhead / viewport stuff:
5330 * 1. we don't update things when there's a pending locate request, otherwise
5331 * when the editor requests a locate there is a chance that this method
5332 * will move the playhead before the locate request is processed, causing
5334 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5335 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5338 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5340 last_update_frame = frame;
5342 if (!_dragging_playhead) {
5343 playhead_cursor->set_position (frame);
5346 if (!_stationary_playhead) {
5348 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5349 /* We only do this if we aren't already
5350 handling a visual change (ie if
5351 pending_visual_change.being_handled is
5352 false) so that these requests don't stack
5353 up there are too many of them to handle in
5356 reset_x_origin_to_follow_playhead ();
5361 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5365 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5366 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5367 if (target <= 0.0) {
5370 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5371 target = (target * 0.15) + (current * 0.85);
5377 set_horizontal_position (current);
5386 Editor::session_going_away ()
5388 _have_idled = false;
5390 _session_connections.drop_connections ();
5392 super_rapid_screen_update_connection.disconnect ();
5394 selection->clear ();
5395 cut_buffer->clear ();
5397 clicked_regionview = 0;
5398 clicked_axisview = 0;
5399 clicked_routeview = 0;
5400 entered_regionview = 0;
5402 last_update_frame = 0;
5405 playhead_cursor->hide ();
5407 /* rip everything out of the list displays */
5411 _route_groups->clear ();
5413 /* do this first so that deleting a track doesn't reset cms to null
5414 and thus cause a leak.
5417 if (current_mixer_strip) {
5418 if (current_mixer_strip->get_parent() != 0) {
5419 global_hpacker.remove (*current_mixer_strip);
5421 delete current_mixer_strip;
5422 current_mixer_strip = 0;
5425 /* delete all trackviews */
5427 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5430 track_views.clear ();
5432 nudge_clock->set_session (0);
5434 editor_list_button.set_active(false);
5435 editor_list_button.set_sensitive(false);
5437 /* clear tempo/meter rulers */
5438 remove_metric_marks ();
5440 clear_marker_display ();
5442 stop_step_editing ();
5444 /* get rid of any existing editor mixer strip */
5446 WindowTitle title(Glib::get_application_name());
5447 title += _("Editor");
5449 set_title (title.get_string());
5451 SessionHandlePtr::session_going_away ();
5456 Editor::show_editor_list (bool yn)
5459 _the_notebook.show ();
5461 _the_notebook.hide ();
5466 Editor::change_region_layering_order (bool from_context_menu)
5468 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5470 if (!clicked_routeview) {
5471 if (layering_order_editor) {
5472 layering_order_editor->hide ();
5477 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5483 boost::shared_ptr<Playlist> pl = track->playlist();
5489 if (layering_order_editor == 0) {
5490 layering_order_editor = new RegionLayeringOrderEditor (*this);
5493 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5494 layering_order_editor->maybe_present ();
5498 Editor::update_region_layering_order_editor ()
5500 if (layering_order_editor && layering_order_editor->is_visible ()) {
5501 change_region_layering_order (true);
5506 Editor::setup_fade_images ()
5508 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5509 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5510 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5511 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5512 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5514 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5515 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5516 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5517 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5518 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5520 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5521 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5522 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5523 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5524 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5526 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5527 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5528 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5529 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5530 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5534 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5536 Editor::action_menu_item (std::string const & name)
5538 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5541 return *manage (a->create_menu_item ());
5545 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5547 EventBox* b = manage (new EventBox);
5548 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5549 Label* l = manage (new Label (name));
5553 _the_notebook.append_page (widget, *b);
5557 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5559 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5560 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5563 if (ev->type == GDK_2BUTTON_PRESS) {
5565 /* double-click on a notebook tab shrinks or expands the notebook */
5567 if (_notebook_shrunk) {
5568 if (pre_notebook_shrink_pane_width) {
5569 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5571 _notebook_shrunk = false;
5573 pre_notebook_shrink_pane_width = edit_pane.get_position();
5575 /* this expands the LHS of the edit pane to cover the notebook
5576 PAGE but leaves the tabs visible.
5578 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5579 _notebook_shrunk = true;
5587 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5589 using namespace Menu_Helpers;
5591 MenuList& items = _control_point_context_menu.items ();
5594 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5595 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5596 if (!can_remove_control_point (item)) {
5597 items.back().set_sensitive (false);
5600 _control_point_context_menu.popup (event->button.button, event->button.time);
5604 Editor::zoom_vertical_modifier_released()
5606 _stepping_axis_view = 0;
5610 Editor::ui_parameter_changed (string parameter)
5612 if (parameter == "icon-set") {
5613 while (!_cursor_stack.empty()) {
5614 _cursor_stack.pop();
5616 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5617 } else if (parameter == "draggable-playhead") {
5618 if (_verbose_cursor) {
5619 playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());