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"),
222 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
225 pane_size_watcher (Paned* pane)
227 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
231 Quartz: impossible to access
233 so stop that by preventing it from ever getting too narrow. 35
234 pixels is basically a rough guess at the tab width.
239 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
241 gint pos = pane->get_position ();
243 if (pos > max_width_of_lhs) {
244 pane->set_position (max_width_of_lhs);
249 : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
251 /* time display buttons */
252 , minsec_label (_("Mins:Secs"))
253 , bbt_label (_("Bars:Beats"))
254 , timecode_label (_("Timecode"))
255 , samples_label (_("Samples"))
256 , tempo_label (_("Tempo"))
257 , meter_label (_("Meter"))
258 , mark_label (_("Location Markers"))
259 , range_mark_label (_("Range Markers"))
260 , transport_mark_label (_("Loop/Punch Ranges"))
261 , cd_mark_label (_("CD Markers"))
262 , videotl_label (_("Video Timeline"))
263 , edit_packer (4, 4, true)
265 /* the values here don't matter: layout widgets
266 reset them as needed.
269 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
270 , horizontal_adjustment (0.0, 0.0, 1e16)
271 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
273 , controls_layout (unused_adjustment, vertical_adjustment)
275 /* tool bar related */
277 , toolbar_selection_clock_table (2,3)
278 , _mouse_mode_tearoff (0)
279 , automation_mode_button (_("mode"))
283 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
287 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
288 , meters_running(false)
289 , _pending_locate_request (false)
290 , _pending_initial_locate (false)
291 , _last_cut_copy_source_track (0)
293 , _region_selection_change_updates_region_list (true)
294 , _following_mixer_selection (false)
295 , _control_point_toggled_on_press (false)
296 , _stepping_axis_view (0)
300 /* we are a singleton */
302 PublicEditor::_instance = this;
306 selection = new Selection (this);
307 cut_buffer = new Selection (this);
309 clicked_regionview = 0;
310 clicked_axisview = 0;
311 clicked_routeview = 0;
312 clicked_control_point = 0;
313 last_update_frame = 0;
314 pre_press_cursor = 0;
315 _drags = new DragManager (this);
318 current_mixer_strip = 0;
321 snap_type_strings = I18N (_snap_type_strings);
322 snap_mode_strings = I18N (_snap_mode_strings);
323 zoom_focus_strings = I18N (_zoom_focus_strings);
324 edit_mode_strings = I18N (_edit_mode_strings);
325 edit_point_strings = I18N (_edit_point_strings);
326 #ifdef USE_RUBBERBAND
327 rb_opt_strings = I18N (_rb_opt_strings);
331 build_edit_mode_menu();
332 build_zoom_focus_menu();
333 build_track_count_menu();
334 build_snap_mode_menu();
335 build_snap_type_menu();
336 build_edit_point_menu();
338 snap_threshold = 5.0;
339 bbt_beat_subdivision = 4;
340 _visible_canvas_width = 0;
341 _visible_canvas_height = 0;
342 autoscroll_horizontal_allowed = false;
343 autoscroll_vertical_allowed = false;
348 current_interthread_info = 0;
349 _show_measures = true;
351 show_gain_after_trim = false;
353 have_pending_keyboard_selection = false;
354 _follow_playhead = true;
355 _stationary_playhead = false;
356 editor_ruler_menu = 0;
357 no_ruler_shown_update = false;
359 range_marker_menu = 0;
360 marker_menu_item = 0;
361 tempo_or_meter_marker_menu = 0;
362 transport_marker_menu = 0;
363 new_transport_marker_menu = 0;
364 editor_mixer_strip_width = Wide;
365 show_editor_mixer_when_tracks_arrive = false;
366 region_edit_menu_split_multichannel_item = 0;
367 region_edit_menu_split_item = 0;
370 current_stepping_trackview = 0;
372 entered_regionview = 0;
374 clear_entered_track = false;
377 button_release_can_deselect = true;
378 _dragging_playhead = false;
379 _dragging_edit_point = false;
380 select_new_marker = false;
382 layering_order_editor = 0;
383 no_save_visual = false;
385 within_track_canvas = false;
387 scrubbing_direction = 0;
391 location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
392 location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
393 location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
394 location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
395 location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
397 zoom_focus = ZoomFocusLeft;
398 _edit_point = EditAtMouse;
399 _internal_editing = false;
400 current_canvas_cursor = 0;
401 _visible_track_count = -1;
403 samples_per_pixel = 2048; /* too early to use reset_zoom () */
405 _scroll_callbacks = 0;
407 bbt_label.set_name ("EditorRulerLabel");
408 bbt_label.set_size_request (-1, (int)timebar_height);
409 bbt_label.set_alignment (1.0, 0.5);
410 bbt_label.set_padding (5,0);
412 bbt_label.set_no_show_all();
413 minsec_label.set_name ("EditorRulerLabel");
414 minsec_label.set_size_request (-1, (int)timebar_height);
415 minsec_label.set_alignment (1.0, 0.5);
416 minsec_label.set_padding (5,0);
417 minsec_label.hide ();
418 minsec_label.set_no_show_all();
419 timecode_label.set_name ("EditorRulerLabel");
420 timecode_label.set_size_request (-1, (int)timebar_height);
421 timecode_label.set_alignment (1.0, 0.5);
422 timecode_label.set_padding (5,0);
423 timecode_label.hide ();
424 timecode_label.set_no_show_all();
425 samples_label.set_name ("EditorRulerLabel");
426 samples_label.set_size_request (-1, (int)timebar_height);
427 samples_label.set_alignment (1.0, 0.5);
428 samples_label.set_padding (5,0);
429 samples_label.hide ();
430 samples_label.set_no_show_all();
432 tempo_label.set_name ("EditorRulerLabel");
433 tempo_label.set_size_request (-1, (int)timebar_height);
434 tempo_label.set_alignment (1.0, 0.5);
435 tempo_label.set_padding (5,0);
437 tempo_label.set_no_show_all();
439 meter_label.set_name ("EditorRulerLabel");
440 meter_label.set_size_request (-1, (int)timebar_height);
441 meter_label.set_alignment (1.0, 0.5);
442 meter_label.set_padding (5,0);
444 meter_label.set_no_show_all();
446 if (Profile->get_trx()) {
447 mark_label.set_text (_("Markers"));
449 mark_label.set_name ("EditorRulerLabel");
450 mark_label.set_size_request (-1, (int)timebar_height);
451 mark_label.set_alignment (1.0, 0.5);
452 mark_label.set_padding (5,0);
454 mark_label.set_no_show_all();
456 cd_mark_label.set_name ("EditorRulerLabel");
457 cd_mark_label.set_size_request (-1, (int)timebar_height);
458 cd_mark_label.set_alignment (1.0, 0.5);
459 cd_mark_label.set_padding (5,0);
460 cd_mark_label.hide();
461 cd_mark_label.set_no_show_all();
463 videotl_bar_height = 4;
464 videotl_label.set_name ("EditorRulerLabel");
465 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
466 videotl_label.set_alignment (1.0, 0.5);
467 videotl_label.set_padding (5,0);
468 videotl_label.hide();
469 videotl_label.set_no_show_all();
471 range_mark_label.set_name ("EditorRulerLabel");
472 range_mark_label.set_size_request (-1, (int)timebar_height);
473 range_mark_label.set_alignment (1.0, 0.5);
474 range_mark_label.set_padding (5,0);
475 range_mark_label.hide();
476 range_mark_label.set_no_show_all();
478 transport_mark_label.set_name ("EditorRulerLabel");
479 transport_mark_label.set_size_request (-1, (int)timebar_height);
480 transport_mark_label.set_alignment (1.0, 0.5);
481 transport_mark_label.set_padding (5,0);
482 transport_mark_label.hide();
483 transport_mark_label.set_no_show_all();
485 initialize_canvas ();
487 CairoWidget::set_focus_handler (sigc::mem_fun (*this, &Editor::reset_focus));
489 _summary = new EditorSummary (this);
491 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
492 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
494 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
496 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
497 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
499 edit_controls_vbox.set_spacing (0);
500 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
501 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
503 HBox* h = manage (new HBox);
504 _group_tabs = new EditorGroupTabs (this);
505 if (!ARDOUR::Profile->get_trx()) {
506 h->pack_start (*_group_tabs, PACK_SHRINK);
508 h->pack_start (edit_controls_vbox);
509 controls_layout.add (*h);
511 controls_layout.set_name ("EditControlsBase");
512 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
513 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
514 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
516 _cursors = new MouseCursors;
517 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
518 cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
520 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
522 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
523 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
524 pad_line_1->set_outline_color (0xFF0000FF);
530 edit_packer.set_col_spacings (0);
531 edit_packer.set_row_spacings (0);
532 edit_packer.set_homogeneous (false);
533 edit_packer.set_border_width (0);
534 edit_packer.set_name ("EditorWindow");
536 time_bars_event_box.add (time_bars_vbox);
537 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
538 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
540 /* labels for the time bars */
541 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
543 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
545 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
547 bottom_hbox.set_border_width (2);
548 bottom_hbox.set_spacing (3);
550 _route_groups = new EditorRouteGroups (this);
551 _routes = new EditorRoutes (this);
552 _regions = new EditorRegions (this);
553 _snapshots = new EditorSnapshots (this);
554 _locations = new EditorLocations (this);
556 /* these are static location signals */
558 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
559 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
560 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
562 add_notebook_page (_("Regions"), _regions->widget ());
563 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
564 add_notebook_page (_("Snapshots"), _snapshots->widget ());
565 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
566 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
568 _the_notebook.set_show_tabs (true);
569 _the_notebook.set_scrollable (true);
570 _the_notebook.popup_disable ();
571 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
572 _the_notebook.show_all ();
574 _notebook_shrunk = false;
576 editor_summary_pane.pack1(edit_packer);
578 Button* summary_arrows_left_left = manage (new Button);
579 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
580 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
581 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
583 Button* summary_arrows_left_right = manage (new Button);
584 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
585 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
586 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
588 VBox* summary_arrows_left = manage (new VBox);
589 summary_arrows_left->pack_start (*summary_arrows_left_left);
590 summary_arrows_left->pack_start (*summary_arrows_left_right);
592 Button* summary_arrows_right_up = manage (new Button);
593 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
594 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
595 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
597 Button* summary_arrows_right_down = manage (new Button);
598 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
599 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
600 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
602 VBox* summary_arrows_right = manage (new VBox);
603 summary_arrows_right->pack_start (*summary_arrows_right_up);
604 summary_arrows_right->pack_start (*summary_arrows_right_down);
606 Frame* summary_frame = manage (new Frame);
607 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
609 summary_frame->add (*_summary);
610 summary_frame->show ();
612 _summary_hbox.pack_start (*summary_arrows_left, false, false);
613 _summary_hbox.pack_start (*summary_frame, true, true);
614 _summary_hbox.pack_start (*summary_arrows_right, false, false);
616 if (!ARDOUR::Profile->get_trx()) {
617 editor_summary_pane.pack2 (_summary_hbox);
620 edit_pane.pack1 (editor_summary_pane, true, true);
621 if (!ARDOUR::Profile->get_trx()) {
622 edit_pane.pack2 (_the_notebook, false, true);
625 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
627 /* XXX: editor_summary_pane might need similar to the edit_pane */
629 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
631 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
632 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
634 top_hbox.pack_start (toolbar_frame);
636 HBox *hbox = manage (new HBox);
637 hbox->pack_start (edit_pane, true, true);
639 global_vpacker.pack_start (top_hbox, false, false);
640 global_vpacker.pack_start (*hbox, true, true);
642 global_hpacker.pack_start (global_vpacker, true, true);
644 set_name ("EditorWindow");
645 add_accel_group (ActionManager::ui_manager->get_accel_group());
647 status_bar_hpacker.show ();
649 vpacker.pack_end (status_bar_hpacker, false, false);
650 vpacker.pack_end (global_hpacker, true, true);
652 /* register actions now so that set_state() can find them and set toggles/checks etc */
655 /* when we start using our own keybinding system for the editor, this
656 * will be uncommented
662 set_zoom_focus (zoom_focus);
663 set_visible_track_count (_visible_track_count);
664 _snap_type = SnapToBeat;
665 set_snap_to (_snap_type);
666 _snap_mode = SnapOff;
667 set_snap_mode (_snap_mode);
668 set_mouse_mode (MouseObject, true);
669 pre_internal_mouse_mode = MouseObject;
670 pre_internal_snap_type = _snap_type;
671 pre_internal_snap_mode = _snap_mode;
672 internal_snap_type = _snap_type;
673 internal_snap_mode = _snap_mode;
674 set_edit_point_preference (EditAtMouse, true);
676 _playlist_selector = new PlaylistSelector();
677 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
679 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
683 nudge_forward_button.set_name ("nudge button");
684 nudge_forward_button.set_image(::get_icon("nudge_right"));
686 nudge_backward_button.set_name ("nudge button");
687 nudge_backward_button.set_image(::get_icon("nudge_left"));
689 fade_context_menu.set_name ("ArdourContextMenu");
691 /* icons, titles, WM stuff */
693 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
694 Glib::RefPtr<Gdk::Pixbuf> icon;
696 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
697 window_icons.push_back (icon);
699 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
700 window_icons.push_back (icon);
702 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
703 window_icons.push_back (icon);
705 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
706 window_icons.push_back (icon);
708 if (!window_icons.empty()) {
709 // set_icon_list (window_icons);
710 set_default_icon_list (window_icons);
713 WindowTitle title(Glib::get_application_name());
714 title += _("Editor");
715 set_title (title.get_string());
716 set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
719 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
721 signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
722 signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
724 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
726 /* allow external control surfaces/protocols to do various things */
728 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
729 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
730 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
731 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
732 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
733 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
734 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
735 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
736 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
737 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
738 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
739 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
740 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
741 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
743 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
744 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
745 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
746 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
747 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
749 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
751 /* problematic: has to return a value and thus cannot be x-thread */
753 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
755 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
756 ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
758 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
760 _ignore_region_action = false;
761 _last_region_menu_was_main = false;
762 _popup_region_menu_item = 0;
764 _ignore_follow_edits = false;
766 _show_marker_lines = false;
768 /* Button bindings */
770 button_bindings = new Bindings;
772 XMLNode* node = button_settings();
774 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
775 button_bindings->load (**i);
781 /* grab current parameter state */
782 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
783 ARDOUR_UI::config()->map_parameters (pc);
785 setup_fade_images ();
792 delete button_bindings;
794 delete _route_groups;
795 delete _track_canvas_viewport;
801 Editor::button_settings () const
803 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
804 XMLNode* node = find_named_node (*settings, X_("Buttons"));
807 node = new XMLNode (X_("Buttons"));
814 Editor::add_toplevel_menu (Container& cont)
816 vpacker.pack_start (cont, false, false);
821 Editor::add_transport_frame (Container& cont)
823 if(ARDOUR::Profile->get_mixbus()) {
824 global_vpacker.pack_start (cont, false, false);
825 global_vpacker.reorder_child (cont, 0);
828 vpacker.pack_start (cont, false, false);
833 Editor::get_smart_mode () const
835 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
839 Editor::catch_vanishing_regionview (RegionView *rv)
841 /* note: the selection will take care of the vanishing
842 audioregionview by itself.
845 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
849 if (clicked_regionview == rv) {
850 clicked_regionview = 0;
853 if (entered_regionview == rv) {
854 set_entered_regionview (0);
857 if (!_all_region_actions_sensitized) {
858 sensitize_all_region_actions (true);
863 Editor::set_entered_regionview (RegionView* rv)
865 if (rv == entered_regionview) {
869 if (entered_regionview) {
870 entered_regionview->exited ();
873 entered_regionview = rv;
875 if (entered_regionview != 0) {
876 entered_regionview->entered (internal_editing ());
879 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
880 /* This RegionView entry might have changed what region actions
881 are allowed, so sensitize them all in case a key is pressed.
883 sensitize_all_region_actions (true);
888 Editor::set_entered_track (TimeAxisView* tav)
891 entered_track->exited ();
897 entered_track->entered ();
902 Editor::show_window ()
904 if (!is_visible ()) {
908 /* XXX: this is a bit unfortunate; it would probably
909 be nicer if we could just call show () above rather
910 than needing the show_all ()
913 /* re-hide stuff if necessary */
914 editor_list_button_toggled ();
915 parameter_changed ("show-summary");
916 parameter_changed ("show-group-tabs");
917 parameter_changed ("show-zoom-tools");
919 /* now reset all audio_time_axis heights, because widgets might need
925 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
926 tv = (static_cast<TimeAxisView*>(*i));
930 if (current_mixer_strip) {
931 current_mixer_strip->hide_things ();
932 current_mixer_strip->parameter_changed ("mixer-element-visibility");
940 Editor::instant_save ()
942 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
947 _session->add_instant_xml(get_state());
949 Config->add_instant_xml(get_state());
954 Editor::control_vertical_zoom_in_all ()
956 tav_zoom_smooth (false, true);
960 Editor::control_vertical_zoom_out_all ()
962 tav_zoom_smooth (true, true);
966 Editor::control_vertical_zoom_in_selected ()
968 tav_zoom_smooth (false, false);
972 Editor::control_vertical_zoom_out_selected ()
974 tav_zoom_smooth (true, false);
978 Editor::control_view (uint32_t view)
980 goto_visual_state (view);
984 Editor::control_unselect ()
986 selection->clear_tracks ();
990 Editor::control_select (uint32_t rid, Selection::Operation op)
992 /* handles the (static) signal from the ControlProtocol class that
993 * requests setting the selected track to a given RID
1000 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
1006 TimeAxisView* tav = axis_view_from_route (r);
1010 case Selection::Add:
1011 selection->add (tav);
1013 case Selection::Toggle:
1014 selection->toggle (tav);
1016 case Selection::Extend:
1018 case Selection::Set:
1019 selection->set (tav);
1023 selection->clear_tracks ();
1028 Editor::control_step_tracks_up ()
1030 scroll_tracks_up_line ();
1034 Editor::control_step_tracks_down ()
1036 scroll_tracks_down_line ();
1040 Editor::control_scroll (float fraction)
1042 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1048 double step = fraction * current_page_samples();
1051 _control_scroll_target is an optional<T>
1053 it acts like a pointer to an framepos_t, with
1054 a operator conversion to boolean to check
1055 that it has a value could possibly use
1056 playhead_cursor->current_frame to store the
1057 value and a boolean in the class to know
1058 when it's out of date
1061 if (!_control_scroll_target) {
1062 _control_scroll_target = _session->transport_frame();
1063 _dragging_playhead = true;
1066 if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
1067 *_control_scroll_target = 0;
1068 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1069 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1071 *_control_scroll_target += (framepos_t) floor (step);
1074 /* move visuals, we'll catch up with it later */
1076 playhead_cursor->set_position (*_control_scroll_target);
1077 UpdateAllTransportClocks (*_control_scroll_target);
1079 if (*_control_scroll_target > (current_page_samples() / 2)) {
1080 /* try to center PH in window */
1081 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1087 Now we do a timeout to actually bring the session to the right place
1088 according to the playhead. This is to avoid reading disk buffers on every
1089 call to control_scroll, which is driven by ScrollTimeline and therefore
1090 probably by a control surface wheel which can generate lots of events.
1092 /* cancel the existing timeout */
1094 control_scroll_connection.disconnect ();
1096 /* add the next timeout */
1098 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1102 Editor::deferred_control_scroll (framepos_t /*target*/)
1104 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1105 // reset for next stream
1106 _control_scroll_target = boost::none;
1107 _dragging_playhead = false;
1112 Editor::access_action (std::string action_group, std::string action_item)
1118 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1121 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1129 Editor::on_realize ()
1131 Window::on_realize ();
1134 if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1135 start_lock_event_timing ();
1138 signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
1142 Editor::start_lock_event_timing ()
1144 /* check if we should lock the GUI every 30 seconds */
1146 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1150 Editor::generic_event_handler (GdkEvent* ev)
1153 case GDK_BUTTON_PRESS:
1154 case GDK_BUTTON_RELEASE:
1155 case GDK_MOTION_NOTIFY:
1157 case GDK_KEY_RELEASE:
1158 gettimeofday (&last_event_time, 0);
1161 case GDK_LEAVE_NOTIFY:
1162 switch (ev->crossing.detail) {
1163 case GDK_NOTIFY_UNKNOWN:
1164 case GDK_NOTIFY_INFERIOR:
1165 case GDK_NOTIFY_ANCESTOR:
1167 case GDK_NOTIFY_VIRTUAL:
1168 case GDK_NOTIFY_NONLINEAR:
1169 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1170 /* leaving window, so reset focus, thus ending any and
1171 all text entry operations.
1186 Editor::lock_timeout_callback ()
1188 struct timeval now, delta;
1190 gettimeofday (&now, 0);
1192 timersub (&now, &last_event_time, &delta);
1194 if (delta.tv_sec > (time_t) ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1196 /* don't call again. Returning false will effectively
1197 disconnect us from the timer callback.
1199 unlock() will call start_lock_event_timing() to get things
1209 Editor::map_position_change (framepos_t frame)
1211 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1213 if (_session == 0) {
1217 if (_follow_playhead) {
1218 center_screen (frame);
1221 playhead_cursor->set_position (frame);
1225 Editor::center_screen (framepos_t frame)
1227 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1229 /* if we're off the page, then scroll.
1232 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1233 center_screen_internal (frame, page);
1238 Editor::center_screen_internal (framepos_t frame, float page)
1243 frame -= (framepos_t) page;
1248 reset_x_origin (frame);
1253 Editor::update_title ()
1255 ENSURE_GUI_THREAD (*this, &Editor::update_title)
1258 bool dirty = _session->dirty();
1260 string session_name;
1262 if (_session->snap_name() != _session->name()) {
1263 session_name = _session->snap_name();
1265 session_name = _session->name();
1269 session_name = "*" + session_name;
1272 WindowTitle title(session_name);
1273 title += Glib::get_application_name();
1274 set_title (title.get_string());
1276 /* ::session_going_away() will have taken care of it */
1281 Editor::set_session (Session *t)
1283 SessionHandlePtr::set_session (t);
1289 _playlist_selector->set_session (_session);
1290 nudge_clock->set_session (_session);
1291 _summary->set_session (_session);
1292 _group_tabs->set_session (_session);
1293 _route_groups->set_session (_session);
1294 _regions->set_session (_session);
1295 _snapshots->set_session (_session);
1296 _routes->set_session (_session);
1297 _locations->set_session (_session);
1299 if (rhythm_ferret) {
1300 rhythm_ferret->set_session (_session);
1303 if (analysis_window) {
1304 analysis_window->set_session (_session);
1308 sfbrowser->set_session (_session);
1311 compute_fixed_ruler_scale ();
1313 /* Make sure we have auto loop and auto punch ranges */
1315 Location* loc = _session->locations()->auto_loop_location();
1317 loc->set_name (_("Loop"));
1320 loc = _session->locations()->auto_punch_location();
1323 loc->set_name (_("Punch"));
1326 refresh_location_display ();
1328 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1329 the selected Marker; this needs the LocationMarker list to be available.
1331 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1332 set_state (*node, Stateful::loading_state_version);
1334 /* catch up with the playhead */
1336 _session->request_locate (playhead_cursor->current_frame ());
1337 _pending_initial_locate = true;
1341 /* These signals can all be emitted by a non-GUI thread. Therefore the
1342 handlers for them must not attempt to directly interact with the GUI,
1343 but use PBD::Signal<T>::connect() which accepts an event loop
1344 ("context") where the handler will be asked to run.
1347 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1348 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1349 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1350 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1351 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1352 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1353 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1354 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1355 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1356 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1357 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1358 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1359 _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1360 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1362 playhead_cursor->show ();
1364 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1365 Config->map_parameters (pc);
1366 _session->config.map_parameters (pc);
1368 restore_ruler_visibility ();
1369 //tempo_map_changed (PropertyChange (0));
1370 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1372 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1373 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1376 super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1377 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1380 switch (_snap_type) {
1381 case SnapToRegionStart:
1382 case SnapToRegionEnd:
1383 case SnapToRegionSync:
1384 case SnapToRegionBoundary:
1385 build_region_boundary_cache ();
1392 /* register for undo history */
1393 _session->register_with_memento_command_factory(id(), this);
1395 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1397 start_updating_meters ();
1401 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1403 if (a->get_name() == "RegionMenu") {
1404 /* When the main menu's region menu is opened, we setup the actions so that they look right
1405 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1406 so we resensitize all region actions when the entered regionview or the region selection
1407 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1408 happens after the region context menu is opened. So we set a flag here, too.
1412 sensitize_the_right_region_actions ();
1413 _last_region_menu_was_main = true;
1418 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1420 using namespace Menu_Helpers;
1422 void (Editor::*emf)(FadeShape);
1423 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1426 images = &_xfade_in_images;
1427 emf = &Editor::set_fade_in_shape;
1429 images = &_xfade_out_images;
1430 emf = &Editor::set_fade_out_shape;
1435 _("Linear (for highly correlated material)"),
1436 *(*images)[FadeLinear],
1437 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1441 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1445 _("Constant power"),
1446 *(*images)[FadeConstantPower],
1447 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1450 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1455 *(*images)[FadeSymmetric],
1456 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1460 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1465 *(*images)[FadeSlow],
1466 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1469 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1474 *(*images)[FadeFast],
1475 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1478 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1481 /** Pop up a context menu for when the user clicks on a start crossfade */
1483 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1485 using namespace Menu_Helpers;
1486 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1489 MenuList& items (xfade_in_context_menu.items());
1492 if (arv->audio_region()->fade_in_active()) {
1493 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1495 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1498 items.push_back (SeparatorElem());
1499 fill_xfade_menu (items, true);
1501 xfade_in_context_menu.popup (button, time);
1504 /** Pop up a context menu for when the user clicks on an end crossfade */
1506 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1508 using namespace Menu_Helpers;
1509 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1512 MenuList& items (xfade_out_context_menu.items());
1515 if (arv->audio_region()->fade_out_active()) {
1516 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1518 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1521 items.push_back (SeparatorElem());
1522 fill_xfade_menu (items, false);
1524 xfade_out_context_menu.popup (button, time);
1528 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1530 using namespace Menu_Helpers;
1531 Menu* (Editor::*build_menu_function)();
1534 switch (item_type) {
1536 case RegionViewName:
1537 case RegionViewNameHighlight:
1538 case LeftFrameHandle:
1539 case RightFrameHandle:
1540 if (with_selection) {
1541 build_menu_function = &Editor::build_track_selection_context_menu;
1543 build_menu_function = &Editor::build_track_region_context_menu;
1548 if (with_selection) {
1549 build_menu_function = &Editor::build_track_selection_context_menu;
1551 build_menu_function = &Editor::build_track_context_menu;
1556 if (clicked_routeview->track()) {
1557 build_menu_function = &Editor::build_track_context_menu;
1559 build_menu_function = &Editor::build_track_bus_context_menu;
1564 /* probably shouldn't happen but if it does, we don't care */
1568 menu = (this->*build_menu_function)();
1569 menu->set_name ("ArdourContextMenu");
1571 /* now handle specific situations */
1573 switch (item_type) {
1575 case RegionViewName:
1576 case RegionViewNameHighlight:
1577 case LeftFrameHandle:
1578 case RightFrameHandle:
1579 if (!with_selection) {
1580 if (region_edit_menu_split_item) {
1581 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1582 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1584 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1587 if (region_edit_menu_split_multichannel_item) {
1588 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1589 region_edit_menu_split_multichannel_item->set_sensitive (true);
1591 region_edit_menu_split_multichannel_item->set_sensitive (false);
1604 /* probably shouldn't happen but if it does, we don't care */
1608 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1610 /* Bounce to disk */
1612 using namespace Menu_Helpers;
1613 MenuList& edit_items = menu->items();
1615 edit_items.push_back (SeparatorElem());
1617 switch (clicked_routeview->audio_track()->freeze_state()) {
1618 case AudioTrack::NoFreeze:
1619 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1622 case AudioTrack::Frozen:
1623 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1626 case AudioTrack::UnFrozen:
1627 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1633 if (item_type == StreamItem && clicked_routeview) {
1634 clicked_routeview->build_underlay_menu(menu);
1637 /* When the region menu is opened, we setup the actions so that they look right
1640 sensitize_the_right_region_actions ();
1641 _last_region_menu_was_main = false;
1643 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1644 menu->popup (button, time);
1648 Editor::build_track_context_menu ()
1650 using namespace Menu_Helpers;
1652 MenuList& edit_items = track_context_menu.items();
1655 add_dstream_context_items (edit_items);
1656 return &track_context_menu;
1660 Editor::build_track_bus_context_menu ()
1662 using namespace Menu_Helpers;
1664 MenuList& edit_items = track_context_menu.items();
1667 add_bus_context_items (edit_items);
1668 return &track_context_menu;
1672 Editor::build_track_region_context_menu ()
1674 using namespace Menu_Helpers;
1675 MenuList& edit_items = track_region_context_menu.items();
1678 /* we've just cleared the track region context menu, so the menu that these
1679 two items were on will have disappeared; stop them dangling.
1681 region_edit_menu_split_item = 0;
1682 region_edit_menu_split_multichannel_item = 0;
1684 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1687 boost::shared_ptr<Track> tr;
1688 boost::shared_ptr<Playlist> pl;
1690 if ((tr = rtv->track())) {
1691 add_region_context_items (edit_items, tr);
1695 add_dstream_context_items (edit_items);
1697 return &track_region_context_menu;
1701 Editor::analyze_region_selection ()
1703 if (analysis_window == 0) {
1704 analysis_window = new AnalysisWindow();
1707 analysis_window->set_session(_session);
1709 analysis_window->show_all();
1712 analysis_window->set_regionmode();
1713 analysis_window->analyze();
1715 analysis_window->present();
1719 Editor::analyze_range_selection()
1721 if (analysis_window == 0) {
1722 analysis_window = new AnalysisWindow();
1725 analysis_window->set_session(_session);
1727 analysis_window->show_all();
1730 analysis_window->set_rangemode();
1731 analysis_window->analyze();
1733 analysis_window->present();
1737 Editor::build_track_selection_context_menu ()
1739 using namespace Menu_Helpers;
1740 MenuList& edit_items = track_selection_context_menu.items();
1741 edit_items.clear ();
1743 add_selection_context_items (edit_items);
1744 // edit_items.push_back (SeparatorElem());
1745 // add_dstream_context_items (edit_items);
1747 return &track_selection_context_menu;
1751 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1753 using namespace Menu_Helpers;
1755 /* OK, stick the region submenu at the top of the list, and then add
1759 RegionSelection rs = get_regions_from_selection_and_entered ();
1761 string::size_type pos = 0;
1762 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1764 /* we have to hack up the region name because "_" has a special
1765 meaning for menu titles.
1768 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1769 menu_item_name.replace (pos, 1, "__");
1773 if (_popup_region_menu_item == 0) {
1774 _popup_region_menu_item = new MenuItem (menu_item_name);
1775 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1776 _popup_region_menu_item->show ();
1778 _popup_region_menu_item->set_label (menu_item_name);
1781 const framepos_t position = get_preferred_edit_position (false, true);
1783 edit_items.push_back (*_popup_region_menu_item);
1784 if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1785 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1787 edit_items.push_back (SeparatorElem());
1790 /** Add context menu items relevant to selection ranges.
1791 * @param edit_items List to add the items to.
1794 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1796 using namespace Menu_Helpers;
1798 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1799 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1801 edit_items.push_back (SeparatorElem());
1802 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
1804 edit_items.push_back (SeparatorElem());
1805 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1807 edit_items.push_back (SeparatorElem());
1809 edit_items.push_back (
1811 _("Move Range Start to Previous Region Boundary"),
1812 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1816 edit_items.push_back (
1818 _("Move Range Start to Next Region Boundary"),
1819 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1823 edit_items.push_back (
1825 _("Move Range End to Previous Region Boundary"),
1826 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1830 edit_items.push_back (
1832 _("Move Range End to Next Region Boundary"),
1833 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1837 edit_items.push_back (SeparatorElem());
1838 edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1839 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1841 edit_items.push_back (SeparatorElem());
1842 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1844 edit_items.push_back (SeparatorElem());
1845 edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1846 edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1848 edit_items.push_back (SeparatorElem());
1849 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1851 edit_items.push_back (SeparatorElem());
1852 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1853 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1854 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1856 edit_items.push_back (SeparatorElem());
1857 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1858 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1859 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1860 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1861 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1862 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1863 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1869 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1871 using namespace Menu_Helpers;
1875 Menu *play_menu = manage (new Menu);
1876 MenuList& play_items = play_menu->items();
1877 play_menu->set_name ("ArdourContextMenu");
1879 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1880 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1881 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1882 play_items.push_back (SeparatorElem());
1883 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1885 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1889 Menu *select_menu = manage (new Menu);
1890 MenuList& select_items = select_menu->items();
1891 select_menu->set_name ("ArdourContextMenu");
1893 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1894 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1895 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1896 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1897 select_items.push_back (SeparatorElem());
1898 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1899 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1900 select_items.push_back (SeparatorElem());
1901 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1902 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1903 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1904 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1905 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1906 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1907 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1909 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1913 Menu *cutnpaste_menu = manage (new Menu);
1914 MenuList& cutnpaste_items = cutnpaste_menu->items();
1915 cutnpaste_menu->set_name ("ArdourContextMenu");
1917 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1918 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1919 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1921 cutnpaste_items.push_back (SeparatorElem());
1923 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1924 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1926 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1928 /* Adding new material */
1930 edit_items.push_back (SeparatorElem());
1931 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1932 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1936 Menu *nudge_menu = manage (new Menu());
1937 MenuList& nudge_items = nudge_menu->items();
1938 nudge_menu->set_name ("ArdourContextMenu");
1940 edit_items.push_back (SeparatorElem());
1941 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1942 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1943 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1944 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1946 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1950 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1952 using namespace Menu_Helpers;
1956 Menu *play_menu = manage (new Menu);
1957 MenuList& play_items = play_menu->items();
1958 play_menu->set_name ("ArdourContextMenu");
1960 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1961 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1962 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1966 Menu *select_menu = manage (new Menu);
1967 MenuList& select_items = select_menu->items();
1968 select_menu->set_name ("ArdourContextMenu");
1970 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1971 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
1972 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1973 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1974 select_items.push_back (SeparatorElem());
1975 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1976 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1977 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1978 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1980 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1984 Menu *cutnpaste_menu = manage (new Menu);
1985 MenuList& cutnpaste_items = cutnpaste_menu->items();
1986 cutnpaste_menu->set_name ("ArdourContextMenu");
1988 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1989 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1990 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1992 Menu *nudge_menu = manage (new Menu());
1993 MenuList& nudge_items = nudge_menu->items();
1994 nudge_menu->set_name ("ArdourContextMenu");
1996 edit_items.push_back (SeparatorElem());
1997 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1998 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1999 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2000 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2002 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2006 Editor::snap_type() const
2012 Editor::snap_mode() const
2018 Editor::set_snap_to (SnapType st)
2020 unsigned int snap_ind = (unsigned int)st;
2024 if (snap_ind > snap_type_strings.size() - 1) {
2026 _snap_type = (SnapType)snap_ind;
2029 string str = snap_type_strings[snap_ind];
2031 if (str != snap_type_selector.get_text()) {
2032 snap_type_selector.set_text (str);
2037 switch (_snap_type) {
2038 case SnapToBeatDiv128:
2039 case SnapToBeatDiv64:
2040 case SnapToBeatDiv32:
2041 case SnapToBeatDiv28:
2042 case SnapToBeatDiv24:
2043 case SnapToBeatDiv20:
2044 case SnapToBeatDiv16:
2045 case SnapToBeatDiv14:
2046 case SnapToBeatDiv12:
2047 case SnapToBeatDiv10:
2048 case SnapToBeatDiv8:
2049 case SnapToBeatDiv7:
2050 case SnapToBeatDiv6:
2051 case SnapToBeatDiv5:
2052 case SnapToBeatDiv4:
2053 case SnapToBeatDiv3:
2054 case SnapToBeatDiv2: {
2055 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2056 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2058 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2059 current_bbt_points_begin, current_bbt_points_end);
2060 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2061 current_bbt_points_begin, current_bbt_points_end);
2062 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2066 case SnapToRegionStart:
2067 case SnapToRegionEnd:
2068 case SnapToRegionSync:
2069 case SnapToRegionBoundary:
2070 build_region_boundary_cache ();
2078 SnapChanged (); /* EMIT SIGNAL */
2082 Editor::set_snap_mode (SnapMode mode)
2084 string str = snap_mode_strings[(int)mode];
2086 if (_internal_editing) {
2087 internal_snap_mode = mode;
2089 pre_internal_snap_mode = mode;
2094 if (str != snap_mode_selector.get_text ()) {
2095 snap_mode_selector.set_text (str);
2101 Editor::set_edit_point_preference (EditPoint ep, bool force)
2103 bool changed = (_edit_point != ep);
2106 string str = edit_point_strings[(int)ep];
2108 if (Profile->get_mixbus())
2109 if (ep == EditAtSelectedMarker)
2110 ep = EditAtPlayhead;
2112 if (str != edit_point_selector.get_text ()) {
2113 edit_point_selector.set_text (str);
2116 reset_canvas_cursor ();
2118 if (!force && !changed) {
2122 const char* action=NULL;
2124 switch (_edit_point) {
2125 case EditAtPlayhead:
2126 action = "edit-at-playhead";
2128 case EditAtSelectedMarker:
2129 action = "edit-at-marker";
2132 action = "edit-at-mouse";
2136 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2138 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2142 bool in_track_canvas;
2144 if (!mouse_frame (foo, in_track_canvas)) {
2145 in_track_canvas = false;
2148 reset_canvas_action_sensitivity (in_track_canvas);
2154 Editor::set_state (const XMLNode& node, int /*version*/)
2156 const XMLProperty* prop;
2163 g.base_width = default_width;
2164 g.base_height = default_height;
2168 if ((geometry = find_named_node (node, "geometry")) != 0) {
2172 if ((prop = geometry->property("x_size")) == 0) {
2173 prop = geometry->property ("x-size");
2176 g.base_width = atoi(prop->value());
2178 if ((prop = geometry->property("y_size")) == 0) {
2179 prop = geometry->property ("y-size");
2182 g.base_height = atoi(prop->value());
2185 if ((prop = geometry->property ("x_pos")) == 0) {
2186 prop = geometry->property ("x-pos");
2189 x = atoi (prop->value());
2192 if ((prop = geometry->property ("y_pos")) == 0) {
2193 prop = geometry->property ("y-pos");
2196 y = atoi (prop->value());
2200 set_default_size (g.base_width, g.base_height);
2203 if (_session && (prop = node.property ("playhead"))) {
2205 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2206 playhead_cursor->set_position (pos);
2208 playhead_cursor->set_position (0);
2211 if ((prop = node.property ("mixer-width"))) {
2212 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2215 if ((prop = node.property ("zoom-focus"))) {
2216 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2219 if ((prop = node.property ("zoom"))) {
2220 /* older versions of ardour used floating point samples_per_pixel */
2221 double f = PBD::atof (prop->value());
2222 reset_zoom (llrintf (f));
2224 reset_zoom (samples_per_pixel);
2227 if ((prop = node.property ("visible-track-count"))) {
2228 set_visible_track_count (PBD::atoi (prop->value()));
2231 if ((prop = node.property ("snap-to"))) {
2232 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2235 if ((prop = node.property ("snap-mode"))) {
2236 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2239 if ((prop = node.property ("internal-snap-to"))) {
2240 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2243 if ((prop = node.property ("internal-snap-mode"))) {
2244 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2247 if ((prop = node.property ("pre-internal-snap-to"))) {
2248 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2252 if ((prop = node.property ("pre-internal-snap-mode"))) {
2253 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2256 if ((prop = node.property ("mouse-mode"))) {
2257 MouseMode m = str2mousemode(prop->value());
2258 set_mouse_mode (m, true);
2260 set_mouse_mode (MouseObject, true);
2263 if ((prop = node.property ("left-frame")) != 0) {
2265 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2269 reset_x_origin (pos);
2273 if ((prop = node.property ("y-origin")) != 0) {
2274 reset_y_origin (atof (prop->value ()));
2277 if ((prop = node.property ("internal-edit"))) {
2278 bool yn = string_is_affirmative (prop->value());
2279 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2281 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2282 tact->set_active (!yn);
2283 tact->set_active (yn);
2287 if ((prop = node.property ("join-object-range"))) {
2288 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2289 bool yn = string_is_affirmative (prop->value());
2291 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2292 tact->set_active (!yn);
2293 tact->set_active (yn);
2295 set_mouse_mode(mouse_mode, true);
2298 if ((prop = node.property ("edit-point"))) {
2299 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2302 if ((prop = node.property ("show-measures"))) {
2303 bool yn = string_is_affirmative (prop->value());
2304 _show_measures = yn;
2305 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2307 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2308 /* do it twice to force the change */
2309 tact->set_active (!yn);
2310 tact->set_active (yn);
2314 if ((prop = node.property ("follow-playhead"))) {
2315 bool yn = string_is_affirmative (prop->value());
2316 set_follow_playhead (yn);
2317 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2319 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2320 if (tact->get_active() != yn) {
2321 tact->set_active (yn);
2326 if ((prop = node.property ("stationary-playhead"))) {
2327 bool yn = string_is_affirmative (prop->value());
2328 set_stationary_playhead (yn);
2329 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2331 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2332 if (tact->get_active() != yn) {
2333 tact->set_active (yn);
2338 if ((prop = node.property ("region-list-sort-type"))) {
2339 RegionListSortType st;
2340 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2343 if ((prop = node.property ("show-editor-mixer"))) {
2345 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2348 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2349 bool yn = string_is_affirmative (prop->value());
2351 /* do it twice to force the change */
2353 tact->set_active (!yn);
2354 tact->set_active (yn);
2357 if ((prop = node.property ("show-editor-list"))) {
2359 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2362 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2363 bool yn = string_is_affirmative (prop->value());
2365 /* do it twice to force the change */
2367 tact->set_active (!yn);
2368 tact->set_active (yn);
2371 if ((prop = node.property (X_("editor-list-page")))) {
2372 _the_notebook.set_current_page (atoi (prop->value ()));
2375 if ((prop = node.property (X_("show-marker-lines")))) {
2376 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2378 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2379 bool yn = string_is_affirmative (prop->value ());
2381 tact->set_active (!yn);
2382 tact->set_active (yn);
2385 XMLNodeList children = node.children ();
2386 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2387 selection->set_state (**i, Stateful::current_state_version);
2388 _regions->set_state (**i);
2391 if ((prop = node.property ("maximised"))) {
2392 bool yn = string_is_affirmative (prop->value());
2393 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2395 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2396 bool fs = tact && tact->get_active();
2398 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2402 if ((prop = node.property ("nudge-clock-value"))) {
2404 sscanf (prop->value().c_str(), "%" PRId64, &f);
2405 nudge_clock->set (f);
2407 nudge_clock->set_mode (AudioClock::Timecode);
2408 nudge_clock->set (_session->frame_rate() * 5, true);
2415 Editor::get_state ()
2417 XMLNode* node = new XMLNode ("Editor");
2420 id().print (buf, sizeof (buf));
2421 node->add_property ("id", buf);
2423 if (is_realized()) {
2424 Glib::RefPtr<Gdk::Window> win = get_window();
2426 int x, y, width, height;
2427 win->get_root_origin(x, y);
2428 win->get_size(width, height);
2430 XMLNode* geometry = new XMLNode ("geometry");
2432 snprintf(buf, sizeof(buf), "%d", width);
2433 geometry->add_property("x-size", string(buf));
2434 snprintf(buf, sizeof(buf), "%d", height);
2435 geometry->add_property("y-size", string(buf));
2436 snprintf(buf, sizeof(buf), "%d", x);
2437 geometry->add_property("x-pos", string(buf));
2438 snprintf(buf, sizeof(buf), "%d", y);
2439 geometry->add_property("y-pos", string(buf));
2440 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2441 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2442 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2443 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2444 geometry->add_property("edit-vertical-pane-pos", string(buf));
2446 node->add_child_nocopy (*geometry);
2449 maybe_add_mixer_strip_width (*node);
2451 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2453 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2454 node->add_property ("zoom", buf);
2455 node->add_property ("snap-to", enum_2_string (_snap_type));
2456 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2457 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2458 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2459 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2460 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2461 node->add_property ("edit-point", enum_2_string (_edit_point));
2462 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2463 node->add_property ("visible-track-count", buf);
2465 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2466 node->add_property ("playhead", buf);
2467 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2468 node->add_property ("left-frame", buf);
2469 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2470 node->add_property ("y-origin", buf);
2472 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2473 node->add_property ("maximised", _maximised ? "yes" : "no");
2474 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2475 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2476 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2477 node->add_property ("mouse-mode", enum2str(mouse_mode));
2478 node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2479 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2481 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2483 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2484 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2487 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2489 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2490 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2493 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2494 node->add_property (X_("editor-list-page"), buf);
2496 if (button_bindings) {
2497 XMLNode* bb = new XMLNode (X_("Buttons"));
2498 button_bindings->save (*bb);
2499 node->add_child_nocopy (*bb);
2502 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2504 node->add_child_nocopy (selection->get_state ());
2505 node->add_child_nocopy (_regions->get_state ());
2507 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2508 node->add_property ("nudge-clock-value", buf);
2513 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2514 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2516 * @return pair: TimeAxisView that y is over, layer index.
2518 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2519 * in stacked or expanded region display mode, otherwise 0.
2521 std::pair<TimeAxisView *, double>
2522 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2524 if (!trackview_relative_offset) {
2525 y -= _trackview_group->canvas_origin().y;
2529 return std::make_pair ( (TimeAxisView *) 0, 0);
2532 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2534 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2541 return std::make_pair ( (TimeAxisView *) 0, 0);
2544 /** Snap a position to the grid, if appropriate, taking into account current
2545 * grid settings and also the state of any snap modifier keys that may be pressed.
2546 * @param start Position to snap.
2547 * @param event Event to get current key modifier information from, or 0.
2550 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2552 if (!_session || !event) {
2556 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2557 if (_snap_mode == SnapOff) {
2558 snap_to_internal (start, direction, for_mark);
2561 if (_snap_mode != SnapOff) {
2562 snap_to_internal (start, direction, for_mark);
2568 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2570 if (!_session || _snap_mode == SnapOff) {
2574 snap_to_internal (start, direction, for_mark);
2578 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2580 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2581 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2583 switch (_snap_type) {
2584 case SnapToTimecodeFrame:
2585 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2586 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2588 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2592 case SnapToTimecodeSeconds:
2593 if (_session->config.get_timecode_offset_negative()) {
2594 start += _session->config.get_timecode_offset ();
2596 start -= _session->config.get_timecode_offset ();
2598 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2599 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2601 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2604 if (_session->config.get_timecode_offset_negative()) {
2605 start -= _session->config.get_timecode_offset ();
2607 start += _session->config.get_timecode_offset ();
2611 case SnapToTimecodeMinutes:
2612 if (_session->config.get_timecode_offset_negative()) {
2613 start += _session->config.get_timecode_offset ();
2615 start -= _session->config.get_timecode_offset ();
2617 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2618 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2620 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2622 if (_session->config.get_timecode_offset_negative()) {
2623 start -= _session->config.get_timecode_offset ();
2625 start += _session->config.get_timecode_offset ();
2629 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2635 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2637 const framepos_t one_second = _session->frame_rate();
2638 const framepos_t one_minute = _session->frame_rate() * 60;
2639 framepos_t presnap = start;
2643 switch (_snap_type) {
2644 case SnapToTimecodeFrame:
2645 case SnapToTimecodeSeconds:
2646 case SnapToTimecodeMinutes:
2647 return timecode_snap_to_internal (start, direction, for_mark);
2650 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2651 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2653 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2658 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2659 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2661 start = (framepos_t) floor ((double) start / one_second) * one_second;
2666 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2667 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2669 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2674 start = _session->tempo_map().round_to_bar (start, direction);
2678 start = _session->tempo_map().round_to_beat (start, direction);
2681 case SnapToBeatDiv128:
2682 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2684 case SnapToBeatDiv64:
2685 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2687 case SnapToBeatDiv32:
2688 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2690 case SnapToBeatDiv28:
2691 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2693 case SnapToBeatDiv24:
2694 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2696 case SnapToBeatDiv20:
2697 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2699 case SnapToBeatDiv16:
2700 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2702 case SnapToBeatDiv14:
2703 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2705 case SnapToBeatDiv12:
2706 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2708 case SnapToBeatDiv10:
2709 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2711 case SnapToBeatDiv8:
2712 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2714 case SnapToBeatDiv7:
2715 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2717 case SnapToBeatDiv6:
2718 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2720 case SnapToBeatDiv5:
2721 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2723 case SnapToBeatDiv4:
2724 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2726 case SnapToBeatDiv3:
2727 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2729 case SnapToBeatDiv2:
2730 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2738 _session->locations()->marks_either_side (start, before, after);
2740 if (before == max_framepos && after == max_framepos) {
2741 /* No marks to snap to, so just don't snap */
2743 } else if (before == max_framepos) {
2745 } else if (after == max_framepos) {
2747 } else if (before != max_framepos && after != max_framepos) {
2748 /* have before and after */
2749 if ((start - before) < (after - start)) {
2758 case SnapToRegionStart:
2759 case SnapToRegionEnd:
2760 case SnapToRegionSync:
2761 case SnapToRegionBoundary:
2762 if (!region_boundary_cache.empty()) {
2764 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2765 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2767 if (direction > 0) {
2768 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2770 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2773 if (next != region_boundary_cache.begin ()) {
2778 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2779 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2781 if (start > (p + n) / 2) {
2790 switch (_snap_mode) {
2796 if (presnap > start) {
2797 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2801 } else if (presnap < start) {
2802 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2808 /* handled at entry */
2816 Editor::setup_toolbar ()
2818 HBox* mode_box = manage(new HBox);
2819 mode_box->set_border_width (2);
2820 mode_box->set_spacing(2);
2822 HBox* mouse_mode_box = manage (new HBox);
2823 HBox* mouse_mode_hbox = manage (new HBox);
2824 VBox* mouse_mode_vbox = manage (new VBox);
2825 Alignment* mouse_mode_align = manage (new Alignment);
2827 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2828 mouse_mode_size_group->add_widget (smart_mode_button);
2829 mouse_mode_size_group->add_widget (mouse_move_button);
2830 mouse_mode_size_group->add_widget (mouse_cut_button);
2831 mouse_mode_size_group->add_widget (mouse_select_button);
2832 mouse_mode_size_group->add_widget (mouse_zoom_button);
2833 mouse_mode_size_group->add_widget (mouse_gain_button);
2834 mouse_mode_size_group->add_widget (mouse_timefx_button);
2835 mouse_mode_size_group->add_widget (mouse_audition_button);
2836 mouse_mode_size_group->add_widget (mouse_draw_button);
2837 mouse_mode_size_group->add_widget (internal_edit_button);
2839 mouse_mode_size_group->add_widget (zoom_in_button);
2840 mouse_mode_size_group->add_widget (zoom_out_button);
2841 mouse_mode_size_group->add_widget (zoom_preset_selector);
2842 mouse_mode_size_group->add_widget (zoom_out_full_button);
2843 mouse_mode_size_group->add_widget (zoom_focus_selector);
2845 mouse_mode_size_group->add_widget (tav_shrink_button);
2846 mouse_mode_size_group->add_widget (tav_expand_button);
2847 mouse_mode_size_group->add_widget (visible_tracks_selector);
2849 mouse_mode_size_group->add_widget (snap_type_selector);
2850 mouse_mode_size_group->add_widget (snap_mode_selector);
2852 mouse_mode_size_group->add_widget (edit_point_selector);
2853 mouse_mode_size_group->add_widget (edit_mode_selector);
2855 mouse_mode_size_group->add_widget (*nudge_clock);
2856 mouse_mode_size_group->add_widget (nudge_forward_button);
2857 mouse_mode_size_group->add_widget (nudge_backward_button);
2859 mouse_mode_hbox->set_spacing (2);
2861 if (!ARDOUR::Profile->get_trx()) {
2862 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2865 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2866 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2868 if (!ARDOUR::Profile->get_mixbus()) {
2869 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2870 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2873 if (!ARDOUR::Profile->get_trx()) {
2874 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2875 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2876 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2877 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2878 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 0);
2881 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2883 mouse_mode_align->add (*mouse_mode_vbox);
2884 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2886 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2888 edit_mode_selector.set_name ("mouse mode button");
2890 if (!ARDOUR::Profile->get_trx()) {
2891 mode_box->pack_start (edit_mode_selector, false, false);
2893 mode_box->pack_start (*mouse_mode_box, false, false);
2895 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2896 _mouse_mode_tearoff->set_name ("MouseModeBase");
2897 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2899 if (Profile->get_sae() || Profile->get_mixbus() ) {
2900 _mouse_mode_tearoff->set_can_be_torn_off (false);
2903 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2904 &_mouse_mode_tearoff->tearoff_window()));
2905 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2906 &_mouse_mode_tearoff->tearoff_window(), 1));
2907 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2908 &_mouse_mode_tearoff->tearoff_window()));
2909 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2910 &_mouse_mode_tearoff->tearoff_window(), 1));
2914 _zoom_box.set_spacing (2);
2915 _zoom_box.set_border_width (2);
2919 zoom_preset_selector.set_name ("zoom button");
2920 zoom_preset_selector.set_image(::get_icon ("time_exp"));
2921 zoom_preset_selector.set_size_request (42, -1);
2923 zoom_in_button.set_name ("zoom button");
2924 zoom_in_button.set_image(::get_icon ("zoom_in"));
2925 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2926 zoom_in_button.set_related_action (act);
2928 zoom_out_button.set_name ("zoom button");
2929 zoom_out_button.set_image(::get_icon ("zoom_out"));
2930 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2931 zoom_out_button.set_related_action (act);
2933 zoom_out_full_button.set_name ("zoom button");
2934 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2935 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2936 zoom_out_full_button.set_related_action (act);
2938 zoom_focus_selector.set_name ("zoom button");
2940 if (ARDOUR::Profile->get_mixbus()) {
2941 _zoom_box.pack_start (zoom_preset_selector, false, false);
2942 } else if (ARDOUR::Profile->get_trx()) {
2943 mode_box->pack_start (zoom_out_button, false, false);
2944 mode_box->pack_start (zoom_in_button, false, false);
2946 _zoom_box.pack_start (zoom_out_button, false, false);
2947 _zoom_box.pack_start (zoom_in_button, false, false);
2948 _zoom_box.pack_start (zoom_out_full_button, false, false);
2949 _zoom_box.pack_start (zoom_focus_selector, false, false);
2952 /* Track zoom buttons */
2953 visible_tracks_selector.set_name ("zoom button");
2954 if (Profile->get_mixbus()) {
2955 visible_tracks_selector.set_image(::get_icon ("tav_exp"));
2956 visible_tracks_selector.set_size_request (42, -1);
2958 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
2961 tav_expand_button.set_name ("zoom button");
2962 tav_expand_button.set_image(::get_icon ("tav_exp"));
2963 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2964 tav_expand_button.set_related_action (act);
2966 tav_shrink_button.set_name ("zoom button");
2967 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2968 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2969 tav_shrink_button.set_related_action (act);
2971 if (ARDOUR::Profile->get_mixbus()) {
2972 _zoom_box.pack_start (visible_tracks_selector);
2973 } else if (ARDOUR::Profile->get_trx()) {
2974 _zoom_box.pack_start (tav_shrink_button);
2975 _zoom_box.pack_start (tav_expand_button);
2977 _zoom_box.pack_start (visible_tracks_selector);
2978 _zoom_box.pack_start (tav_shrink_button);
2979 _zoom_box.pack_start (tav_expand_button);
2982 if (!ARDOUR::Profile->get_trx()) {
2983 _zoom_tearoff = manage (new TearOff (_zoom_box));
2985 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2986 &_zoom_tearoff->tearoff_window()));
2987 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2988 &_zoom_tearoff->tearoff_window(), 0));
2989 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2990 &_zoom_tearoff->tearoff_window()));
2991 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2992 &_zoom_tearoff->tearoff_window(), 0));
2995 if (Profile->get_sae() || Profile->get_mixbus() ) {
2996 _zoom_tearoff->set_can_be_torn_off (false);
2999 snap_box.set_spacing (2);
3000 snap_box.set_border_width (2);
3002 snap_type_selector.set_name ("mouse mode button");
3004 snap_mode_selector.set_name ("mouse mode button");
3006 edit_point_selector.set_name ("mouse mode button");
3008 snap_box.pack_start (snap_mode_selector, false, false);
3009 snap_box.pack_start (snap_type_selector, false, false);
3010 snap_box.pack_start (edit_point_selector, false, false);
3014 HBox *nudge_box = manage (new HBox);
3015 nudge_box->set_spacing (2);
3016 nudge_box->set_border_width (2);
3018 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3019 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3021 nudge_box->pack_start (nudge_backward_button, false, false);
3022 nudge_box->pack_start (nudge_forward_button, false, false);
3023 nudge_box->pack_start (*nudge_clock, false, false);
3026 /* Pack everything in... */
3028 HBox* hbox = manage (new HBox);
3029 hbox->set_spacing(2);
3031 _tools_tearoff = manage (new TearOff (*hbox));
3032 _tools_tearoff->set_name ("MouseModeBase");
3033 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3035 if (Profile->get_sae() || Profile->get_mixbus()) {
3036 _tools_tearoff->set_can_be_torn_off (false);
3039 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3040 &_tools_tearoff->tearoff_window()));
3041 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3042 &_tools_tearoff->tearoff_window(), 0));
3043 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3044 &_tools_tearoff->tearoff_window()));
3045 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3046 &_tools_tearoff->tearoff_window(), 0));
3048 toolbar_hbox.set_spacing (2);
3049 toolbar_hbox.set_border_width (1);
3051 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3052 if (!ARDOUR::Profile->get_trx()) {
3053 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3054 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3057 if (!ARDOUR::Profile->get_trx()) {
3058 hbox->pack_start (snap_box, false, false);
3059 if ( !Profile->get_small_screen() || Profile->get_mixbus() ) {
3060 hbox->pack_start (*nudge_box, false, false);
3062 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3065 hbox->pack_start (panic_box, false, false);
3069 toolbar_base.set_name ("ToolBarBase");
3070 toolbar_base.add (toolbar_hbox);
3072 _toolbar_viewport.add (toolbar_base);
3073 /* stick to the required height but allow width to vary if there's not enough room */
3074 _toolbar_viewport.set_size_request (1, -1);
3076 toolbar_frame.set_shadow_type (SHADOW_OUT);
3077 toolbar_frame.set_name ("BaseFrame");
3078 toolbar_frame.add (_toolbar_viewport);
3082 Editor::build_edit_point_menu ()
3084 using namespace Menu_Helpers;
3086 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3087 if(!Profile->get_mixbus())
3088 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3089 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3091 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3095 Editor::build_edit_mode_menu ()
3097 using namespace Menu_Helpers;
3099 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3100 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3101 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3102 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3104 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3108 Editor::build_snap_mode_menu ()
3110 using namespace Menu_Helpers;
3112 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3113 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3114 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3116 set_size_request_to_display_given_text (snap_mode_selector, snap_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3120 Editor::build_snap_type_menu ()
3122 using namespace Menu_Helpers;
3124 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3125 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3126 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3127 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3128 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3129 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3130 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3131 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3132 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3133 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3134 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3135 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3136 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3137 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3138 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3139 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3140 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3141 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3142 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3143 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3144 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3145 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3146 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3147 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3148 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3149 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3150 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3151 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3152 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3153 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3155 set_size_request_to_display_given_text (snap_type_selector, snap_type_strings, COMBO_TRIANGLE_WIDTH, 2);
3160 Editor::setup_tooltips ()
3162 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3163 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3164 ARDOUR_UI::instance()->set_tip (mouse_cut_button, _("Cut Mode (split Regions)"));
3165 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3166 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3167 ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3168 ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3169 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3170 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3171 ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3172 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3173 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3174 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3175 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3176 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3177 ARDOUR_UI::instance()->set_tip (zoom_preset_selector, _("Zoom to Time Scale"));
3178 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3179 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3180 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3181 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3182 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3183 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3184 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3185 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3186 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3187 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3191 Editor::convert_drop_to_paths (
3192 vector<string>& paths,
3193 const RefPtr<Gdk::DragContext>& /*context*/,
3196 const SelectionData& data,
3200 if (_session == 0) {
3204 vector<string> uris = data.get_uris();
3208 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3209 are actually URI lists. So do it by hand.
3212 if (data.get_target() != "text/plain") {
3216 /* Parse the "uri-list" format that Nautilus provides,
3217 where each pathname is delimited by \r\n.
3219 THERE MAY BE NO NULL TERMINATING CHAR!!!
3222 string txt = data.get_text();
3226 p = (char *) malloc (txt.length() + 1);
3227 txt.copy (p, txt.length(), 0);
3228 p[txt.length()] = '\0';
3234 while (g_ascii_isspace (*p))
3238 while (*q && (*q != '\n') && (*q != '\r')) {
3245 while (q > p && g_ascii_isspace (*q))
3250 uris.push_back (string (p, q - p + 1));
3254 p = strchr (p, '\n');
3266 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3267 if ((*i).substr (0,7) == "file://") {
3268 paths.push_back (Glib::filename_from_uri (*i));
3276 Editor::new_tempo_section ()
3281 Editor::map_transport_state ()
3283 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3285 if (_session && _session->transport_stopped()) {
3286 have_pending_keyboard_selection = false;
3289 update_loop_range_view ();
3295 Editor::begin_reversible_command (string name)
3298 _session->begin_reversible_command (name);
3303 Editor::begin_reversible_command (GQuark q)
3306 _session->begin_reversible_command (q);
3311 Editor::commit_reversible_command ()
3314 _session->commit_reversible_command ();
3319 Editor::history_changed ()
3323 if (undo_action && _session) {
3324 if (_session->undo_depth() == 0) {
3325 label = S_("Command|Undo");
3327 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3329 undo_action->property_label() = label;
3332 if (redo_action && _session) {
3333 if (_session->redo_depth() == 0) {
3336 label = string_compose(_("Redo (%1)"), _session->next_redo());
3338 redo_action->property_label() = label;
3343 Editor::duplicate_range (bool with_dialog)
3347 RegionSelection rs = get_regions_from_selection_and_entered ();
3349 if ( selection->time.length() == 0 && rs.empty()) {
3355 ArdourDialog win (_("Duplicate"));
3356 Label label (_("Number of duplications:"));
3357 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3358 SpinButton spinner (adjustment, 0.0, 1);
3361 win.get_vbox()->set_spacing (12);
3362 win.get_vbox()->pack_start (hbox);
3363 hbox.set_border_width (6);
3364 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3366 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3367 place, visually. so do this by hand.
3370 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3371 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3372 spinner.grab_focus();
3378 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3379 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3380 win.set_default_response (RESPONSE_ACCEPT);
3382 spinner.grab_focus ();
3384 switch (win.run ()) {
3385 case RESPONSE_ACCEPT:
3391 times = adjustment.get_value();
3394 if ((current_mouse_mode() == Editing::MouseRange)) {
3395 if (selection->time.length()) {
3396 duplicate_selection (times);
3398 } else if (get_smart_mode()) {
3399 if (selection->time.length()) {
3400 duplicate_selection (times);
3402 duplicate_some_regions (rs, times);
3404 duplicate_some_regions (rs, times);
3409 Editor::set_edit_mode (EditMode m)
3411 Config->set_edit_mode (m);
3415 Editor::cycle_edit_mode ()
3417 switch (Config->get_edit_mode()) {
3419 if (Profile->get_sae()) {
3420 Config->set_edit_mode (Lock);
3422 Config->set_edit_mode (Ripple);
3427 Config->set_edit_mode (Lock);
3430 Config->set_edit_mode (Slide);
3436 Editor::edit_mode_selection_done ( EditMode m )
3438 Config->set_edit_mode ( m );
3442 Editor::snap_type_selection_done (SnapType snaptype)
3444 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3446 ract->set_active ();
3451 Editor::snap_mode_selection_done (SnapMode mode)
3453 RefPtr<RadioAction> ract = snap_mode_action (mode);
3456 ract->set_active (true);
3461 Editor::cycle_edit_point (bool with_marker)
3463 if(Profile->get_mixbus())
3464 with_marker = false;
3466 switch (_edit_point) {
3468 set_edit_point_preference (EditAtPlayhead);
3470 case EditAtPlayhead:
3472 set_edit_point_preference (EditAtSelectedMarker);
3474 set_edit_point_preference (EditAtMouse);
3477 case EditAtSelectedMarker:
3478 set_edit_point_preference (EditAtMouse);
3484 Editor::edit_point_selection_done (EditPoint ep)
3486 set_edit_point_preference ( ep );
3490 Editor::build_zoom_focus_menu ()
3492 using namespace Menu_Helpers;
3494 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3495 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3496 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3497 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3498 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3499 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3501 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3505 Editor::zoom_focus_selection_done ( ZoomFocus f )
3507 RefPtr<RadioAction> ract = zoom_focus_action (f);
3509 ract->set_active ();
3514 Editor::build_track_count_menu ()
3516 using namespace Menu_Helpers;
3518 if (!Profile->get_mixbus()) {
3519 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3520 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3521 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3522 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3523 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3524 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3525 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3526 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3527 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3528 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3529 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3530 visible_tracks_selector.AddMenuElem (MenuElem (_("Selected"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3531 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3533 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3534 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3535 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3536 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3537 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3538 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3539 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3540 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3541 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3542 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selected tracks"), sigc::mem_fun(*this, &Editor::fit_selected_tracks)));
3544 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3545 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3546 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3547 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3548 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3549 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3550 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3551 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3552 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3553 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3554 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), false)));
3559 Editor::set_zoom_preset (int64_t ms)
3562 temporal_zoom_session();
3566 ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3567 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3571 Editor::set_visible_track_count (int32_t n)
3573 _visible_track_count = n;
3575 /* if the canvas hasn't really been allocated any size yet, just
3576 record the desired number of visible tracks and return. when canvas
3577 allocation happens, we will get called again and then we can do the
3581 if (_visible_canvas_height <= 1) {
3588 if (_visible_track_count > 0) {
3589 h = trackviews_height() / _visible_track_count;
3590 std::ostringstream s;
3591 s << _visible_track_count;
3593 } else if (_visible_track_count == 0) {
3595 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3596 if ((*i)->marked_for_display()) {
3600 h = trackviews_height() / n;
3603 /* negative value means that the visible track count has
3604 been overridden by explicit track height changes.
3606 visible_tracks_selector.set_text (X_("*"));
3610 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3611 (*i)->set_height (h);
3614 if (str != visible_tracks_selector.get_text()) {
3615 visible_tracks_selector.set_text (str);
3620 Editor::override_visible_track_count ()
3622 _visible_track_count = -1;
3623 visible_tracks_selector.set_text ( _("*") );
3627 Editor::edit_controls_button_release (GdkEventButton* ev)
3629 if (Keyboard::is_context_menu_event (ev)) {
3630 ARDOUR_UI::instance()->add_route (this);
3631 } else if (ev->button == 1) {
3632 selection->clear_tracks ();
3639 Editor::mouse_select_button_release (GdkEventButton* ev)
3641 /* this handles just right-clicks */
3643 if (ev->button != 3) {
3651 Editor::set_zoom_focus (ZoomFocus f)
3653 string str = zoom_focus_strings[(int)f];
3655 if (str != zoom_focus_selector.get_text()) {
3656 zoom_focus_selector.set_text (str);
3659 if (zoom_focus != f) {
3666 Editor::cycle_zoom_focus ()
3668 switch (zoom_focus) {
3670 set_zoom_focus (ZoomFocusRight);
3672 case ZoomFocusRight:
3673 set_zoom_focus (ZoomFocusCenter);
3675 case ZoomFocusCenter:
3676 set_zoom_focus (ZoomFocusPlayhead);
3678 case ZoomFocusPlayhead:
3679 set_zoom_focus (ZoomFocusMouse);
3681 case ZoomFocusMouse:
3682 set_zoom_focus (ZoomFocusEdit);
3685 set_zoom_focus (ZoomFocusLeft);
3691 Editor::ensure_float (Window& win)
3693 win.set_transient_for (*this);
3697 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3699 /* recover or initialize pane positions. do this here rather than earlier because
3700 we don't want the positions to change the child allocations, which they seem to do.
3706 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3715 XMLNode* geometry = find_named_node (*node, "geometry");
3717 if (which == static_cast<Paned*> (&edit_pane)) {
3719 if (done & Horizontal) {
3723 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3724 _notebook_shrunk = string_is_affirmative (prop->value ());
3727 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3728 /* initial allocation is 90% to canvas, 10% to notebook */
3729 pos = (int) floor (alloc.get_width() * 0.90f);
3730 snprintf (buf, sizeof(buf), "%d", pos);
3732 pos = atoi (prop->value());
3735 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3736 edit_pane.set_position (pos);
3739 done = (Pane) (done | Horizontal);
3741 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3743 if (done & Vertical) {
3747 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3748 /* initial allocation is 90% to canvas, 10% to summary */
3749 pos = (int) floor (alloc.get_height() * 0.90f);
3750 snprintf (buf, sizeof(buf), "%d", pos);
3753 pos = atoi (prop->value());
3756 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3757 editor_summary_pane.set_position (pos);
3760 done = (Pane) (done | Vertical);
3765 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3767 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3768 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3769 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3770 top_hbox.remove (toolbar_frame);
3775 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3777 if (toolbar_frame.get_parent() == 0) {
3778 top_hbox.pack_end (toolbar_frame);
3783 Editor::set_show_measures (bool yn)
3785 if (_show_measures != yn) {
3788 if ((_show_measures = yn) == true) {
3790 tempo_lines->show();
3793 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3794 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3796 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3797 draw_measures (begin, end);
3805 Editor::toggle_follow_playhead ()
3807 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3809 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3810 set_follow_playhead (tact->get_active());
3814 /** @param yn true to follow playhead, otherwise false.
3815 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3818 Editor::set_follow_playhead (bool yn, bool catch_up)
3820 if (_follow_playhead != yn) {
3821 if ((_follow_playhead = yn) == true && catch_up) {
3823 reset_x_origin_to_follow_playhead ();
3830 Editor::toggle_stationary_playhead ()
3832 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3834 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3835 set_stationary_playhead (tact->get_active());
3840 Editor::set_stationary_playhead (bool yn)
3842 if (_stationary_playhead != yn) {
3843 if ((_stationary_playhead = yn) == true) {
3845 // FIXME need a 3.0 equivalent of this 2.X call
3846 // update_current_screen ();
3853 Editor::playlist_selector () const
3855 return *_playlist_selector;
3859 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3863 switch (_snap_type) {
3868 case SnapToBeatDiv128:
3871 case SnapToBeatDiv64:
3874 case SnapToBeatDiv32:
3877 case SnapToBeatDiv28:
3880 case SnapToBeatDiv24:
3883 case SnapToBeatDiv20:
3886 case SnapToBeatDiv16:
3889 case SnapToBeatDiv14:
3892 case SnapToBeatDiv12:
3895 case SnapToBeatDiv10:
3898 case SnapToBeatDiv8:
3901 case SnapToBeatDiv7:
3904 case SnapToBeatDiv6:
3907 case SnapToBeatDiv5:
3910 case SnapToBeatDiv4:
3913 case SnapToBeatDiv3:
3916 case SnapToBeatDiv2:
3922 return _session->tempo_map().meter_at (position).divisions_per_bar();
3927 case SnapToTimecodeFrame:
3928 case SnapToTimecodeSeconds:
3929 case SnapToTimecodeMinutes:
3932 case SnapToRegionStart:
3933 case SnapToRegionEnd:
3934 case SnapToRegionSync:
3935 case SnapToRegionBoundary:
3945 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3949 ret = nudge_clock->current_duration (pos);
3950 next = ret + 1; /* XXXX fix me */
3956 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3958 ArdourDialog dialog (_("Playlist Deletion"));
3959 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3960 "If it is kept, its audio files will not be cleaned.\n"
3961 "If it is deleted, audio files used by it alone will be cleaned."),
3964 dialog.set_position (WIN_POS_CENTER);
3965 dialog.get_vbox()->pack_start (label);
3969 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3970 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3971 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3973 switch (dialog.run ()) {
3974 case RESPONSE_ACCEPT:
3975 /* delete the playlist */
3979 case RESPONSE_REJECT:
3980 /* keep the playlist */
3992 Editor::audio_region_selection_covers (framepos_t where)
3994 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3995 if ((*a)->region()->covers (where)) {
4004 Editor::prepare_for_cleanup ()
4006 cut_buffer->clear_regions ();
4007 cut_buffer->clear_playlists ();
4009 selection->clear_regions ();
4010 selection->clear_playlists ();
4012 _regions->suspend_redisplay ();
4016 Editor::finish_cleanup ()
4018 _regions->resume_redisplay ();
4022 Editor::transport_loop_location()
4025 return _session->locations()->auto_loop_location();
4032 Editor::transport_punch_location()
4035 return _session->locations()->auto_punch_location();
4042 Editor::control_layout_scroll (GdkEventScroll* ev)
4044 /* Just forward to the normal canvas scroll method. The coordinate
4045 systems are different but since the canvas is always larger than the
4046 track headers, and aligned with the trackview area, this will work.
4048 In the not too distant future this layout is going away anyway and
4049 headers will be on the canvas.
4051 return canvas_scroll_event (ev, false);
4055 Editor::session_state_saved (string)
4058 _snapshots->redisplay ();
4062 Editor::update_tearoff_visibility()
4064 bool visible = Config->get_keep_tearoffs();
4065 _mouse_mode_tearoff->set_visible (visible);
4066 _tools_tearoff->set_visible (visible);
4067 if (_zoom_tearoff) {
4068 _zoom_tearoff->set_visible (visible);
4073 Editor::reattach_all_tearoffs ()
4075 if (_mouse_mode_tearoff) _mouse_mode_tearoff->put_it_back ();
4076 if (_tools_tearoff) _tools_tearoff->put_it_back ();
4077 if (_zoom_tearoff) _zoom_tearoff->put_it_back ();
4081 Editor::maximise_editing_space ()
4093 Editor::restore_editing_space ()
4105 * Make new playlists for a given track and also any others that belong
4106 * to the same active route group with the `select' property.
4111 Editor::new_playlists (TimeAxisView* v)
4113 begin_reversible_command (_("new playlists"));
4114 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4115 _session->playlists->get (playlists);
4116 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4117 commit_reversible_command ();
4121 * Use a copy of the current playlist for a given track and also any others that belong
4122 * to the same active route group with the `select' property.
4127 Editor::copy_playlists (TimeAxisView* v)
4129 begin_reversible_command (_("copy playlists"));
4130 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4131 _session->playlists->get (playlists);
4132 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4133 commit_reversible_command ();
4136 /** Clear the current playlist for a given track and also any others that belong
4137 * to the same active route group with the `select' property.
4142 Editor::clear_playlists (TimeAxisView* v)
4144 begin_reversible_command (_("clear playlists"));
4145 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4146 _session->playlists->get (playlists);
4147 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4148 commit_reversible_command ();
4152 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4154 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4158 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4160 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4164 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4166 atv.clear_playlist ();
4170 Editor::on_key_press_event (GdkEventKey* ev)
4172 return key_press_focus_accelerator_handler (*this, ev);
4176 Editor::on_key_release_event (GdkEventKey* ev)
4178 return Gtk::Window::on_key_release_event (ev);
4179 // return key_press_focus_accelerator_handler (*this, ev);
4182 /** Queue up a change to the viewport x origin.
4183 * @param frame New x origin.
4186 Editor::reset_x_origin (framepos_t frame)
4188 pending_visual_change.add (VisualChange::TimeOrigin);
4189 pending_visual_change.time_origin = frame;
4190 ensure_visual_change_idle_handler ();
4194 Editor::reset_y_origin (double y)
4196 pending_visual_change.add (VisualChange::YOrigin);
4197 pending_visual_change.y_origin = y;
4198 ensure_visual_change_idle_handler ();
4202 Editor::reset_zoom (framecnt_t spp)
4204 if (spp == samples_per_pixel) {
4208 pending_visual_change.add (VisualChange::ZoomLevel);
4209 pending_visual_change.samples_per_pixel = spp;
4210 ensure_visual_change_idle_handler ();
4214 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4216 reset_x_origin (frame);
4219 if (!no_save_visual) {
4220 undo_visual_stack.push_back (current_visual_state(false));
4224 Editor::VisualState::VisualState (bool with_tracks)
4225 : gui_state (with_tracks ? new GUIObjectState : 0)
4229 Editor::VisualState::~VisualState ()
4234 Editor::VisualState*
4235 Editor::current_visual_state (bool with_tracks)
4237 VisualState* vs = new VisualState (with_tracks);
4238 vs->y_position = vertical_adjustment.get_value();
4239 vs->samples_per_pixel = samples_per_pixel;
4240 vs->leftmost_frame = leftmost_frame;
4241 vs->zoom_focus = zoom_focus;
4244 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4251 Editor::undo_visual_state ()
4253 if (undo_visual_stack.empty()) {
4257 VisualState* vs = undo_visual_stack.back();
4258 undo_visual_stack.pop_back();
4261 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4263 use_visual_state (*vs);
4267 Editor::redo_visual_state ()
4269 if (redo_visual_stack.empty()) {
4273 VisualState* vs = redo_visual_stack.back();
4274 redo_visual_stack.pop_back();
4276 undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4278 use_visual_state (*vs);
4282 Editor::swap_visual_state ()
4284 if (undo_visual_stack.empty()) {
4285 redo_visual_state ();
4287 undo_visual_state ();
4292 Editor::use_visual_state (VisualState& vs)
4294 PBD::Unwinder<bool> nsv (no_save_visual, true);
4295 DisplaySuspender ds;
4297 vertical_adjustment.set_value (vs.y_position);
4299 set_zoom_focus (vs.zoom_focus);
4300 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4303 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4305 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4306 (*i)->reset_visual_state ();
4310 _routes->update_visibility ();
4313 /** This is the core function that controls the zoom level of the canvas. It is called
4314 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4315 * @param spp new number of samples per pixel
4318 Editor::set_samples_per_pixel (framecnt_t spp)
4324 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4325 const framecnt_t lots_of_pixels = 4000;
4327 /* if the zoom level is greater than what you'd get trying to display 3
4328 * days of audio on a really big screen, then it's too big.
4331 if (spp * lots_of_pixels > three_days) {
4335 samples_per_pixel = spp;
4338 tempo_lines->tempo_map_changed();
4341 bool const showing_time_selection = selection->time.length() > 0;
4343 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4344 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4345 (*i)->reshow_selection (selection->time);
4349 ZoomChanged (); /* EMIT_SIGNAL */
4351 ArdourCanvas::GtkCanvasViewport* c;
4353 c = get_track_canvas();
4355 c->canvas()->zoomed ();
4358 if (playhead_cursor) {
4359 playhead_cursor->set_position (playhead_cursor->current_frame ());
4362 refresh_location_display();
4363 _summary->set_overlays_dirty ();
4365 update_marker_labels ();
4371 Editor::queue_visual_videotimeline_update ()
4374 * pending_visual_change.add (VisualChange::VideoTimeline);
4375 * or maybe even more specific: which videotimeline-image
4376 * currently it calls update_video_timeline() to update
4377 * _all outdated_ images on the video-timeline.
4378 * see 'exposeimg()' in video_image_frame.cc
4380 ensure_visual_change_idle_handler ();
4384 Editor::ensure_visual_change_idle_handler ()
4386 if (pending_visual_change.idle_handler_id < 0) {
4387 // see comment in add_to_idle_resize above.
4388 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE + 20, _idle_visual_changer, this, NULL);
4389 pending_visual_change.being_handled = false;
4394 Editor::_idle_visual_changer (void* arg)
4396 return static_cast<Editor*>(arg)->idle_visual_changer ();
4400 Editor::idle_visual_changer ()
4402 /* set_horizontal_position() below (and maybe other calls) call
4403 gtk_main_iteration(), so it's possible that a signal will be handled
4404 half-way through this method. If this signal wants an
4405 idle_visual_changer we must schedule another one after this one, so
4406 mark the idle_handler_id as -1 here to allow that. Also make a note
4407 that we are doing the visual change, so that changes in response to
4408 super-rapid-screen-update can be dropped if we are still processing
4412 pending_visual_change.idle_handler_id = -1;
4413 pending_visual_change.being_handled = true;
4415 VisualChange vc = pending_visual_change;
4417 pending_visual_change.pending = (VisualChange::Type) 0;
4419 visual_changer (vc);
4421 pending_visual_change.being_handled = false;
4423 return 0; /* this is always a one-shot call */
4427 Editor::visual_changer (const VisualChange& vc)
4429 double const last_time_origin = horizontal_position ();
4431 if (vc.pending & VisualChange::ZoomLevel) {
4432 set_samples_per_pixel (vc.samples_per_pixel);
4434 compute_fixed_ruler_scale ();
4436 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4437 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4439 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4440 current_bbt_points_begin, current_bbt_points_end);
4441 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4442 current_bbt_points_begin, current_bbt_points_end);
4443 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4445 update_video_timeline();
4448 if (vc.pending & VisualChange::TimeOrigin) {
4449 set_horizontal_position (vc.time_origin / samples_per_pixel);
4452 if (vc.pending & VisualChange::YOrigin) {
4453 vertical_adjustment.set_value (vc.y_origin);
4456 if (last_time_origin == horizontal_position ()) {
4457 /* changed signal not emitted */
4458 update_fixed_rulers ();
4459 redisplay_tempo (true);
4462 if (!(vc.pending & VisualChange::ZoomLevel)) {
4463 update_video_timeline();
4466 _summary->set_overlays_dirty ();
4469 struct EditorOrderTimeAxisSorter {
4470 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4471 return a->order () < b->order ();
4476 Editor::sort_track_selection (TrackViewList& sel)
4478 EditorOrderTimeAxisSorter cmp;
4483 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4486 framepos_t where = 0;
4487 EditPoint ep = _edit_point;
4489 if(Profile->get_mixbus())
4490 if (ep == EditAtSelectedMarker)
4493 if (from_context_menu && (ep == EditAtMouse)) {
4494 return canvas_event_sample (&context_click_event, 0, 0);
4497 if (entered_marker) {
4498 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4499 return entered_marker->position();
4502 if (ignore_playhead && ep == EditAtPlayhead) {
4503 ep = EditAtSelectedMarker;
4507 case EditAtPlayhead:
4508 where = _session->audible_frame();
4509 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4512 case EditAtSelectedMarker:
4513 if (!selection->markers.empty()) {
4515 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4518 where = loc->start();
4522 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4530 if (!mouse_frame (where, ignored)) {
4531 /* XXX not right but what can we do ? */
4535 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4543 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4545 if (!_session) return;
4547 begin_reversible_command (cmd);
4551 if ((tll = transport_loop_location()) == 0) {
4552 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4553 XMLNode &before = _session->locations()->get_state();
4554 _session->locations()->add (loc, true);
4555 _session->set_auto_loop_location (loc);
4556 XMLNode &after = _session->locations()->get_state();
4557 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4559 XMLNode &before = tll->get_state();
4560 tll->set_hidden (false, this);
4561 tll->set (start, end);
4562 XMLNode &after = tll->get_state();
4563 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4566 commit_reversible_command ();
4570 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4572 if (!_session) return;
4574 begin_reversible_command (cmd);
4578 if ((tpl = transport_punch_location()) == 0) {
4579 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4580 XMLNode &before = _session->locations()->get_state();
4581 _session->locations()->add (loc, true);
4582 _session->set_auto_punch_location (loc);
4583 XMLNode &after = _session->locations()->get_state();
4584 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4587 XMLNode &before = tpl->get_state();
4588 tpl->set_hidden (false, this);
4589 tpl->set (start, end);
4590 XMLNode &after = tpl->get_state();
4591 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4594 commit_reversible_command ();
4597 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4598 * @param rs List to which found regions are added.
4599 * @param where Time to look at.
4600 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4603 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4605 const TrackViewList* tracks;
4608 tracks = &track_views;
4613 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4615 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4618 boost::shared_ptr<Track> tr;
4619 boost::shared_ptr<Playlist> pl;
4621 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4623 boost::shared_ptr<RegionList> regions = pl->regions_at (
4624 (framepos_t) floor ( (double) where * tr->speed()));
4626 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4627 RegionView* rv = rtv->view()->find_view (*i);
4638 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4640 const TrackViewList* tracks;
4643 tracks = &track_views;
4648 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4649 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4651 boost::shared_ptr<Track> tr;
4652 boost::shared_ptr<Playlist> pl;
4654 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4656 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4657 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4659 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4661 RegionView* rv = rtv->view()->find_view (*i);
4672 /** Get regions using the following method:
4674 * Make a region list using:
4675 * (a) any selected regions
4676 * (b) the intersection of any selected tracks and the edit point(*)
4677 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4679 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4681 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4685 Editor::get_regions_from_selection_and_edit_point ()
4687 RegionSelection regions;
4689 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4690 regions.add (entered_regionview);
4692 regions = selection->regions;
4695 if ( regions.empty() ) {
4696 TrackViewList tracks = selection->tracks;
4698 if (!tracks.empty()) {
4699 /* no region selected or entered, but some selected tracks:
4700 * act on all regions on the selected tracks at the edit point
4702 framepos_t const where = get_preferred_edit_position ();
4703 get_regions_at(regions, where, tracks);
4710 /** Get regions using the following method:
4712 * Make a region list using:
4713 * (a) any selected regions
4714 * (b) the intersection of any selected tracks and the edit point(*)
4715 * (c) if neither exists, then whatever region is under the mouse
4717 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4719 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4722 Editor::get_regions_from_selection_and_mouse (framepos_t pos)
4724 RegionSelection regions;
4726 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4727 regions.add (entered_regionview);
4729 regions = selection->regions;
4732 if ( regions.empty() ) {
4733 TrackViewList tracks = selection->tracks;
4735 if (!tracks.empty()) {
4736 /* no region selected or entered, but some selected tracks:
4737 * act on all regions on the selected tracks at the edit point
4739 get_regions_at(regions, pos, tracks);
4746 /** Start with regions that are selected, or the entered regionview if none are selected.
4747 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4748 * of the regions that we started with.
4752 Editor::get_regions_from_selection_and_entered ()
4754 RegionSelection regions = selection->regions;
4756 if (regions.empty() && entered_regionview) {
4757 regions.add (entered_regionview);
4764 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4766 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4768 RouteTimeAxisView* tatv;
4770 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4772 boost::shared_ptr<Playlist> pl;
4773 vector<boost::shared_ptr<Region> > results;
4775 boost::shared_ptr<Track> tr;
4777 if ((tr = tatv->track()) == 0) {
4782 if ((pl = (tr->playlist())) != 0) {
4783 if (src_comparison) {
4784 pl->get_source_equivalent_regions (region, results);
4786 pl->get_region_list_equivalent_regions (region, results);
4790 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4791 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4792 regions.push_back (marv);
4801 Editor::show_rhythm_ferret ()
4803 if (rhythm_ferret == 0) {
4804 rhythm_ferret = new RhythmFerret(*this);
4807 rhythm_ferret->set_session (_session);
4808 rhythm_ferret->show ();
4809 rhythm_ferret->present ();
4813 Editor::first_idle ()
4815 MessageDialog* dialog = 0;
4817 if (track_views.size() > 1) {
4818 dialog = new MessageDialog (
4820 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4824 ARDOUR_UI::instance()->flush_pending ();
4827 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4831 // first idle adds route children (automation tracks), so we need to redisplay here
4832 _routes->redisplay ();
4839 Editor::_idle_resize (gpointer arg)
4841 return ((Editor*)arg)->idle_resize ();
4845 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4847 if (resize_idle_id < 0) {
4848 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
4849 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
4850 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
4852 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
4853 _pending_resize_amount = 0;
4856 /* make a note of the smallest resulting height, so that we can clamp the
4857 lower limit at TimeAxisView::hSmall */
4859 int32_t min_resulting = INT32_MAX;
4861 _pending_resize_amount += h;
4862 _pending_resize_view = view;
4864 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4866 if (selection->tracks.contains (_pending_resize_view)) {
4867 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4868 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4872 if (min_resulting < 0) {
4877 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4878 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4882 /** Handle pending resizing of tracks */
4884 Editor::idle_resize ()
4886 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4888 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4889 selection->tracks.contains (_pending_resize_view)) {
4891 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4892 if (*i != _pending_resize_view) {
4893 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4898 _pending_resize_amount = 0;
4899 _group_tabs->set_dirty ();
4900 resize_idle_id = -1;
4908 ENSURE_GUI_THREAD (*this, &Editor::located);
4911 playhead_cursor->set_position (_session->audible_frame ());
4912 if (_follow_playhead && !_pending_initial_locate) {
4913 reset_x_origin_to_follow_playhead ();
4917 _pending_locate_request = false;
4918 _pending_initial_locate = false;
4922 Editor::region_view_added (RegionView *)
4924 _summary->set_background_dirty ();
4928 Editor::region_view_removed ()
4930 _summary->set_background_dirty ();
4934 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4936 TrackViewList::const_iterator j = track_views.begin ();
4937 while (j != track_views.end()) {
4938 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4939 if (rtv && rtv->route() == r) {
4950 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4954 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4955 TimeAxisView* tv = axis_view_from_route (*i);
4965 Editor::suspend_route_redisplay ()
4968 _routes->suspend_redisplay();
4973 Editor::resume_route_redisplay ()
4976 _routes->resume_redisplay();
4981 Editor::add_routes (RouteList& routes)
4983 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4985 RouteTimeAxisView *rtv;
4986 list<RouteTimeAxisView*> new_views;
4988 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4989 boost::shared_ptr<Route> route = (*x);
4991 if (route->is_auditioner() || route->is_monitor()) {
4995 DataType dt = route->input()->default_type();
4997 if (dt == ARDOUR::DataType::AUDIO) {
4998 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4999 rtv->set_route (route);
5000 } else if (dt == ARDOUR::DataType::MIDI) {
5001 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5002 rtv->set_route (route);
5004 throw unknown_type();
5007 new_views.push_back (rtv);
5008 track_views.push_back (rtv);
5010 rtv->effective_gain_display ();
5012 if (internal_editing()) {
5013 rtv->enter_internal_edit_mode ();
5015 rtv->leave_internal_edit_mode ();
5018 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5019 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5022 if (new_views.size() > 0) {
5023 _routes->routes_added (new_views);
5024 _summary->routes_added (new_views);
5027 if (show_editor_mixer_when_tracks_arrive) {
5028 show_editor_mixer (true);
5031 editor_list_button.set_sensitive (true);
5035 Editor::timeaxisview_deleted (TimeAxisView *tv)
5037 if (tv == entered_track) {
5041 if (_session && _session->deletion_in_progress()) {
5042 /* the situation is under control */
5046 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5048 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5050 _routes->route_removed (tv);
5052 TimeAxisView::Children c = tv->get_child_list ();
5053 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5054 if (entered_track == i->get()) {
5059 /* remove it from the list of track views */
5061 TrackViewList::iterator i;
5063 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5064 i = track_views.erase (i);
5067 /* update whatever the current mixer strip is displaying, if revelant */
5069 boost::shared_ptr<Route> route;
5072 route = rtav->route ();
5075 if (current_mixer_strip && current_mixer_strip->route() == route) {
5077 TimeAxisView* next_tv;
5079 if (track_views.empty()) {
5081 } else if (i == track_views.end()) {
5082 next_tv = track_views.front();
5089 set_selected_mixer_strip (*next_tv);
5091 /* make the editor mixer strip go away setting the
5092 * button to inactive (which also unticks the menu option)
5095 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5101 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5103 if (apply_to_selection) {
5104 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5106 TrackSelection::iterator j = i;
5109 hide_track_in_display (*i, false);
5114 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5116 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5117 // this will hide the mixer strip
5118 set_selected_mixer_strip (*tv);
5121 _routes->hide_track_in_display (*tv);
5126 Editor::sync_track_view_list_and_routes ()
5128 track_views = TrackViewList (_routes->views ());
5130 _summary->set_dirty ();
5131 _group_tabs->set_dirty ();
5133 return false; // do not call again (until needed)
5137 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5139 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5144 /** Find a RouteTimeAxisView by the ID of its route */
5146 Editor::get_route_view_by_route_id (const PBD::ID& id) const
5148 RouteTimeAxisView* v;
5150 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5151 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5152 if(v->route()->id() == id) {
5162 Editor::fit_route_group (RouteGroup *g)
5164 TrackViewList ts = axis_views_from_routes (g->route_list ());
5169 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5171 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5174 _session->cancel_audition ();
5178 if (_session->is_auditioning()) {
5179 _session->cancel_audition ();
5180 if (r == last_audition_region) {
5185 _session->audition_region (r);
5186 last_audition_region = r;
5191 Editor::hide_a_region (boost::shared_ptr<Region> r)
5193 r->set_hidden (true);
5197 Editor::show_a_region (boost::shared_ptr<Region> r)
5199 r->set_hidden (false);
5203 Editor::audition_region_from_region_list ()
5205 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5209 Editor::hide_region_from_region_list ()
5211 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5215 Editor::show_region_in_region_list ()
5217 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5221 Editor::step_edit_status_change (bool yn)
5224 start_step_editing ();
5226 stop_step_editing ();
5231 Editor::start_step_editing ()
5233 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5237 Editor::stop_step_editing ()
5239 step_edit_connection.disconnect ();
5243 Editor::check_step_edit ()
5245 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5246 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5248 mtv->check_step_edit ();
5252 return true; // do it again, till we stop
5256 Editor::scroll_press (Direction dir)
5258 ++_scroll_callbacks;
5260 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5261 /* delay the first auto-repeat */
5267 scroll_backward (1);
5275 scroll_up_one_track ();
5279 scroll_down_one_track ();
5283 /* do hacky auto-repeat */
5284 if (!_scroll_connection.connected ()) {
5286 _scroll_connection = Glib::signal_timeout().connect (
5287 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5290 _scroll_callbacks = 0;
5297 Editor::scroll_release ()
5299 _scroll_connection.disconnect ();
5302 /** Queue a change for the Editor viewport x origin to follow the playhead */
5304 Editor::reset_x_origin_to_follow_playhead ()
5306 framepos_t const frame = playhead_cursor->current_frame ();
5308 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5310 if (_session->transport_speed() < 0) {
5312 if (frame > (current_page_samples() / 2)) {
5313 center_screen (frame-(current_page_samples()/2));
5315 center_screen (current_page_samples()/2);
5322 if (frame < leftmost_frame) {
5324 if (_session->transport_rolling()) {
5325 /* rolling; end up with the playhead at the right of the page */
5326 l = frame - current_page_samples ();
5328 /* not rolling: end up with the playhead 1/4 of the way along the page */
5329 l = frame - current_page_samples() / 4;
5333 if (_session->transport_rolling()) {
5334 /* rolling: end up with the playhead on the left of the page */
5337 /* not rolling: end up with the playhead 3/4 of the way along the page */
5338 l = frame - 3 * current_page_samples() / 4;
5346 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5352 Editor::super_rapid_screen_update ()
5354 if (!_session || !_session->engine().running()) {
5358 /* METERING / MIXER STRIPS */
5360 /* update track meters, if required */
5361 if (is_mapped() && meters_running) {
5362 RouteTimeAxisView* rtv;
5363 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5364 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5365 rtv->fast_update ();
5370 /* and any current mixer strip */
5371 if (current_mixer_strip) {
5372 current_mixer_strip->fast_update ();
5375 /* PLAYHEAD AND VIEWPORT */
5377 framepos_t const frame = _session->audible_frame();
5379 /* There are a few reasons why we might not update the playhead / viewport stuff:
5381 * 1. we don't update things when there's a pending locate request, otherwise
5382 * when the editor requests a locate there is a chance that this method
5383 * will move the playhead before the locate request is processed, causing
5385 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5386 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5389 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5391 last_update_frame = frame;
5393 if (!_dragging_playhead) {
5394 playhead_cursor->set_position (frame);
5397 if (!_stationary_playhead) {
5399 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5400 /* We only do this if we aren't already
5401 handling a visual change (ie if
5402 pending_visual_change.being_handled is
5403 false) so that these requests don't stack
5404 up there are too many of them to handle in
5407 reset_x_origin_to_follow_playhead ();
5412 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5416 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5417 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5418 if (target <= 0.0) {
5421 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5422 target = (target * 0.15) + (current * 0.85);
5428 set_horizontal_position (current);
5437 Editor::session_going_away ()
5439 _have_idled = false;
5441 _session_connections.drop_connections ();
5443 super_rapid_screen_update_connection.disconnect ();
5445 selection->clear ();
5446 cut_buffer->clear ();
5448 clicked_regionview = 0;
5449 clicked_axisview = 0;
5450 clicked_routeview = 0;
5451 entered_regionview = 0;
5453 last_update_frame = 0;
5456 playhead_cursor->hide ();
5458 /* rip everything out of the list displays */
5462 _route_groups->clear ();
5464 /* do this first so that deleting a track doesn't reset cms to null
5465 and thus cause a leak.
5468 if (current_mixer_strip) {
5469 if (current_mixer_strip->get_parent() != 0) {
5470 global_hpacker.remove (*current_mixer_strip);
5472 delete current_mixer_strip;
5473 current_mixer_strip = 0;
5476 /* delete all trackviews */
5478 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5481 track_views.clear ();
5483 nudge_clock->set_session (0);
5485 editor_list_button.set_active(false);
5486 editor_list_button.set_sensitive(false);
5488 /* clear tempo/meter rulers */
5489 remove_metric_marks ();
5491 clear_marker_display ();
5493 stop_step_editing ();
5495 /* get rid of any existing editor mixer strip */
5497 WindowTitle title(Glib::get_application_name());
5498 title += _("Editor");
5500 set_title (title.get_string());
5502 SessionHandlePtr::session_going_away ();
5507 Editor::show_editor_list (bool yn)
5510 _the_notebook.show ();
5512 _the_notebook.hide ();
5517 Editor::change_region_layering_order (bool from_context_menu)
5519 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5521 if (!clicked_routeview) {
5522 if (layering_order_editor) {
5523 layering_order_editor->hide ();
5528 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5534 boost::shared_ptr<Playlist> pl = track->playlist();
5540 if (layering_order_editor == 0) {
5541 layering_order_editor = new RegionLayeringOrderEditor (*this);
5544 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5545 layering_order_editor->maybe_present ();
5549 Editor::update_region_layering_order_editor ()
5551 if (layering_order_editor && layering_order_editor->is_visible ()) {
5552 change_region_layering_order (true);
5557 Editor::setup_fade_images ()
5559 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5560 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5561 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5562 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5563 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5565 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5566 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5567 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5568 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5569 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5571 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5572 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5573 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5574 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5575 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5577 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5578 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5579 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5580 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5581 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5585 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5587 Editor::action_menu_item (std::string const & name)
5589 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5592 return *manage (a->create_menu_item ());
5596 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5598 EventBox* b = manage (new EventBox);
5599 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5600 Label* l = manage (new Label (name));
5604 _the_notebook.append_page (widget, *b);
5608 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5610 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5611 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5614 if (ev->type == GDK_2BUTTON_PRESS) {
5616 /* double-click on a notebook tab shrinks or expands the notebook */
5618 if (_notebook_shrunk) {
5619 if (pre_notebook_shrink_pane_width) {
5620 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5622 _notebook_shrunk = false;
5624 pre_notebook_shrink_pane_width = edit_pane.get_position();
5626 /* this expands the LHS of the edit pane to cover the notebook
5627 PAGE but leaves the tabs visible.
5629 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5630 _notebook_shrunk = true;
5638 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5640 using namespace Menu_Helpers;
5642 MenuList& items = _control_point_context_menu.items ();
5645 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5646 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5647 if (!can_remove_control_point (item)) {
5648 items.back().set_sensitive (false);
5651 _control_point_context_menu.popup (event->button.button, event->button.time);
5655 Editor::zoom_vertical_modifier_released()
5657 _stepping_axis_view = 0;
5661 Editor::ui_parameter_changed (string parameter)
5663 if (parameter == "icon-set") {
5664 while (!_cursor_stack.empty()) {
5665 _cursor_stack.pop();
5667 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5668 } else if (parameter == "draggable-playhead") {
5669 if (_verbose_cursor) {
5670 playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());