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 (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1763 edit_items.push_back (SeparatorElem());
1764 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1766 edit_items.push_back (SeparatorElem());
1768 edit_items.push_back (
1770 _("Move Range Start to Previous Region Boundary"),
1771 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1775 edit_items.push_back (
1777 _("Move Range Start to Next Region Boundary"),
1778 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1782 edit_items.push_back (
1784 _("Move Range End to Previous Region Boundary"),
1785 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1789 edit_items.push_back (
1791 _("Move Range End to Next Region Boundary"),
1792 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1796 edit_items.push_back (SeparatorElem());
1797 edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1798 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1800 edit_items.push_back (SeparatorElem());
1801 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1803 edit_items.push_back (SeparatorElem());
1804 edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1805 edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1807 edit_items.push_back (SeparatorElem());
1808 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1810 edit_items.push_back (SeparatorElem());
1811 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1812 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1813 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1815 edit_items.push_back (SeparatorElem());
1816 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1817 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1818 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1819 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1820 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1821 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1822 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1828 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1830 using namespace Menu_Helpers;
1834 Menu *play_menu = manage (new Menu);
1835 MenuList& play_items = play_menu->items();
1836 play_menu->set_name ("ArdourContextMenu");
1838 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1839 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1840 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1841 play_items.push_back (SeparatorElem());
1842 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1844 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1848 Menu *select_menu = manage (new Menu);
1849 MenuList& select_items = select_menu->items();
1850 select_menu->set_name ("ArdourContextMenu");
1852 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1853 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1854 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1855 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1856 select_items.push_back (SeparatorElem());
1857 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1858 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1859 select_items.push_back (SeparatorElem());
1860 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1861 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1862 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1863 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1864 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1865 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1866 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1868 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1872 Menu *cutnpaste_menu = manage (new Menu);
1873 MenuList& cutnpaste_items = cutnpaste_menu->items();
1874 cutnpaste_menu->set_name ("ArdourContextMenu");
1876 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1877 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1878 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1880 cutnpaste_items.push_back (SeparatorElem());
1882 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1883 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1885 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1887 /* Adding new material */
1889 edit_items.push_back (SeparatorElem());
1890 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1891 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1895 Menu *nudge_menu = manage (new Menu());
1896 MenuList& nudge_items = nudge_menu->items();
1897 nudge_menu->set_name ("ArdourContextMenu");
1899 edit_items.push_back (SeparatorElem());
1900 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1901 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1902 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1903 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1905 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1909 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1911 using namespace Menu_Helpers;
1915 Menu *play_menu = manage (new Menu);
1916 MenuList& play_items = play_menu->items();
1917 play_menu->set_name ("ArdourContextMenu");
1919 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1920 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1921 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1925 Menu *select_menu = manage (new Menu);
1926 MenuList& select_items = select_menu->items();
1927 select_menu->set_name ("ArdourContextMenu");
1929 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1930 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1931 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1932 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1933 select_items.push_back (SeparatorElem());
1934 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1935 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1936 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1937 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1939 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1943 Menu *cutnpaste_menu = manage (new Menu);
1944 MenuList& cutnpaste_items = cutnpaste_menu->items();
1945 cutnpaste_menu->set_name ("ArdourContextMenu");
1947 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1948 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1949 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1951 Menu *nudge_menu = manage (new Menu());
1952 MenuList& nudge_items = nudge_menu->items();
1953 nudge_menu->set_name ("ArdourContextMenu");
1955 edit_items.push_back (SeparatorElem());
1956 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1957 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1958 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1959 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1961 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1965 Editor::snap_type() const
1971 Editor::snap_mode() const
1977 Editor::set_snap_to (SnapType st)
1979 unsigned int snap_ind = (unsigned int)st;
1983 if (snap_ind > snap_type_strings.size() - 1) {
1985 _snap_type = (SnapType)snap_ind;
1988 string str = snap_type_strings[snap_ind];
1990 if (str != snap_type_selector.get_text()) {
1991 snap_type_selector.set_text (str);
1996 switch (_snap_type) {
1997 case SnapToBeatDiv128:
1998 case SnapToBeatDiv64:
1999 case SnapToBeatDiv32:
2000 case SnapToBeatDiv28:
2001 case SnapToBeatDiv24:
2002 case SnapToBeatDiv20:
2003 case SnapToBeatDiv16:
2004 case SnapToBeatDiv14:
2005 case SnapToBeatDiv12:
2006 case SnapToBeatDiv10:
2007 case SnapToBeatDiv8:
2008 case SnapToBeatDiv7:
2009 case SnapToBeatDiv6:
2010 case SnapToBeatDiv5:
2011 case SnapToBeatDiv4:
2012 case SnapToBeatDiv3:
2013 case SnapToBeatDiv2: {
2014 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2015 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2017 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2018 current_bbt_points_begin, current_bbt_points_end);
2019 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2020 current_bbt_points_begin, current_bbt_points_end);
2021 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2025 case SnapToRegionStart:
2026 case SnapToRegionEnd:
2027 case SnapToRegionSync:
2028 case SnapToRegionBoundary:
2029 build_region_boundary_cache ();
2037 SnapChanged (); /* EMIT SIGNAL */
2041 Editor::set_snap_mode (SnapMode mode)
2043 string str = snap_mode_strings[(int)mode];
2045 if (_internal_editing) {
2046 internal_snap_mode = mode;
2048 pre_internal_snap_mode = mode;
2053 if (str != snap_mode_selector.get_text ()) {
2054 snap_mode_selector.set_text (str);
2060 Editor::set_edit_point_preference (EditPoint ep, bool force)
2062 bool changed = (_edit_point != ep);
2065 string str = edit_point_strings[(int)ep];
2067 if (Profile->get_mixbus())
2068 if (ep == EditAtSelectedMarker)
2069 ep = EditAtPlayhead;
2071 if (str != edit_point_selector.get_text ()) {
2072 edit_point_selector.set_text (str);
2075 reset_canvas_cursor ();
2077 if (!force && !changed) {
2081 const char* action=NULL;
2083 switch (_edit_point) {
2084 case EditAtPlayhead:
2085 action = "edit-at-playhead";
2087 case EditAtSelectedMarker:
2088 action = "edit-at-marker";
2091 action = "edit-at-mouse";
2095 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2097 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2101 bool in_track_canvas;
2103 if (!mouse_frame (foo, in_track_canvas)) {
2104 in_track_canvas = false;
2107 reset_canvas_action_sensitivity (in_track_canvas);
2113 Editor::set_state (const XMLNode& node, int /*version*/)
2115 const XMLProperty* prop;
2122 g.base_width = default_width;
2123 g.base_height = default_height;
2127 if ((geometry = find_named_node (node, "geometry")) != 0) {
2131 if ((prop = geometry->property("x_size")) == 0) {
2132 prop = geometry->property ("x-size");
2135 g.base_width = atoi(prop->value());
2137 if ((prop = geometry->property("y_size")) == 0) {
2138 prop = geometry->property ("y-size");
2141 g.base_height = atoi(prop->value());
2144 if ((prop = geometry->property ("x_pos")) == 0) {
2145 prop = geometry->property ("x-pos");
2148 x = atoi (prop->value());
2151 if ((prop = geometry->property ("y_pos")) == 0) {
2152 prop = geometry->property ("y-pos");
2155 y = atoi (prop->value());
2159 set_default_size (g.base_width, g.base_height);
2162 if (_session && (prop = node.property ("playhead"))) {
2164 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2165 playhead_cursor->set_position (pos);
2167 playhead_cursor->set_position (0);
2170 if ((prop = node.property ("mixer-width"))) {
2171 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2174 if ((prop = node.property ("zoom-focus"))) {
2175 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2178 if ((prop = node.property ("zoom"))) {
2179 /* older versions of ardour used floating point samples_per_pixel */
2180 double f = PBD::atof (prop->value());
2181 reset_zoom (llrintf (f));
2183 reset_zoom (samples_per_pixel);
2186 if ((prop = node.property ("visible-track-count"))) {
2187 set_visible_track_count (PBD::atoi (prop->value()));
2190 if ((prop = node.property ("snap-to"))) {
2191 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2194 if ((prop = node.property ("snap-mode"))) {
2195 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2198 if ((prop = node.property ("internal-snap-to"))) {
2199 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2202 if ((prop = node.property ("internal-snap-mode"))) {
2203 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2206 if ((prop = node.property ("pre-internal-snap-to"))) {
2207 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2211 if ((prop = node.property ("pre-internal-snap-mode"))) {
2212 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2215 if ((prop = node.property ("mouse-mode"))) {
2216 MouseMode m = str2mousemode(prop->value());
2217 set_mouse_mode (m, true);
2219 set_mouse_mode (MouseObject, true);
2222 if ((prop = node.property ("left-frame")) != 0) {
2224 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2228 reset_x_origin (pos);
2232 if ((prop = node.property ("y-origin")) != 0) {
2233 reset_y_origin (atof (prop->value ()));
2236 if ((prop = node.property ("internal-edit"))) {
2237 bool yn = string_is_affirmative (prop->value());
2238 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2240 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2241 tact->set_active (!yn);
2242 tact->set_active (yn);
2246 if ((prop = node.property ("join-object-range"))) {
2247 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2248 bool yn = string_is_affirmative (prop->value());
2250 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2251 tact->set_active (!yn);
2252 tact->set_active (yn);
2254 set_mouse_mode(mouse_mode, true);
2257 if ((prop = node.property ("edit-point"))) {
2258 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2261 if ((prop = node.property ("show-measures"))) {
2262 bool yn = string_is_affirmative (prop->value());
2263 _show_measures = yn;
2264 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2266 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2267 /* do it twice to force the change */
2268 tact->set_active (!yn);
2269 tact->set_active (yn);
2273 if ((prop = node.property ("follow-playhead"))) {
2274 bool yn = string_is_affirmative (prop->value());
2275 set_follow_playhead (yn);
2276 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2278 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2279 if (tact->get_active() != yn) {
2280 tact->set_active (yn);
2285 if ((prop = node.property ("stationary-playhead"))) {
2286 bool yn = string_is_affirmative (prop->value());
2287 set_stationary_playhead (yn);
2288 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2290 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2291 if (tact->get_active() != yn) {
2292 tact->set_active (yn);
2297 if ((prop = node.property ("region-list-sort-type"))) {
2298 RegionListSortType st;
2299 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2302 if ((prop = node.property ("show-editor-mixer"))) {
2304 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2307 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2308 bool yn = string_is_affirmative (prop->value());
2310 /* do it twice to force the change */
2312 tact->set_active (!yn);
2313 tact->set_active (yn);
2316 if ((prop = node.property ("show-editor-list"))) {
2318 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2321 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2322 bool yn = string_is_affirmative (prop->value());
2324 /* do it twice to force the change */
2326 tact->set_active (!yn);
2327 tact->set_active (yn);
2330 if ((prop = node.property (X_("editor-list-page")))) {
2331 _the_notebook.set_current_page (atoi (prop->value ()));
2334 if ((prop = node.property (X_("show-marker-lines")))) {
2335 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2337 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2338 bool yn = string_is_affirmative (prop->value ());
2340 tact->set_active (!yn);
2341 tact->set_active (yn);
2344 XMLNodeList children = node.children ();
2345 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2346 selection->set_state (**i, Stateful::current_state_version);
2347 _regions->set_state (**i);
2350 if ((prop = node.property ("maximised"))) {
2351 bool yn = string_is_affirmative (prop->value());
2352 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2354 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2355 bool fs = tact && tact->get_active();
2357 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2361 if ((prop = node.property ("nudge-clock-value"))) {
2363 sscanf (prop->value().c_str(), "%" PRId64, &f);
2364 nudge_clock->set (f);
2366 nudge_clock->set_mode (AudioClock::Timecode);
2367 nudge_clock->set (_session->frame_rate() * 5, true);
2374 Editor::get_state ()
2376 XMLNode* node = new XMLNode ("Editor");
2379 id().print (buf, sizeof (buf));
2380 node->add_property ("id", buf);
2382 if (is_realized()) {
2383 Glib::RefPtr<Gdk::Window> win = get_window();
2385 int x, y, width, height;
2386 win->get_root_origin(x, y);
2387 win->get_size(width, height);
2389 XMLNode* geometry = new XMLNode ("geometry");
2391 snprintf(buf, sizeof(buf), "%d", width);
2392 geometry->add_property("x-size", string(buf));
2393 snprintf(buf, sizeof(buf), "%d", height);
2394 geometry->add_property("y-size", string(buf));
2395 snprintf(buf, sizeof(buf), "%d", x);
2396 geometry->add_property("x-pos", string(buf));
2397 snprintf(buf, sizeof(buf), "%d", y);
2398 geometry->add_property("y-pos", string(buf));
2399 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2400 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2401 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2402 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2403 geometry->add_property("edit-vertical-pane-pos", string(buf));
2405 node->add_child_nocopy (*geometry);
2408 maybe_add_mixer_strip_width (*node);
2410 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2412 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2413 node->add_property ("zoom", buf);
2414 node->add_property ("snap-to", enum_2_string (_snap_type));
2415 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2416 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2417 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2418 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2419 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2420 node->add_property ("edit-point", enum_2_string (_edit_point));
2421 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2422 node->add_property ("visible-track-count", buf);
2424 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2425 node->add_property ("playhead", buf);
2426 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2427 node->add_property ("left-frame", buf);
2428 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2429 node->add_property ("y-origin", buf);
2431 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2432 node->add_property ("maximised", _maximised ? "yes" : "no");
2433 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2434 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2435 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2436 node->add_property ("mouse-mode", enum2str(mouse_mode));
2437 node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2438 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2440 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2442 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2443 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2446 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2448 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2449 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2452 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2453 node->add_property (X_("editor-list-page"), buf);
2455 if (button_bindings) {
2456 XMLNode* bb = new XMLNode (X_("Buttons"));
2457 button_bindings->save (*bb);
2458 node->add_child_nocopy (*bb);
2461 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2463 node->add_child_nocopy (selection->get_state ());
2464 node->add_child_nocopy (_regions->get_state ());
2466 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2467 node->add_property ("nudge-clock-value", buf);
2472 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2473 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2475 * @return pair: TimeAxisView that y is over, layer index.
2477 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2478 * in stacked or expanded region display mode, otherwise 0.
2480 std::pair<TimeAxisView *, double>
2481 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2483 if (!trackview_relative_offset) {
2484 y -= _trackview_group->canvas_origin().y;
2488 return std::make_pair ( (TimeAxisView *) 0, 0);
2491 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2493 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2500 return std::make_pair ( (TimeAxisView *) 0, 0);
2503 /** Snap a position to the grid, if appropriate, taking into account current
2504 * grid settings and also the state of any snap modifier keys that may be pressed.
2505 * @param start Position to snap.
2506 * @param event Event to get current key modifier information from, or 0.
2509 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2511 if (!_session || !event) {
2515 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2516 if (_snap_mode == SnapOff) {
2517 snap_to_internal (start, direction, for_mark);
2520 if (_snap_mode != SnapOff) {
2521 snap_to_internal (start, direction, for_mark);
2527 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2529 if (!_session || _snap_mode == SnapOff) {
2533 snap_to_internal (start, direction, for_mark);
2537 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2539 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2540 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2542 switch (_snap_type) {
2543 case SnapToTimecodeFrame:
2544 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2545 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2547 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2551 case SnapToTimecodeSeconds:
2552 if (_session->config.get_timecode_offset_negative()) {
2553 start += _session->config.get_timecode_offset ();
2555 start -= _session->config.get_timecode_offset ();
2557 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2558 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2560 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2563 if (_session->config.get_timecode_offset_negative()) {
2564 start -= _session->config.get_timecode_offset ();
2566 start += _session->config.get_timecode_offset ();
2570 case SnapToTimecodeMinutes:
2571 if (_session->config.get_timecode_offset_negative()) {
2572 start += _session->config.get_timecode_offset ();
2574 start -= _session->config.get_timecode_offset ();
2576 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2577 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2579 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2581 if (_session->config.get_timecode_offset_negative()) {
2582 start -= _session->config.get_timecode_offset ();
2584 start += _session->config.get_timecode_offset ();
2588 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2594 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2596 const framepos_t one_second = _session->frame_rate();
2597 const framepos_t one_minute = _session->frame_rate() * 60;
2598 framepos_t presnap = start;
2602 switch (_snap_type) {
2603 case SnapToTimecodeFrame:
2604 case SnapToTimecodeSeconds:
2605 case SnapToTimecodeMinutes:
2606 return timecode_snap_to_internal (start, direction, for_mark);
2609 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2610 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2612 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2617 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2618 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2620 start = (framepos_t) floor ((double) start / one_second) * one_second;
2625 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2626 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2628 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2633 start = _session->tempo_map().round_to_bar (start, direction);
2637 start = _session->tempo_map().round_to_beat (start, direction);
2640 case SnapToBeatDiv128:
2641 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2643 case SnapToBeatDiv64:
2644 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2646 case SnapToBeatDiv32:
2647 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2649 case SnapToBeatDiv28:
2650 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2652 case SnapToBeatDiv24:
2653 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2655 case SnapToBeatDiv20:
2656 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2658 case SnapToBeatDiv16:
2659 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2661 case SnapToBeatDiv14:
2662 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2664 case SnapToBeatDiv12:
2665 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2667 case SnapToBeatDiv10:
2668 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2670 case SnapToBeatDiv8:
2671 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2673 case SnapToBeatDiv7:
2674 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2676 case SnapToBeatDiv6:
2677 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2679 case SnapToBeatDiv5:
2680 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2682 case SnapToBeatDiv4:
2683 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2685 case SnapToBeatDiv3:
2686 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2688 case SnapToBeatDiv2:
2689 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2697 _session->locations()->marks_either_side (start, before, after);
2699 if (before == max_framepos && after == max_framepos) {
2700 /* No marks to snap to, so just don't snap */
2702 } else if (before == max_framepos) {
2704 } else if (after == max_framepos) {
2706 } else if (before != max_framepos && after != max_framepos) {
2707 /* have before and after */
2708 if ((start - before) < (after - start)) {
2717 case SnapToRegionStart:
2718 case SnapToRegionEnd:
2719 case SnapToRegionSync:
2720 case SnapToRegionBoundary:
2721 if (!region_boundary_cache.empty()) {
2723 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2724 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2726 if (direction > 0) {
2727 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2729 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2732 if (next != region_boundary_cache.begin ()) {
2737 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2738 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2740 if (start > (p + n) / 2) {
2749 switch (_snap_mode) {
2755 if (presnap > start) {
2756 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2760 } else if (presnap < start) {
2761 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2767 /* handled at entry */
2775 Editor::setup_toolbar ()
2777 HBox* mode_box = manage(new HBox);
2778 mode_box->set_border_width (2);
2779 mode_box->set_spacing(2);
2781 HBox* mouse_mode_box = manage (new HBox);
2782 HBox* mouse_mode_hbox = manage (new HBox);
2783 VBox* mouse_mode_vbox = manage (new VBox);
2784 Alignment* mouse_mode_align = manage (new Alignment);
2786 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
2787 //mouse_mode_size_group->add_widget (smart_mode_button);
2788 mouse_mode_size_group->add_widget (mouse_move_button);
2789 mouse_mode_size_group->add_widget (mouse_cut_button);
2790 mouse_mode_size_group->add_widget (mouse_select_button);
2791 mouse_mode_size_group->add_widget (mouse_zoom_button);
2792 mouse_mode_size_group->add_widget (mouse_gain_button);
2793 mouse_mode_size_group->add_widget (mouse_timefx_button);
2794 mouse_mode_size_group->add_widget (mouse_audition_button);
2795 mouse_mode_size_group->add_widget (mouse_draw_button);
2796 mouse_mode_size_group->add_widget (internal_edit_button);
2798 if (!ARDOUR::Profile->get_small_screen()) {
2799 /* make them just a bit bigger */
2800 mouse_move_button.set_size_request (24, 30);
2802 /* make them just a bit taller */
2803 mouse_move_button.set_size_request (-1, 30);
2805 mouse_mode_hbox->set_spacing (2);
2807 if (!ARDOUR::Profile->get_trx()) {
2808 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2811 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2812 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2814 if (!ARDOUR::Profile->get_mixbus()) {
2815 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2816 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2819 if (!ARDOUR::Profile->get_trx()) {
2820 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2821 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2822 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2823 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2824 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 4);
2827 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2829 mouse_mode_align->add (*mouse_mode_vbox);
2830 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2832 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2834 edit_mode_selector.set_name ("mouse mode button");
2835 edit_mode_selector.add_elements (ArdourButton::Inset);
2837 if (!ARDOUR::Profile->get_trx()) {
2838 mode_box->pack_start (edit_mode_selector, false, false);
2840 mode_box->pack_start (*mouse_mode_box, false, false);
2842 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2843 _mouse_mode_tearoff->set_name ("MouseModeBase");
2844 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2846 if (Profile->get_sae() || Profile->get_mixbus() ) {
2847 _mouse_mode_tearoff->set_can_be_torn_off (false);
2850 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2851 &_mouse_mode_tearoff->tearoff_window()));
2852 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2853 &_mouse_mode_tearoff->tearoff_window(), 1));
2854 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2855 &_mouse_mode_tearoff->tearoff_window()));
2856 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2857 &_mouse_mode_tearoff->tearoff_window(), 1));
2861 _zoom_box.set_spacing (2);
2862 _zoom_box.set_border_width (2);
2866 zoom_preset_selector.set_name ("zoom button");
2867 zoom_preset_selector.set_image(::get_icon ("time_exp"));
2868 zoom_preset_selector.set_size_request (42, -1);
2870 zoom_in_button.set_name ("zoom button");
2871 // zoom_in_button.add_elements ( ArdourButton::Inset );
2872 zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2873 zoom_in_button.set_image(::get_icon ("zoom_in"));
2874 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2875 zoom_in_button.set_related_action (act);
2877 zoom_out_button.set_name ("zoom button");
2878 // zoom_out_button.add_elements ( ArdourButton::Inset );
2879 zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2880 zoom_out_button.set_image(::get_icon ("zoom_out"));
2881 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2882 zoom_out_button.set_related_action (act);
2884 zoom_out_full_button.set_name ("zoom button");
2885 // zoom_out_full_button.add_elements ( ArdourButton::Inset );
2886 zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2887 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2888 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2889 zoom_out_full_button.set_related_action (act);
2891 zoom_focus_selector.set_name ("zoom button");
2892 // zoom_focus_selector.add_elements (ArdourButton::Inset);
2894 if (ARDOUR::Profile->get_mixbus()) {
2895 _zoom_box.pack_start (zoom_preset_selector, false, false);
2896 } else if (ARDOUR::Profile->get_trx()) {
2897 mode_box->pack_start (zoom_out_button, false, false);
2898 mode_box->pack_start (zoom_in_button, false, false);
2900 _zoom_box.pack_start (zoom_out_button, false, false);
2901 _zoom_box.pack_start (zoom_in_button, false, false);
2902 _zoom_box.pack_start (zoom_out_full_button, false, false);
2903 _zoom_box.pack_start (zoom_focus_selector, false, false);
2906 /* Track zoom buttons */
2907 visible_tracks_selector.set_name ("zoom button");
2908 // visible_tracks_selector.add_elements ( ArdourButton::Inset );
2909 if (Profile->get_mixbus()) {
2910 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2911 visible_tracks_selector.set_size_request (42, -1);
2913 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 40, 2);
2916 tav_expand_button.set_name ("zoom button");
2917 // tav_expand_button.add_elements ( ArdourButton::FlatFace );
2918 tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2919 tav_expand_button.set_size_request (-1, 20);
2920 tav_expand_button.set_image(::get_icon ("tav_exp"));
2921 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2922 tav_expand_button.set_related_action (act);
2924 tav_shrink_button.set_name ("zoom button");
2925 // tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2926 tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2927 tav_shrink_button.set_size_request (-1, 20);
2928 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2929 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2930 tav_shrink_button.set_related_action (act);
2932 if (ARDOUR::Profile->get_mixbus()) {
2933 _zoom_box.pack_start (visible_tracks_selector);
2934 } else if (ARDOUR::Profile->get_trx()) {
2935 _zoom_box.pack_start (tav_shrink_button);
2936 _zoom_box.pack_start (tav_expand_button);
2938 _zoom_box.pack_start (visible_tracks_selector);
2939 _zoom_box.pack_start (tav_shrink_button);
2940 _zoom_box.pack_start (tav_expand_button);
2943 if (!ARDOUR::Profile->get_trx()) {
2944 _zoom_tearoff = manage (new TearOff (_zoom_box));
2946 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2947 &_zoom_tearoff->tearoff_window()));
2948 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2949 &_zoom_tearoff->tearoff_window(), 0));
2950 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2951 &_zoom_tearoff->tearoff_window()));
2952 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2953 &_zoom_tearoff->tearoff_window(), 0));
2956 if (Profile->get_sae() || Profile->get_mixbus() ) {
2957 _zoom_tearoff->set_can_be_torn_off (false);
2960 snap_box.set_spacing (2);
2961 snap_box.set_border_width (2);
2963 snap_type_selector.set_name ("mouse mode button");
2964 snap_type_selector.add_elements (ArdourButton::Inset);
2966 snap_mode_selector.set_name ("mouse mode button");
2967 snap_mode_selector.add_elements (ArdourButton::Inset);
2969 edit_point_selector.set_name ("mouse mode button");
2970 edit_point_selector.add_elements (ArdourButton::Inset);
2972 snap_box.pack_start (snap_mode_selector, false, false);
2973 snap_box.pack_start (snap_type_selector, false, false);
2974 snap_box.pack_start (edit_point_selector, false, false);
2978 HBox *nudge_box = manage (new HBox);
2979 nudge_box->set_spacing (2);
2980 nudge_box->set_border_width (2);
2982 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
2983 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
2985 nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2986 nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2988 nudge_box->pack_start (nudge_backward_button, false, false);
2989 nudge_box->pack_start (nudge_forward_button, false, false);
2990 nudge_box->pack_start (*nudge_clock, false, false);
2993 /* Pack everything in... */
2995 HBox* hbox = manage (new HBox);
2996 hbox->set_spacing(2);
2998 _tools_tearoff = manage (new TearOff (*hbox));
2999 _tools_tearoff->set_name ("MouseModeBase");
3000 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3002 if (Profile->get_sae() || Profile->get_mixbus()) {
3003 _tools_tearoff->set_can_be_torn_off (false);
3006 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3007 &_tools_tearoff->tearoff_window()));
3008 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3009 &_tools_tearoff->tearoff_window(), 0));
3010 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3011 &_tools_tearoff->tearoff_window()));
3012 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3013 &_tools_tearoff->tearoff_window(), 0));
3015 toolbar_hbox.set_spacing (2);
3016 toolbar_hbox.set_border_width (1);
3018 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3019 if (!ARDOUR::Profile->get_trx()) {
3020 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3021 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3024 if (!ARDOUR::Profile->get_trx()) {
3025 hbox->pack_start (snap_box, false, false);
3026 if (!Profile->get_small_screen()) {
3027 hbox->pack_start (*nudge_box, false, false);
3029 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3032 hbox->pack_start (panic_box, false, false);
3036 toolbar_base.set_name ("ToolBarBase");
3037 toolbar_base.add (toolbar_hbox);
3039 _toolbar_viewport.add (toolbar_base);
3040 /* stick to the required height but allow width to vary if there's not enough room */
3041 _toolbar_viewport.set_size_request (1, -1);
3043 toolbar_frame.set_shadow_type (SHADOW_OUT);
3044 toolbar_frame.set_name ("BaseFrame");
3045 toolbar_frame.add (_toolbar_viewport);
3049 Editor::build_edit_point_menu ()
3051 using namespace Menu_Helpers;
3053 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3054 if(!Profile->get_mixbus())
3055 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3056 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3058 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, 30, 2);
3062 Editor::build_edit_mode_menu ()
3064 using namespace Menu_Helpers;
3066 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3067 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3068 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3069 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3071 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, 30, 2);
3075 Editor::build_snap_mode_menu ()
3077 using namespace Menu_Helpers;
3079 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3080 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3081 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3083 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, 34, 2);
3087 Editor::build_snap_type_menu ()
3089 using namespace Menu_Helpers;
3091 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3092 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3093 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3094 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3095 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3096 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3097 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3098 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3099 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3100 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3101 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3102 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3103 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3104 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3105 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3106 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3107 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3108 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3109 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3110 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3111 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3112 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3113 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3114 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3115 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3116 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3117 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3118 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3119 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3120 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3122 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, 34, 2);
3127 Editor::setup_tooltips ()
3129 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3130 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3131 ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
3132 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3133 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3134 ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3135 ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3136 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3137 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3138 ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3139 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3140 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3141 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3142 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3143 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3144 ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3145 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3146 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3147 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3148 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3149 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3150 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3151 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3152 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3153 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3154 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3158 Editor::convert_drop_to_paths (
3159 vector<string>& paths,
3160 const RefPtr<Gdk::DragContext>& /*context*/,
3163 const SelectionData& data,
3167 if (_session == 0) {
3171 vector<string> uris = data.get_uris();
3175 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3176 are actually URI lists. So do it by hand.
3179 if (data.get_target() != "text/plain") {
3183 /* Parse the "uri-list" format that Nautilus provides,
3184 where each pathname is delimited by \r\n.
3186 THERE MAY BE NO NULL TERMINATING CHAR!!!
3189 string txt = data.get_text();
3193 p = (char *) malloc (txt.length() + 1);
3194 txt.copy (p, txt.length(), 0);
3195 p[txt.length()] = '\0';
3201 while (g_ascii_isspace (*p))
3205 while (*q && (*q != '\n') && (*q != '\r')) {
3212 while (q > p && g_ascii_isspace (*q))
3217 uris.push_back (string (p, q - p + 1));
3221 p = strchr (p, '\n');
3233 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3234 if ((*i).substr (0,7) == "file://") {
3235 paths.push_back (Glib::filename_from_uri (*i));
3243 Editor::new_tempo_section ()
3248 Editor::map_transport_state ()
3250 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3252 if (_session && _session->transport_stopped()) {
3253 have_pending_keyboard_selection = false;
3256 update_loop_range_view ();
3262 Editor::begin_reversible_command (string name)
3265 _session->begin_reversible_command (name);
3270 Editor::begin_reversible_command (GQuark q)
3273 _session->begin_reversible_command (q);
3278 Editor::commit_reversible_command ()
3281 _session->commit_reversible_command ();
3286 Editor::history_changed ()
3290 if (undo_action && _session) {
3291 if (_session->undo_depth() == 0) {
3292 label = S_("Command|Undo");
3294 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3296 undo_action->property_label() = label;
3299 if (redo_action && _session) {
3300 if (_session->redo_depth() == 0) {
3303 label = string_compose(_("Redo (%1)"), _session->next_redo());
3305 redo_action->property_label() = label;
3310 Editor::duplicate_range (bool with_dialog)
3314 RegionSelection rs = get_regions_from_selection_and_entered ();
3316 if ( selection->time.length() == 0 && rs.empty()) {
3322 ArdourDialog win (_("Duplicate"));
3323 Label label (_("Number of duplications:"));
3324 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3325 SpinButton spinner (adjustment, 0.0, 1);
3328 win.get_vbox()->set_spacing (12);
3329 win.get_vbox()->pack_start (hbox);
3330 hbox.set_border_width (6);
3331 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3333 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3334 place, visually. so do this by hand.
3337 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3338 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3339 spinner.grab_focus();
3345 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3346 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3347 win.set_default_response (RESPONSE_ACCEPT);
3349 spinner.grab_focus ();
3351 switch (win.run ()) {
3352 case RESPONSE_ACCEPT:
3358 times = adjustment.get_value();
3361 if ((current_mouse_mode() == Editing::MouseRange)) {
3362 if (selection->time.length()) {
3363 duplicate_selection (times);
3365 } else if (get_smart_mode()) {
3366 if (selection->time.length()) {
3367 duplicate_selection (times);
3369 duplicate_some_regions (rs, times);
3371 duplicate_some_regions (rs, times);
3376 Editor::set_edit_mode (EditMode m)
3378 Config->set_edit_mode (m);
3382 Editor::cycle_edit_mode ()
3384 switch (Config->get_edit_mode()) {
3386 if (Profile->get_sae()) {
3387 Config->set_edit_mode (Lock);
3389 Config->set_edit_mode (Ripple);
3394 Config->set_edit_mode (Lock);
3397 Config->set_edit_mode (Slide);
3403 Editor::edit_mode_selection_done ( EditMode m )
3405 Config->set_edit_mode ( m );
3409 Editor::snap_type_selection_done (SnapType snaptype)
3411 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3413 ract->set_active ();
3418 Editor::snap_mode_selection_done (SnapMode mode)
3420 RefPtr<RadioAction> ract = snap_mode_action (mode);
3423 ract->set_active (true);
3428 Editor::cycle_edit_point (bool with_marker)
3430 if(Profile->get_mixbus())
3431 with_marker = false;
3433 switch (_edit_point) {
3435 set_edit_point_preference (EditAtPlayhead);
3437 case EditAtPlayhead:
3439 set_edit_point_preference (EditAtSelectedMarker);
3441 set_edit_point_preference (EditAtMouse);
3444 case EditAtSelectedMarker:
3445 set_edit_point_preference (EditAtMouse);
3451 Editor::edit_point_selection_done (EditPoint ep)
3453 set_edit_point_preference ( ep );
3457 Editor::build_zoom_focus_menu ()
3459 using namespace Menu_Helpers;
3461 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3462 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3463 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3464 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3465 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3466 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3468 set_size_request_to_display_given_text (zoom_focus_selector, longest (zoom_focus_strings), 30, 2);
3472 Editor::zoom_focus_selection_done ( ZoomFocus f )
3474 RefPtr<RadioAction> ract = zoom_focus_action (f);
3476 ract->set_active ();
3481 Editor::build_track_count_menu ()
3483 using namespace Menu_Helpers;
3485 if (!Profile->get_mixbus()) {
3486 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3487 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3488 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3489 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3490 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3491 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3492 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3493 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3494 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3495 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3496 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3497 visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3498 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3500 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3501 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3502 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3503 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3504 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3505 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3506 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3507 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3508 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3509 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selected tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3511 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3512 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3513 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3514 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3515 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3516 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3517 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3518 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3519 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3520 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3521 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3526 Editor::set_zoom_preset (int64_t ms)
3529 temporal_zoom_session();
3533 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3534 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3538 Editor::set_visible_track_count (int32_t n)
3540 _visible_track_count = n;
3542 /* if the canvas hasn't really been allocated any size yet, just
3543 record the desired number of visible tracks and return. when canvas
3544 allocation happens, we will get called again and then we can do the
3548 if (_visible_canvas_height <= 1) {
3555 if (_visible_track_count > 0) {
3556 h = trackviews_height() / _visible_track_count;
3557 std::ostringstream s;
3558 s << _visible_track_count;
3560 } else if (_visible_track_count == 0) {
3562 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3563 if ((*i)->marked_for_display()) {
3567 h = trackviews_height() / n;
3570 /* negative value means that the visible track count has
3571 been overridden by explicit track height changes.
3573 visible_tracks_selector.set_text (X_("*"));
3577 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3578 (*i)->set_height (h);
3581 if (str != visible_tracks_selector.get_text()) {
3582 visible_tracks_selector.set_text (str);
3587 Editor::override_visible_track_count ()
3589 _visible_track_count = -_visible_track_count;
3590 visible_tracks_selector.set_text ( _("*") );
3594 Editor::edit_controls_button_release (GdkEventButton* ev)
3596 if (Keyboard::is_context_menu_event (ev)) {
3597 ARDOUR_UI::instance()->add_route (this);
3598 } else if (ev->button == 1) {
3599 selection->clear_tracks ();
3606 Editor::mouse_select_button_release (GdkEventButton* ev)
3608 /* this handles just right-clicks */
3610 if (ev->button != 3) {
3618 Editor::set_zoom_focus (ZoomFocus f)
3620 string str = zoom_focus_strings[(int)f];
3622 if (str != zoom_focus_selector.get_text()) {
3623 zoom_focus_selector.set_text (str);
3626 if (zoom_focus != f) {
3633 Editor::cycle_zoom_focus ()
3635 switch (zoom_focus) {
3637 set_zoom_focus (ZoomFocusRight);
3639 case ZoomFocusRight:
3640 set_zoom_focus (ZoomFocusCenter);
3642 case ZoomFocusCenter:
3643 set_zoom_focus (ZoomFocusPlayhead);
3645 case ZoomFocusPlayhead:
3646 set_zoom_focus (ZoomFocusMouse);
3648 case ZoomFocusMouse:
3649 set_zoom_focus (ZoomFocusEdit);
3652 set_zoom_focus (ZoomFocusLeft);
3658 Editor::ensure_float (Window& win)
3660 win.set_transient_for (*this);
3664 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3666 /* recover or initialize pane positions. do this here rather than earlier because
3667 we don't want the positions to change the child allocations, which they seem to do.
3673 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3682 XMLNode* geometry = find_named_node (*node, "geometry");
3684 if (which == static_cast<Paned*> (&edit_pane)) {
3686 if (done & Horizontal) {
3690 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3691 _notebook_shrunk = string_is_affirmative (prop->value ());
3694 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3695 /* initial allocation is 90% to canvas, 10% to notebook */
3696 pos = (int) floor (alloc.get_width() * 0.90f);
3697 snprintf (buf, sizeof(buf), "%d", pos);
3699 pos = atoi (prop->value());
3702 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3703 edit_pane.set_position (pos);
3706 done = (Pane) (done | Horizontal);
3708 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3710 if (done & Vertical) {
3714 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3715 /* initial allocation is 90% to canvas, 10% to summary */
3716 pos = (int) floor (alloc.get_height() * 0.90f);
3717 snprintf (buf, sizeof(buf), "%d", pos);
3720 pos = atoi (prop->value());
3723 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3724 editor_summary_pane.set_position (pos);
3727 done = (Pane) (done | Vertical);
3732 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3734 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3735 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3736 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3737 top_hbox.remove (toolbar_frame);
3742 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3744 if (toolbar_frame.get_parent() == 0) {
3745 top_hbox.pack_end (toolbar_frame);
3750 Editor::set_show_measures (bool yn)
3752 if (_show_measures != yn) {
3755 if ((_show_measures = yn) == true) {
3757 tempo_lines->show();
3760 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3761 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3763 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3764 draw_measures (begin, end);
3772 Editor::toggle_follow_playhead ()
3774 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3776 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3777 set_follow_playhead (tact->get_active());
3781 /** @param yn true to follow playhead, otherwise false.
3782 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3785 Editor::set_follow_playhead (bool yn, bool catch_up)
3787 if (_follow_playhead != yn) {
3788 if ((_follow_playhead = yn) == true && catch_up) {
3790 reset_x_origin_to_follow_playhead ();
3797 Editor::toggle_stationary_playhead ()
3799 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3801 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3802 set_stationary_playhead (tact->get_active());
3807 Editor::set_stationary_playhead (bool yn)
3809 if (_stationary_playhead != yn) {
3810 if ((_stationary_playhead = yn) == true) {
3812 // FIXME need a 3.0 equivalent of this 2.X call
3813 // update_current_screen ();
3820 Editor::playlist_selector () const
3822 return *_playlist_selector;
3826 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3830 switch (_snap_type) {
3835 case SnapToBeatDiv128:
3838 case SnapToBeatDiv64:
3841 case SnapToBeatDiv32:
3844 case SnapToBeatDiv28:
3847 case SnapToBeatDiv24:
3850 case SnapToBeatDiv20:
3853 case SnapToBeatDiv16:
3856 case SnapToBeatDiv14:
3859 case SnapToBeatDiv12:
3862 case SnapToBeatDiv10:
3865 case SnapToBeatDiv8:
3868 case SnapToBeatDiv7:
3871 case SnapToBeatDiv6:
3874 case SnapToBeatDiv5:
3877 case SnapToBeatDiv4:
3880 case SnapToBeatDiv3:
3883 case SnapToBeatDiv2:
3889 return _session->tempo_map().meter_at (position).divisions_per_bar();
3894 case SnapToTimecodeFrame:
3895 case SnapToTimecodeSeconds:
3896 case SnapToTimecodeMinutes:
3899 case SnapToRegionStart:
3900 case SnapToRegionEnd:
3901 case SnapToRegionSync:
3902 case SnapToRegionBoundary:
3912 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3916 ret = nudge_clock->current_duration (pos);
3917 next = ret + 1; /* XXXX fix me */
3923 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3925 ArdourDialog dialog (_("Playlist Deletion"));
3926 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3927 "If it is kept, its audio files will not be cleaned.\n"
3928 "If it is deleted, audio files used by it alone will be cleaned."),
3931 dialog.set_position (WIN_POS_CENTER);
3932 dialog.get_vbox()->pack_start (label);
3936 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3937 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3938 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3940 switch (dialog.run ()) {
3941 case RESPONSE_ACCEPT:
3942 /* delete the playlist */
3946 case RESPONSE_REJECT:
3947 /* keep the playlist */
3959 Editor::audio_region_selection_covers (framepos_t where)
3961 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3962 if ((*a)->region()->covers (where)) {
3971 Editor::prepare_for_cleanup ()
3973 cut_buffer->clear_regions ();
3974 cut_buffer->clear_playlists ();
3976 selection->clear_regions ();
3977 selection->clear_playlists ();
3979 _regions->suspend_redisplay ();
3983 Editor::finish_cleanup ()
3985 _regions->resume_redisplay ();
3989 Editor::transport_loop_location()
3992 return _session->locations()->auto_loop_location();
3999 Editor::transport_punch_location()
4002 return _session->locations()->auto_punch_location();
4009 Editor::control_layout_scroll (GdkEventScroll* ev)
4011 /* Just forward to the normal canvas scroll method. The coordinate
4012 systems are different but since the canvas is always larger than the
4013 track headers, and aligned with the trackview area, this will work.
4015 In the not too distant future this layout is going away anyway and
4016 headers will be on the canvas.
4018 return canvas_scroll_event (ev, false);
4022 Editor::session_state_saved (string)
4025 _snapshots->redisplay ();
4029 Editor::update_tearoff_visibility()
4031 bool visible = Config->get_keep_tearoffs();
4032 _mouse_mode_tearoff->set_visible (visible);
4033 _tools_tearoff->set_visible (visible);
4034 if (_zoom_tearoff) {
4035 _zoom_tearoff->set_visible (visible);
4040 Editor::maximise_editing_space ()
4052 Editor::restore_editing_space ()
4064 * Make new playlists for a given track and also any others that belong
4065 * to the same active route group with the `select' property.
4070 Editor::new_playlists (TimeAxisView* v)
4072 begin_reversible_command (_("new playlists"));
4073 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4074 _session->playlists->get (playlists);
4075 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4076 commit_reversible_command ();
4080 * Use a copy of the current playlist for a given track and also any others that belong
4081 * to the same active route group with the `select' property.
4086 Editor::copy_playlists (TimeAxisView* v)
4088 begin_reversible_command (_("copy playlists"));
4089 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4090 _session->playlists->get (playlists);
4091 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4092 commit_reversible_command ();
4095 /** Clear the current playlist for a given track and also any others that belong
4096 * to the same active route group with the `select' property.
4101 Editor::clear_playlists (TimeAxisView* v)
4103 begin_reversible_command (_("clear playlists"));
4104 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4105 _session->playlists->get (playlists);
4106 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4107 commit_reversible_command ();
4111 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4113 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4117 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4119 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4123 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4125 atv.clear_playlist ();
4129 Editor::on_key_press_event (GdkEventKey* ev)
4131 return key_press_focus_accelerator_handler (*this, ev);
4135 Editor::on_key_release_event (GdkEventKey* ev)
4137 return Gtk::Window::on_key_release_event (ev);
4138 // return key_press_focus_accelerator_handler (*this, ev);
4141 /** Queue up a change to the viewport x origin.
4142 * @param frame New x origin.
4145 Editor::reset_x_origin (framepos_t frame)
4147 pending_visual_change.add (VisualChange::TimeOrigin);
4148 pending_visual_change.time_origin = frame;
4149 ensure_visual_change_idle_handler ();
4153 Editor::reset_y_origin (double y)
4155 pending_visual_change.add (VisualChange::YOrigin);
4156 pending_visual_change.y_origin = y;
4157 ensure_visual_change_idle_handler ();
4161 Editor::reset_zoom (framecnt_t spp)
4163 if (spp == samples_per_pixel) {
4167 pending_visual_change.add (VisualChange::ZoomLevel);
4168 pending_visual_change.samples_per_pixel = spp;
4169 ensure_visual_change_idle_handler ();
4173 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4175 reset_x_origin (frame);
4178 if (!no_save_visual) {
4179 undo_visual_stack.push_back (current_visual_state(false));
4183 Editor::VisualState::VisualState (bool with_tracks)
4184 : gui_state (with_tracks ? new GUIObjectState : 0)
4188 Editor::VisualState::~VisualState ()
4193 Editor::VisualState*
4194 Editor::current_visual_state (bool with_tracks)
4196 VisualState* vs = new VisualState (with_tracks);
4197 vs->y_position = vertical_adjustment.get_value();
4198 vs->samples_per_pixel = samples_per_pixel;
4199 vs->leftmost_frame = leftmost_frame;
4200 vs->zoom_focus = zoom_focus;
4203 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4210 Editor::undo_visual_state ()
4212 if (undo_visual_stack.empty()) {
4216 VisualState* vs = undo_visual_stack.back();
4217 undo_visual_stack.pop_back();
4220 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4222 use_visual_state (*vs);
4226 Editor::redo_visual_state ()
4228 if (redo_visual_stack.empty()) {
4232 VisualState* vs = redo_visual_stack.back();
4233 redo_visual_stack.pop_back();
4235 undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4237 use_visual_state (*vs);
4241 Editor::swap_visual_state ()
4243 if (undo_visual_stack.empty()) {
4244 redo_visual_state ();
4246 undo_visual_state ();
4251 Editor::use_visual_state (VisualState& vs)
4253 PBD::Unwinder<bool> nsv (no_save_visual, true);
4254 DisplaySuspender ds;
4256 vertical_adjustment.set_value (vs.y_position);
4258 set_zoom_focus (vs.zoom_focus);
4259 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4262 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4264 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4265 (*i)->reset_visual_state ();
4269 _routes->update_visibility ();
4272 /** This is the core function that controls the zoom level of the canvas. It is called
4273 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4274 * @param spp new number of samples per pixel
4277 Editor::set_samples_per_pixel (framecnt_t spp)
4283 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4284 const framecnt_t lots_of_pixels = 4000;
4286 /* if the zoom level is greater than what you'd get trying to display 3
4287 * days of audio on a really big screen, then it's too big.
4290 if (spp * lots_of_pixels > three_days) {
4294 samples_per_pixel = spp;
4297 tempo_lines->tempo_map_changed();
4300 bool const showing_time_selection = selection->time.length() > 0;
4302 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4303 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4304 (*i)->reshow_selection (selection->time);
4308 ZoomChanged (); /* EMIT_SIGNAL */
4310 ArdourCanvas::GtkCanvasViewport* c;
4312 c = get_track_canvas();
4314 c->canvas()->zoomed ();
4317 if (playhead_cursor) {
4318 playhead_cursor->set_position (playhead_cursor->current_frame ());
4321 refresh_location_display();
4322 _summary->set_overlays_dirty ();
4324 update_marker_labels ();
4330 Editor::queue_visual_videotimeline_update ()
4333 * pending_visual_change.add (VisualChange::VideoTimeline);
4334 * or maybe even more specific: which videotimeline-image
4335 * currently it calls update_video_timeline() to update
4336 * _all outdated_ images on the video-timeline.
4337 * see 'exposeimg()' in video_image_frame.cc
4339 ensure_visual_change_idle_handler ();
4343 Editor::ensure_visual_change_idle_handler ()
4345 if (pending_visual_change.idle_handler_id < 0) {
4346 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4347 pending_visual_change.being_handled = false;
4352 Editor::_idle_visual_changer (void* arg)
4354 return static_cast<Editor*>(arg)->idle_visual_changer ();
4358 Editor::idle_visual_changer ()
4360 /* set_horizontal_position() below (and maybe other calls) call
4361 gtk_main_iteration(), so it's possible that a signal will be handled
4362 half-way through this method. If this signal wants an
4363 idle_visual_changer we must schedule another one after this one, so
4364 mark the idle_handler_id as -1 here to allow that. Also make a note
4365 that we are doing the visual change, so that changes in response to
4366 super-rapid-screen-update can be dropped if we are still processing
4370 pending_visual_change.idle_handler_id = -1;
4371 pending_visual_change.being_handled = true;
4373 VisualChange vc = pending_visual_change;
4375 pending_visual_change.pending = (VisualChange::Type) 0;
4377 visual_changer (vc);
4379 pending_visual_change.being_handled = false;
4381 return 0; /* this is always a one-shot call */
4385 Editor::visual_changer (const VisualChange& vc)
4387 double const last_time_origin = horizontal_position ();
4389 if (vc.pending & VisualChange::ZoomLevel) {
4390 set_samples_per_pixel (vc.samples_per_pixel);
4392 compute_fixed_ruler_scale ();
4394 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4395 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4397 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4398 current_bbt_points_begin, current_bbt_points_end);
4399 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4400 current_bbt_points_begin, current_bbt_points_end);
4401 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4403 update_video_timeline();
4406 if (vc.pending & VisualChange::TimeOrigin) {
4407 set_horizontal_position (vc.time_origin / samples_per_pixel);
4410 if (vc.pending & VisualChange::YOrigin) {
4411 vertical_adjustment.set_value (vc.y_origin);
4414 if (last_time_origin == horizontal_position ()) {
4415 /* changed signal not emitted */
4416 update_fixed_rulers ();
4417 redisplay_tempo (true);
4420 if (!(vc.pending & VisualChange::ZoomLevel)) {
4421 update_video_timeline();
4424 _summary->set_overlays_dirty ();
4427 struct EditorOrderTimeAxisSorter {
4428 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4429 return a->order () < b->order ();
4434 Editor::sort_track_selection (TrackViewList& sel)
4436 EditorOrderTimeAxisSorter cmp;
4441 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4444 framepos_t where = 0;
4445 EditPoint ep = _edit_point;
4447 if(Profile->get_mixbus())
4448 if (ep == EditAtSelectedMarker)
4451 if (from_context_menu && (ep == EditAtMouse)) {
4452 return canvas_event_sample (&context_click_event, 0, 0);
4455 if (entered_marker) {
4456 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4457 return entered_marker->position();
4460 if (ignore_playhead && ep == EditAtPlayhead) {
4461 ep = EditAtSelectedMarker;
4465 case EditAtPlayhead:
4466 where = _session->audible_frame();
4467 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4470 case EditAtSelectedMarker:
4471 if (!selection->markers.empty()) {
4473 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4476 where = loc->start();
4480 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4488 if (!mouse_frame (where, ignored)) {
4489 /* XXX not right but what can we do ? */
4493 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4501 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4503 if (!_session) return;
4505 begin_reversible_command (cmd);
4509 if ((tll = transport_loop_location()) == 0) {
4510 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4511 XMLNode &before = _session->locations()->get_state();
4512 _session->locations()->add (loc, true);
4513 _session->set_auto_loop_location (loc);
4514 XMLNode &after = _session->locations()->get_state();
4515 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4517 XMLNode &before = tll->get_state();
4518 tll->set_hidden (false, this);
4519 tll->set (start, end);
4520 XMLNode &after = tll->get_state();
4521 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4524 commit_reversible_command ();
4528 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4530 if (!_session) return;
4532 begin_reversible_command (cmd);
4536 if ((tpl = transport_punch_location()) == 0) {
4537 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4538 XMLNode &before = _session->locations()->get_state();
4539 _session->locations()->add (loc, true);
4540 _session->set_auto_punch_location (loc);
4541 XMLNode &after = _session->locations()->get_state();
4542 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4545 XMLNode &before = tpl->get_state();
4546 tpl->set_hidden (false, this);
4547 tpl->set (start, end);
4548 XMLNode &after = tpl->get_state();
4549 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4552 commit_reversible_command ();
4555 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4556 * @param rs List to which found regions are added.
4557 * @param where Time to look at.
4558 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4561 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4563 const TrackViewList* tracks;
4566 tracks = &track_views;
4571 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4573 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4576 boost::shared_ptr<Track> tr;
4577 boost::shared_ptr<Playlist> pl;
4579 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4581 boost::shared_ptr<RegionList> regions = pl->regions_at (
4582 (framepos_t) floor ( (double) where * tr->speed()));
4584 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4585 RegionView* rv = rtv->view()->find_view (*i);
4596 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4598 const TrackViewList* tracks;
4601 tracks = &track_views;
4606 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4607 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4609 boost::shared_ptr<Track> tr;
4610 boost::shared_ptr<Playlist> pl;
4612 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4614 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4615 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4617 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4619 RegionView* rv = rtv->view()->find_view (*i);
4630 /** Get regions using the following method:
4632 * Make a region list using:
4633 * (a) any selected regions
4634 * (b) the intersection of any selected tracks and the edit point(*)
4635 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4637 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4639 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4643 Editor::get_regions_from_selection_and_edit_point ()
4645 RegionSelection regions;
4647 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4648 regions.add (entered_regionview);
4650 regions = selection->regions;
4653 if ( regions.empty() ) {
4654 TrackViewList tracks = selection->tracks;
4656 if (!tracks.empty()) {
4657 /* no region selected or entered, but some selected tracks:
4658 * act on all regions on the selected tracks at the edit point
4660 framepos_t const where = get_preferred_edit_position ();
4661 get_regions_at(regions, where, tracks);
4668 /** Get regions using the following method:
4670 * Make a region list using:
4671 * (a) any selected regions
4672 * (b) the intersection of any selected tracks and the edit point(*)
4673 * (c) if neither exists, then whatever region is under the mouse
4675 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4677 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4680 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4682 RegionSelection regions;
4684 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4685 regions.add (entered_regionview);
4687 regions = selection->regions;
4690 if ( regions.empty() ) {
4691 TrackViewList tracks = selection->tracks;
4693 if (!tracks.empty()) {
4694 /* no region selected or entered, but some selected tracks:
4695 * act on all regions on the selected tracks at the edit point
4697 get_regions_at(regions, pos, tracks);
4704 /** Start with regions that are selected, or the entered regionview if none are selected.
4705 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4706 * of the regions that we started with.
4710 Editor::get_regions_from_selection_and_entered ()
4712 RegionSelection regions = selection->regions;
4714 if (regions.empty() && entered_regionview) {
4715 regions.add (entered_regionview);
4722 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4724 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4726 RouteTimeAxisView* tatv;
4728 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4730 boost::shared_ptr<Playlist> pl;
4731 vector<boost::shared_ptr<Region> > results;
4733 boost::shared_ptr<Track> tr;
4735 if ((tr = tatv->track()) == 0) {
4740 if ((pl = (tr->playlist())) != 0) {
4741 if (src_comparison) {
4742 pl->get_source_equivalent_regions (region, results);
4744 pl->get_region_list_equivalent_regions (region, results);
4748 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4749 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4750 regions.push_back (marv);
4759 Editor::show_rhythm_ferret ()
4761 if (rhythm_ferret == 0) {
4762 rhythm_ferret = new RhythmFerret(*this);
4765 rhythm_ferret->set_session (_session);
4766 rhythm_ferret->show ();
4767 rhythm_ferret->present ();
4771 Editor::first_idle ()
4773 MessageDialog* dialog = 0;
4775 if (track_views.size() > 1) {
4776 dialog = new MessageDialog (
4778 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4782 ARDOUR_UI::instance()->flush_pending ();
4785 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4789 // first idle adds route children (automation tracks), so we need to redisplay here
4790 _routes->redisplay ();
4797 Editor::_idle_resize (gpointer arg)
4799 return ((Editor*)arg)->idle_resize ();
4803 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4805 if (resize_idle_id < 0) {
4806 resize_idle_id = g_idle_add (_idle_resize, this);
4807 _pending_resize_amount = 0;
4810 /* make a note of the smallest resulting height, so that we can clamp the
4811 lower limit at TimeAxisView::hSmall */
4813 int32_t min_resulting = INT32_MAX;
4815 _pending_resize_amount += h;
4816 _pending_resize_view = view;
4818 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4820 if (selection->tracks.contains (_pending_resize_view)) {
4821 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4822 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4826 if (min_resulting < 0) {
4831 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4832 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4836 /** Handle pending resizing of tracks */
4838 Editor::idle_resize ()
4840 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4842 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4843 selection->tracks.contains (_pending_resize_view)) {
4845 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4846 if (*i != _pending_resize_view) {
4847 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4852 _pending_resize_amount = 0;
4853 _group_tabs->set_dirty ();
4854 resize_idle_id = -1;
4862 ENSURE_GUI_THREAD (*this, &Editor::located);
4865 playhead_cursor->set_position (_session->audible_frame ());
4866 if (_follow_playhead && !_pending_initial_locate) {
4867 reset_x_origin_to_follow_playhead ();
4871 _pending_locate_request = false;
4872 _pending_initial_locate = false;
4876 Editor::region_view_added (RegionView *)
4878 _summary->set_background_dirty ();
4882 Editor::region_view_removed ()
4884 _summary->set_background_dirty ();
4888 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4890 TrackViewList::const_iterator j = track_views.begin ();
4891 while (j != track_views.end()) {
4892 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4893 if (rtv && rtv->route() == r) {
4904 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4908 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4909 TimeAxisView* tv = axis_view_from_route (*i);
4919 Editor::suspend_route_redisplay ()
4922 _routes->suspend_redisplay();
4927 Editor::resume_route_redisplay ()
4930 _routes->resume_redisplay();
4935 Editor::add_routes (RouteList& routes)
4937 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4939 RouteTimeAxisView *rtv;
4940 list<RouteTimeAxisView*> new_views;
4942 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4943 boost::shared_ptr<Route> route = (*x);
4945 if (route->is_auditioner() || route->is_monitor()) {
4949 DataType dt = route->input()->default_type();
4951 if (dt == ARDOUR::DataType::AUDIO) {
4952 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4953 rtv->set_route (route);
4954 } else if (dt == ARDOUR::DataType::MIDI) {
4955 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
4956 rtv->set_route (route);
4958 throw unknown_type();
4961 new_views.push_back (rtv);
4962 track_views.push_back (rtv);
4964 rtv->effective_gain_display ();
4966 if (internal_editing()) {
4967 rtv->enter_internal_edit_mode ();
4969 rtv->leave_internal_edit_mode ();
4972 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4973 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4976 if (new_views.size() > 0) {
4977 _routes->routes_added (new_views);
4978 _summary->routes_added (new_views);
4981 if (show_editor_mixer_when_tracks_arrive) {
4982 show_editor_mixer (true);
4985 editor_list_button.set_sensitive (true);
4989 Editor::timeaxisview_deleted (TimeAxisView *tv)
4991 if (tv == entered_track) {
4995 if (_session && _session->deletion_in_progress()) {
4996 /* the situation is under control */
5000 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5002 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5004 _routes->route_removed (tv);
5006 TimeAxisView::Children c = tv->get_child_list ();
5007 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5008 if (entered_track == i->get()) {
5013 /* remove it from the list of track views */
5015 TrackViewList::iterator i;
5017 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5018 i = track_views.erase (i);
5021 /* update whatever the current mixer strip is displaying, if revelant */
5023 boost::shared_ptr<Route> route;
5026 route = rtav->route ();
5029 if (current_mixer_strip && current_mixer_strip->route() == route) {
5031 TimeAxisView* next_tv;
5033 if (track_views.empty()) {
5035 } else if (i == track_views.end()) {
5036 next_tv = track_views.front();
5043 set_selected_mixer_strip (*next_tv);
5045 /* make the editor mixer strip go away setting the
5046 * button to inactive (which also unticks the menu option)
5049 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5055 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5057 if (apply_to_selection) {
5058 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5060 TrackSelection::iterator j = i;
5063 hide_track_in_display (*i, false);
5068 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5070 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5071 // this will hide the mixer strip
5072 set_selected_mixer_strip (*tv);
5075 _routes->hide_track_in_display (*tv);
5080 Editor::sync_track_view_list_and_routes ()
5082 track_views = TrackViewList (_routes->views ());
5084 _summary->set_dirty ();
5085 _group_tabs->set_dirty ();
5087 return false; // do not call again (until needed)
5091 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5093 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5098 /** Find a RouteTimeAxisView by the ID of its route */
5100 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5102 RouteTimeAxisView* v;
5104 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5105 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5106 if(v->route()->id() == id) {
5116 Editor::fit_route_group (RouteGroup *g)
5118 TrackViewList ts = axis_views_from_routes (g->route_list ());
5123 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5125 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5128 _session->cancel_audition ();
5132 if (_session->is_auditioning()) {
5133 _session->cancel_audition ();
5134 if (r == last_audition_region) {
5139 _session->audition_region (r);
5140 last_audition_region = r;
5145 Editor::hide_a_region (boost::shared_ptr<Region> r)
5147 r->set_hidden (true);
5151 Editor::show_a_region (boost::shared_ptr<Region> r)
5153 r->set_hidden (false);
5157 Editor::audition_region_from_region_list ()
5159 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5163 Editor::hide_region_from_region_list ()
5165 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5169 Editor::show_region_in_region_list ()
5171 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5175 Editor::step_edit_status_change (bool yn)
5178 start_step_editing ();
5180 stop_step_editing ();
5185 Editor::start_step_editing ()
5187 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5191 Editor::stop_step_editing ()
5193 step_edit_connection.disconnect ();
5197 Editor::check_step_edit ()
5199 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5200 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5202 mtv->check_step_edit ();
5206 return true; // do it again, till we stop
5210 Editor::scroll_press (Direction dir)
5212 ++_scroll_callbacks;
5214 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5215 /* delay the first auto-repeat */
5221 scroll_backward (1);
5229 scroll_up_one_track ();
5233 scroll_down_one_track ();
5237 /* do hacky auto-repeat */
5238 if (!_scroll_connection.connected ()) {
5240 _scroll_connection = Glib::signal_timeout().connect (
5241 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5244 _scroll_callbacks = 0;
5251 Editor::scroll_release ()
5253 _scroll_connection.disconnect ();
5256 /** Queue a change for the Editor viewport x origin to follow the playhead */
5258 Editor::reset_x_origin_to_follow_playhead ()
5260 framepos_t const frame = playhead_cursor->current_frame ();
5262 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5264 if (_session->transport_speed() < 0) {
5266 if (frame > (current_page_samples() / 2)) {
5267 center_screen (frame-(current_page_samples()/2));
5269 center_screen (current_page_samples()/2);
5276 if (frame < leftmost_frame) {
5278 if (_session->transport_rolling()) {
5279 /* rolling; end up with the playhead at the right of the page */
5280 l = frame - current_page_samples ();
5282 /* not rolling: end up with the playhead 1/4 of the way along the page */
5283 l = frame - current_page_samples() / 4;
5287 if (_session->transport_rolling()) {
5288 /* rolling: end up with the playhead on the left of the page */
5291 /* not rolling: end up with the playhead 3/4 of the way along the page */
5292 l = frame - 3 * current_page_samples() / 4;
5300 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5306 Editor::super_rapid_screen_update ()
5308 if (!_session || !_session->engine().running()) {
5312 /* METERING / MIXER STRIPS */
5314 /* update track meters, if required */
5315 if (is_mapped() && meters_running) {
5316 RouteTimeAxisView* rtv;
5317 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5318 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5319 rtv->fast_update ();
5324 /* and any current mixer strip */
5325 if (current_mixer_strip) {
5326 current_mixer_strip->fast_update ();
5329 /* PLAYHEAD AND VIEWPORT */
5331 framepos_t const frame = _session->audible_frame();
5333 /* There are a few reasons why we might not update the playhead / viewport stuff:
5335 * 1. we don't update things when there's a pending locate request, otherwise
5336 * when the editor requests a locate there is a chance that this method
5337 * will move the playhead before the locate request is processed, causing
5339 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5340 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5343 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5345 last_update_frame = frame;
5347 if (!_dragging_playhead) {
5348 playhead_cursor->set_position (frame);
5351 if (!_stationary_playhead) {
5353 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5354 /* We only do this if we aren't already
5355 handling a visual change (ie if
5356 pending_visual_change.being_handled is
5357 false) so that these requests don't stack
5358 up there are too many of them to handle in
5361 reset_x_origin_to_follow_playhead ();
5366 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5370 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5371 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5372 if (target <= 0.0) {
5375 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5376 target = (target * 0.15) + (current * 0.85);
5382 set_horizontal_position (current);
5391 Editor::session_going_away ()
5393 _have_idled = false;
5395 _session_connections.drop_connections ();
5397 super_rapid_screen_update_connection.disconnect ();
5399 selection->clear ();
5400 cut_buffer->clear ();
5402 clicked_regionview = 0;
5403 clicked_axisview = 0;
5404 clicked_routeview = 0;
5405 entered_regionview = 0;
5407 last_update_frame = 0;
5410 playhead_cursor->hide ();
5412 /* rip everything out of the list displays */
5416 _route_groups->clear ();
5418 /* do this first so that deleting a track doesn't reset cms to null
5419 and thus cause a leak.
5422 if (current_mixer_strip) {
5423 if (current_mixer_strip->get_parent() != 0) {
5424 global_hpacker.remove (*current_mixer_strip);
5426 delete current_mixer_strip;
5427 current_mixer_strip = 0;
5430 /* delete all trackviews */
5432 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5435 track_views.clear ();
5437 nudge_clock->set_session (0);
5439 editor_list_button.set_active(false);
5440 editor_list_button.set_sensitive(false);
5442 /* clear tempo/meter rulers */
5443 remove_metric_marks ();
5445 clear_marker_display ();
5447 stop_step_editing ();
5449 /* get rid of any existing editor mixer strip */
5451 WindowTitle title(Glib::get_application_name());
5452 title += _("Editor");
5454 set_title (title.get_string());
5456 SessionHandlePtr::session_going_away ();
5461 Editor::show_editor_list (bool yn)
5464 _the_notebook.show ();
5466 _the_notebook.hide ();
5471 Editor::change_region_layering_order (bool from_context_menu)
5473 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5475 if (!clicked_routeview) {
5476 if (layering_order_editor) {
5477 layering_order_editor->hide ();
5482 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5488 boost::shared_ptr<Playlist> pl = track->playlist();
5494 if (layering_order_editor == 0) {
5495 layering_order_editor = new RegionLayeringOrderEditor (*this);
5498 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5499 layering_order_editor->maybe_present ();
5503 Editor::update_region_layering_order_editor ()
5505 if (layering_order_editor && layering_order_editor->is_visible ()) {
5506 change_region_layering_order (true);
5511 Editor::setup_fade_images ()
5513 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5514 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5515 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5516 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5517 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5519 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5520 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5521 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5522 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5523 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5525 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5526 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5527 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5528 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5529 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5531 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5532 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5533 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5534 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5535 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5539 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5541 Editor::action_menu_item (std::string const & name)
5543 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5546 return *manage (a->create_menu_item ());
5550 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5552 EventBox* b = manage (new EventBox);
5553 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5554 Label* l = manage (new Label (name));
5558 _the_notebook.append_page (widget, *b);
5562 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5564 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5565 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5568 if (ev->type == GDK_2BUTTON_PRESS) {
5570 /* double-click on a notebook tab shrinks or expands the notebook */
5572 if (_notebook_shrunk) {
5573 if (pre_notebook_shrink_pane_width) {
5574 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5576 _notebook_shrunk = false;
5578 pre_notebook_shrink_pane_width = edit_pane.get_position();
5580 /* this expands the LHS of the edit pane to cover the notebook
5581 PAGE but leaves the tabs visible.
5583 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5584 _notebook_shrunk = true;
5592 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5594 using namespace Menu_Helpers;
5596 MenuList& items = _control_point_context_menu.items ();
5599 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5600 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5601 if (!can_remove_control_point (item)) {
5602 items.back().set_sensitive (false);
5605 _control_point_context_menu.popup (event->button.button, event->button.time);
5609 Editor::zoom_vertical_modifier_released()
5611 _stepping_axis_view = 0;
5615 Editor::ui_parameter_changed (string parameter)
5617 if (parameter == "icon-set") {
5618 while (!_cursor_stack.empty()) {
5619 _cursor_stack.pop();
5621 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5622 } else if (parameter == "draggable-playhead") {
5623 if (_verbose_cursor) {
5624 playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());