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"
49 #include <glibmm/miscutils.h>
50 #include <glibmm/uriutils.h>
51 #include <gtkmm/image.h>
52 #include <gdkmm/color.h>
53 #include <gdkmm/bitmap.h>
55 #include <gtkmm/menu.h>
56 #include <gtkmm/menuitem.h>
58 #include "gtkmm2ext/bindings.h"
59 #include "gtkmm2ext/grouped_buttons.h"
60 #include "gtkmm2ext/gtk_ui.h"
61 #include "gtkmm2ext/tearoff.h"
62 #include "gtkmm2ext/utils.h"
63 #include "gtkmm2ext/window_title.h"
64 #include "gtkmm2ext/choice.h"
65 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
67 #include "ardour/audio_track.h"
68 #include "ardour/audioengine.h"
69 #include "ardour/audioregion.h"
70 #include "ardour/location.h"
71 #include "ardour/profile.h"
72 #include "ardour/route_group.h"
73 #include "ardour/session_playlists.h"
74 #include "ardour/tempo.h"
75 #include "ardour/utils.h"
77 #include "canvas/debug.h"
78 #include "canvas/text.h"
80 #include "control_protocol/control_protocol.h"
84 #include "analysis_window.h"
85 #include "audio_clock.h"
86 #include "audio_region_view.h"
87 #include "audio_streamview.h"
88 #include "audio_time_axis.h"
89 #include "automation_time_axis.h"
90 #include "bundle_manager.h"
91 #include "crossfade_edit.h"
95 #include "editor_cursors.h"
96 #include "editor_drag.h"
97 #include "editor_group_tabs.h"
98 #include "editor_locations.h"
99 #include "editor_regions.h"
100 #include "editor_route_groups.h"
101 #include "editor_routes.h"
102 #include "editor_snapshots.h"
103 #include "editor_summary.h"
104 #include "global_port_matrix.h"
105 #include "gui_object.h"
106 #include "gui_thread.h"
107 #include "keyboard.h"
109 #include "midi_time_axis.h"
110 #include "mixer_strip.h"
111 #include "mixer_ui.h"
112 #include "mouse_cursors.h"
113 #include "playlist_selector.h"
114 #include "public_editor.h"
115 #include "region_layering_order_editor.h"
116 #include "rgb_macros.h"
117 #include "rhythm_ferret.h"
118 #include "selection.h"
120 #include "tempo_lines.h"
121 #include "time_axis_view.h"
127 using namespace ARDOUR;
130 using namespace Glib;
131 using namespace Gtkmm2ext;
132 using namespace Editing;
134 using PBD::internationalize;
136 using Gtkmm2ext::Keyboard;
138 const double Editor::timebar_height = 15.0;
140 static const gchar *_snap_type_strings[] = {
142 N_("Timecode Frames"),
143 N_("Timecode Seconds"),
144 N_("Timecode Minutes"),
174 static const gchar *_snap_mode_strings[] = {
181 static const gchar *_edit_point_strings[] = {
188 static const gchar *_zoom_focus_strings[] = {
198 #ifdef USE_RUBBERBAND
199 static const gchar *_rb_opt_strings[] = {
202 N_("Balanced multitimbral mixture"),
203 N_("Unpitched percussion with stable notes"),
204 N_("Crisp monophonic instrumental"),
205 N_("Unpitched solo percussion"),
206 N_("Resample without preserving pitch"),
212 pane_size_watcher (Paned* pane)
214 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
218 Quartz: impossible to access
220 so stop that by preventing it from ever getting too narrow. 35
221 pixels is basically a rough guess at the tab width.
226 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
228 gint pos = pane->get_position ();
230 if (pos > max_width_of_lhs) {
231 pane->set_position (max_width_of_lhs);
236 : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
238 /* time display buttons */
239 , minsec_label (_("Mins:Secs"))
240 , bbt_label (_("Bars:Beats"))
241 , timecode_label (_("Timecode"))
242 , samples_label (_("Samples"))
243 , tempo_label (_("Tempo"))
244 , meter_label (_("Meter"))
245 , mark_label (_("Location Markers"))
246 , range_mark_label (_("Range Markers"))
247 , transport_mark_label (_("Loop/Punch Ranges"))
248 , cd_mark_label (_("CD Markers"))
249 , videotl_label (_("Video Timeline"))
250 , edit_packer (4, 4, true)
252 /* the values here don't matter: layout widgets
253 reset them as needed.
256 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
257 , horizontal_adjustment (0.0, 0.0, 1e16)
258 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
260 , controls_layout (unused_adjustment, vertical_adjustment)
262 /* tool bar related */
264 , zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
265 , toolbar_selection_clock_table (2,3)
266 , _mouse_mode_tearoff (0)
267 , automation_mode_button (_("mode"))
271 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
275 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
276 , meters_running(false)
277 , _pending_locate_request (false)
278 , _pending_initial_locate (false)
279 , _last_cut_copy_source_track (0)
281 , _region_selection_change_updates_region_list (true)
282 , _following_mixer_selection (false)
283 , _control_point_toggled_on_press (false)
284 , _stepping_axis_view (0)
288 /* we are a singleton */
290 PublicEditor::_instance = this;
294 selection = new Selection (this);
295 cut_buffer = new Selection (this);
297 clicked_regionview = 0;
298 clicked_axisview = 0;
299 clicked_routeview = 0;
300 clicked_control_point = 0;
301 last_update_frame = 0;
302 pre_press_cursor = 0;
303 _drags = new DragManager (this);
304 current_mixer_strip = 0;
307 snap_type_strings = I18N (_snap_type_strings);
308 snap_mode_strings = I18N (_snap_mode_strings);
309 zoom_focus_strings = I18N (_zoom_focus_strings);
310 edit_point_strings = I18N (_edit_point_strings);
311 #ifdef USE_RUBBERBAND
312 rb_opt_strings = I18N (_rb_opt_strings);
316 build_edit_mode_menu();
317 build_zoom_focus_menu();
318 build_track_count_menu();
319 build_snap_mode_menu();
320 build_snap_type_menu();
321 build_edit_point_menu();
323 snap_threshold = 5.0;
324 bbt_beat_subdivision = 4;
325 _visible_canvas_width = 0;
326 _visible_canvas_height = 0;
327 autoscroll_horizontal_allowed = false;
328 autoscroll_vertical_allowed = false;
333 current_interthread_info = 0;
334 _show_measures = true;
336 show_gain_after_trim = false;
338 have_pending_keyboard_selection = false;
339 _follow_playhead = true;
340 _stationary_playhead = false;
341 editor_ruler_menu = 0;
342 no_ruler_shown_update = false;
344 range_marker_menu = 0;
345 marker_menu_item = 0;
346 tempo_or_meter_marker_menu = 0;
347 transport_marker_menu = 0;
348 new_transport_marker_menu = 0;
349 editor_mixer_strip_width = Wide;
350 show_editor_mixer_when_tracks_arrive = false;
351 region_edit_menu_split_multichannel_item = 0;
352 region_edit_menu_split_item = 0;
355 current_stepping_trackview = 0;
357 entered_regionview = 0;
359 clear_entered_track = false;
362 button_release_can_deselect = true;
363 _dragging_playhead = false;
364 _dragging_edit_point = false;
365 select_new_marker = false;
367 layering_order_editor = 0;
368 no_save_visual = false;
370 within_track_canvas = false;
372 scrubbing_direction = 0;
376 location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
377 location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
378 location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
379 location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
380 location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
382 zoom_focus = ZoomFocusLeft;
383 _edit_point = EditAtMouse;
384 _internal_editing = false;
385 current_canvas_cursor = 0;
386 _visible_track_count = 16;
388 samples_per_pixel = 2048; /* too early to use reset_zoom () */
390 _scroll_callbacks = 0;
392 zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
394 bbt_label.set_name ("EditorRulerLabel");
395 bbt_label.set_size_request (-1, (int)timebar_height);
396 bbt_label.set_alignment (1.0, 0.5);
397 bbt_label.set_padding (5,0);
399 bbt_label.set_no_show_all();
400 minsec_label.set_name ("EditorRulerLabel");
401 minsec_label.set_size_request (-1, (int)timebar_height);
402 minsec_label.set_alignment (1.0, 0.5);
403 minsec_label.set_padding (5,0);
404 minsec_label.hide ();
405 minsec_label.set_no_show_all();
406 timecode_label.set_name ("EditorRulerLabel");
407 timecode_label.set_size_request (-1, (int)timebar_height);
408 timecode_label.set_alignment (1.0, 0.5);
409 timecode_label.set_padding (5,0);
410 timecode_label.hide ();
411 timecode_label.set_no_show_all();
412 samples_label.set_name ("EditorRulerLabel");
413 samples_label.set_size_request (-1, (int)timebar_height);
414 samples_label.set_alignment (1.0, 0.5);
415 samples_label.set_padding (5,0);
416 samples_label.hide ();
417 samples_label.set_no_show_all();
419 tempo_label.set_name ("EditorRulerLabel");
420 tempo_label.set_size_request (-1, (int)timebar_height);
421 tempo_label.set_alignment (1.0, 0.5);
422 tempo_label.set_padding (5,0);
424 tempo_label.set_no_show_all();
426 meter_label.set_name ("EditorRulerLabel");
427 meter_label.set_size_request (-1, (int)timebar_height);
428 meter_label.set_alignment (1.0, 0.5);
429 meter_label.set_padding (5,0);
431 meter_label.set_no_show_all();
433 if (Profile->get_trx()) {
434 mark_label.set_text (_("Markers"));
436 mark_label.set_name ("EditorRulerLabel");
437 mark_label.set_size_request (-1, (int)timebar_height);
438 mark_label.set_alignment (1.0, 0.5);
439 mark_label.set_padding (5,0);
441 mark_label.set_no_show_all();
443 cd_mark_label.set_name ("EditorRulerLabel");
444 cd_mark_label.set_size_request (-1, (int)timebar_height);
445 cd_mark_label.set_alignment (1.0, 0.5);
446 cd_mark_label.set_padding (5,0);
447 cd_mark_label.hide();
448 cd_mark_label.set_no_show_all();
450 videotl_bar_height = 4;
451 videotl_label.set_name ("EditorRulerLabel");
452 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
453 videotl_label.set_alignment (1.0, 0.5);
454 videotl_label.set_padding (5,0);
455 videotl_label.hide();
456 videotl_label.set_no_show_all();
458 range_mark_label.set_name ("EditorRulerLabel");
459 range_mark_label.set_size_request (-1, (int)timebar_height);
460 range_mark_label.set_alignment (1.0, 0.5);
461 range_mark_label.set_padding (5,0);
462 range_mark_label.hide();
463 range_mark_label.set_no_show_all();
465 transport_mark_label.set_name ("EditorRulerLabel");
466 transport_mark_label.set_size_request (-1, (int)timebar_height);
467 transport_mark_label.set_alignment (1.0, 0.5);
468 transport_mark_label.set_padding (5,0);
469 transport_mark_label.hide();
470 transport_mark_label.set_no_show_all();
472 initialize_rulers ();
473 initialize_canvas ();
475 _summary = new EditorSummary (this);
477 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
478 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
480 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
482 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
483 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
485 edit_controls_vbox.set_spacing (0);
486 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
487 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
489 HBox* h = manage (new HBox);
490 _group_tabs = new EditorGroupTabs (this);
491 if (!ARDOUR::Profile->get_trx()) {
492 h->pack_start (*_group_tabs, PACK_SHRINK);
494 h->pack_start (edit_controls_vbox);
495 controls_layout.add (*h);
497 controls_layout.set_name ("EditControlsBase");
498 controls_layout.add_events (Gdk::SCROLL_MASK);
499 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
501 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
502 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
504 _cursors = new MouseCursors;
506 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
508 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
509 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
510 pad_line_1->set_outline_color (0xFF0000FF);
516 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2);
517 time_canvas_vbox.set_size_request (-1, -1);
519 ruler_label_event_box.add (ruler_label_vbox);
520 ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
521 ruler_label_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
523 time_bars_event_box.add (time_bars_vbox);
524 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
525 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
527 time_canvas_event_box.add (time_canvas_vbox);
528 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
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 /* labels for the rulers */
537 edit_packer.attach (ruler_label_event_box, 1, 2, 0, 1, FILL, SHRINK, 0, 0);
538 /* labels for the marker "tracks" (time bars) */
539 edit_packer.attach (time_bars_event_box, 1, 2, 1, 2, FILL, SHRINK, 0, 0);
541 edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0);
543 edit_packer.attach (controls_layout, 0, 2, 2, 3, FILL, FILL|EXPAND, 0, 0);
545 edit_packer.attach (*_track_canvas_viewport, 2, 3, 1, 3, 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 add_notebook_page (_("Regions"), _regions->widget ());
557 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
558 add_notebook_page (_("Snapshots"), _snapshots->widget ());
559 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
560 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
562 _the_notebook.set_show_tabs (true);
563 _the_notebook.set_scrollable (true);
564 _the_notebook.popup_disable ();
565 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
566 _the_notebook.show_all ();
568 _notebook_shrunk = false;
570 editor_summary_pane.pack1(edit_packer);
572 Button* summary_arrows_left_left = manage (new Button);
573 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
574 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
575 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
577 Button* summary_arrows_left_right = manage (new Button);
578 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
579 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
580 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
582 VBox* summary_arrows_left = manage (new VBox);
583 summary_arrows_left->pack_start (*summary_arrows_left_left);
584 summary_arrows_left->pack_start (*summary_arrows_left_right);
586 Button* summary_arrows_right_up = manage (new Button);
587 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
588 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
589 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
591 Button* summary_arrows_right_down = manage (new Button);
592 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
593 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
594 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
596 VBox* summary_arrows_right = manage (new VBox);
597 summary_arrows_right->pack_start (*summary_arrows_right_up);
598 summary_arrows_right->pack_start (*summary_arrows_right_down);
600 Frame* summary_frame = manage (new Frame);
601 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
603 summary_frame->add (*_summary);
604 summary_frame->show ();
606 _summary_hbox.pack_start (*summary_arrows_left, false, false);
607 _summary_hbox.pack_start (*summary_frame, true, true);
608 _summary_hbox.pack_start (*summary_arrows_right, false, false);
610 if (!ARDOUR::Profile->get_trx()) {
611 editor_summary_pane.pack2 (_summary_hbox);
614 edit_pane.pack1 (editor_summary_pane, true, true);
615 if (!ARDOUR::Profile->get_trx()) {
616 edit_pane.pack2 (_the_notebook, false, true);
619 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
621 /* XXX: editor_summary_pane might need similar to the edit_pane */
623 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
625 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
626 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
628 top_hbox.pack_start (toolbar_frame);
630 HBox *hbox = manage (new HBox);
631 hbox->pack_start (edit_pane, true, true);
633 global_vpacker.pack_start (top_hbox, false, false);
634 global_vpacker.pack_start (*hbox, true, true);
636 global_hpacker.pack_start (global_vpacker, true, true);
638 set_name ("EditorWindow");
639 add_accel_group (ActionManager::ui_manager->get_accel_group());
641 status_bar_hpacker.show ();
643 vpacker.pack_end (status_bar_hpacker, false, false);
644 vpacker.pack_end (global_hpacker, true, true);
646 /* register actions now so that set_state() can find them and set toggles/checks etc */
649 /* when we start using our own keybinding system for the editor, this
650 * will be uncommented
656 set_zoom_focus (zoom_focus);
657 set_visible_track_count (_visible_track_count);
658 _snap_type = SnapToBeat;
659 set_snap_to (_snap_type);
660 _snap_mode = SnapOff;
661 set_snap_mode (_snap_mode);
662 set_mouse_mode (MouseObject, true);
663 pre_internal_mouse_mode = MouseObject;
664 pre_internal_snap_type = _snap_type;
665 pre_internal_snap_mode = _snap_mode;
666 internal_snap_type = _snap_type;
667 internal_snap_mode = _snap_mode;
668 set_edit_point_preference (EditAtMouse, true);
670 _playlist_selector = new PlaylistSelector();
671 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
673 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
677 nudge_forward_button.set_name ("nudge button");
678 // nudge_forward_button.add_elements (ArdourButton::Inset);
679 nudge_forward_button.set_image(::get_icon("nudge_right"));
681 nudge_backward_button.set_name ("nudge button");
682 // nudge_backward_button.add_elements (ArdourButton::Inset);
683 nudge_backward_button.set_image(::get_icon("nudge_left"));
685 fade_context_menu.set_name ("ArdourContextMenu");
687 /* icons, titles, WM stuff */
689 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
690 Glib::RefPtr<Gdk::Pixbuf> icon;
692 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
693 window_icons.push_back (icon);
695 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
696 window_icons.push_back (icon);
698 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
699 window_icons.push_back (icon);
701 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
702 window_icons.push_back (icon);
704 if (!window_icons.empty()) {
705 // set_icon_list (window_icons);
706 set_default_icon_list (window_icons);
709 WindowTitle title(Glib::get_application_name());
710 title += _("Editor");
711 set_title (title.get_string());
712 set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
715 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
717 signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
718 signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
720 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
722 /* allow external control surfaces/protocols to do various things */
724 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
725 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
726 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
727 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
728 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
729 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
730 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
731 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
732 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
733 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
734 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
735 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
736 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
737 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
739 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
740 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
741 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
742 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
743 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
745 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
747 /* problematic: has to return a value and thus cannot be x-thread */
749 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
751 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
753 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
755 _ignore_region_action = false;
756 _last_region_menu_was_main = false;
757 _popup_region_menu_item = 0;
759 _show_marker_lines = false;
760 _over_region_trim_target = false;
762 /* Button bindings */
764 button_bindings = new Bindings;
766 XMLNode* node = button_settings();
768 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
769 button_bindings->load (**i);
776 setup_fade_images ();
781 delete button_bindings;
783 delete _route_groups;
784 delete _track_canvas_viewport;
789 Editor::button_settings () const
791 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
792 XMLNode* node = find_named_node (*settings, X_("Buttons"));
795 node = new XMLNode (X_("Buttons"));
802 Editor::add_toplevel_controls (Container& cont)
804 vpacker.pack_start (cont, false, false);
809 Editor::get_smart_mode () const
811 return ( (current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active() );
815 Editor::catch_vanishing_regionview (RegionView *rv)
817 /* note: the selection will take care of the vanishing
818 audioregionview by itself.
821 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
825 if (clicked_regionview == rv) {
826 clicked_regionview = 0;
829 if (entered_regionview == rv) {
830 set_entered_regionview (0);
833 if (!_all_region_actions_sensitized) {
834 sensitize_all_region_actions (true);
837 _over_region_trim_target = false;
841 Editor::set_entered_regionview (RegionView* rv)
843 if (rv == entered_regionview) {
847 if (entered_regionview) {
848 entered_regionview->exited ();
851 if ((entered_regionview = rv) != 0) {
852 entered_regionview->entered (internal_editing ());
855 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
856 /* This RegionView entry might have changed what region actions
857 are allowed, so sensitize them all in case a key is pressed.
859 sensitize_all_region_actions (true);
864 Editor::set_entered_track (TimeAxisView* tav)
867 entered_track->exited ();
870 if ((entered_track = tav) != 0) {
871 entered_track->entered ();
876 Editor::show_window ()
878 if (!is_visible ()) {
881 /* XXX: this is a bit unfortunate; it would probably
882 be nicer if we could just call show () above rather
883 than needing the show_all ()
886 /* re-hide stuff if necessary */
887 editor_list_button_toggled ();
888 parameter_changed ("show-summary");
889 parameter_changed ("show-group-tabs");
890 parameter_changed ("show-zoom-tools");
892 /* now reset all audio_time_axis heights, because widgets might need
898 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
899 tv = (static_cast<TimeAxisView*>(*i));
903 if (current_mixer_strip) {
904 current_mixer_strip->hide_things ();
905 current_mixer_strip->parameter_changed ("mixer-strip-visibility");
913 Editor::instant_save ()
915 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
920 _session->add_instant_xml(get_state());
922 Config->add_instant_xml(get_state());
927 Editor::zoom_adjustment_changed ()
933 framecnt_t fpu = llrintf (zoom_range_clock->current_duration() / _visible_canvas_width);
934 bool clamped = clamp_samples_per_pixel (fpu);
937 zoom_range_clock->set ((framepos_t) floor (fpu * _visible_canvas_width));
944 Editor::control_vertical_zoom_in_all ()
946 tav_zoom_smooth (false, true);
950 Editor::control_vertical_zoom_out_all ()
952 tav_zoom_smooth (true, true);
956 Editor::control_vertical_zoom_in_selected ()
958 tav_zoom_smooth (false, false);
962 Editor::control_vertical_zoom_out_selected ()
964 tav_zoom_smooth (true, false);
968 Editor::control_view (uint32_t view)
970 goto_visual_state (view);
974 Editor::control_unselect ()
976 selection->clear_tracks ();
980 Editor::control_select (uint32_t rid, Selection::Operation op)
982 /* handles the (static) signal from the ControlProtocol class that
983 * requests setting the selected track to a given RID
990 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
996 TimeAxisView* tav = axis_view_from_route (r);
1000 case Selection::Add:
1001 selection->add (tav);
1003 case Selection::Toggle:
1004 selection->toggle (tav);
1006 case Selection::Extend:
1008 case Selection::Set:
1009 selection->set (tav);
1013 selection->clear_tracks ();
1018 Editor::control_step_tracks_up ()
1020 scroll_tracks_up_line ();
1024 Editor::control_step_tracks_down ()
1026 scroll_tracks_down_line ();
1030 Editor::control_scroll (float fraction)
1032 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1038 double step = fraction * current_page_samples();
1041 _control_scroll_target is an optional<T>
1043 it acts like a pointer to an framepos_t, with
1044 a operator conversion to boolean to check
1045 that it has a value could possibly use
1046 playhead_cursor->current_frame to store the
1047 value and a boolean in the class to know
1048 when it's out of date
1051 if (!_control_scroll_target) {
1052 _control_scroll_target = _session->transport_frame();
1053 _dragging_playhead = true;
1056 if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
1057 *_control_scroll_target = 0;
1058 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1059 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1061 *_control_scroll_target += (framepos_t) floor (step);
1064 /* move visuals, we'll catch up with it later */
1066 playhead_cursor->set_position (*_control_scroll_target);
1067 UpdateAllTransportClocks (*_control_scroll_target);
1069 if (*_control_scroll_target > (current_page_samples() / 2)) {
1070 /* try to center PH in window */
1071 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1077 Now we do a timeout to actually bring the session to the right place
1078 according to the playhead. This is to avoid reading disk buffers on every
1079 call to control_scroll, which is driven by ScrollTimeline and therefore
1080 probably by a control surface wheel which can generate lots of events.
1082 /* cancel the existing timeout */
1084 control_scroll_connection.disconnect ();
1086 /* add the next timeout */
1088 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1092 Editor::deferred_control_scroll (framepos_t /*target*/)
1094 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1095 // reset for next stream
1096 _control_scroll_target = boost::none;
1097 _dragging_playhead = false;
1102 Editor::access_action (std::string action_group, std::string action_item)
1108 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1111 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1119 Editor::on_realize ()
1121 Window::on_realize ();
1126 Editor::map_position_change (framepos_t frame)
1128 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1130 if (_session == 0) {
1134 if (_follow_playhead) {
1135 center_screen (frame);
1138 playhead_cursor->set_position (frame);
1142 Editor::center_screen (framepos_t frame)
1144 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1146 /* if we're off the page, then scroll.
1149 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1150 center_screen_internal (frame, page);
1155 Editor::center_screen_internal (framepos_t frame, float page)
1160 frame -= (framepos_t) page;
1165 reset_x_origin (frame);
1170 Editor::update_title ()
1172 ENSURE_GUI_THREAD (*this, &Editor::update_title)
1175 bool dirty = _session->dirty();
1177 string session_name;
1179 if (_session->snap_name() != _session->name()) {
1180 session_name = _session->snap_name();
1182 session_name = _session->name();
1186 session_name = "*" + session_name;
1189 WindowTitle title(session_name);
1190 title += Glib::get_application_name();
1191 set_title (title.get_string());
1193 /* ::session_going_away() will have taken care of it */
1198 Editor::set_session (Session *t)
1200 SessionHandlePtr::set_session (t);
1206 zoom_range_clock->set_session (_session);
1207 _playlist_selector->set_session (_session);
1208 nudge_clock->set_session (_session);
1209 _summary->set_session (_session);
1210 _group_tabs->set_session (_session);
1211 _route_groups->set_session (_session);
1212 _regions->set_session (_session);
1213 _snapshots->set_session (_session);
1214 _routes->set_session (_session);
1215 _locations->set_session (_session);
1217 if (rhythm_ferret) {
1218 rhythm_ferret->set_session (_session);
1221 if (analysis_window) {
1222 analysis_window->set_session (_session);
1226 sfbrowser->set_session (_session);
1229 compute_fixed_ruler_scale ();
1231 /* Make sure we have auto loop and auto punch ranges */
1233 Location* loc = _session->locations()->auto_loop_location();
1235 loc->set_name (_("Loop"));
1238 loc = _session->locations()->auto_punch_location();
1241 loc->set_name (_("Punch"));
1244 refresh_location_display ();
1246 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1247 the selected Marker; this needs the LocationMarker list to be available.
1249 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1250 set_state (*node, Stateful::loading_state_version);
1252 /* catch up with the playhead */
1254 _session->request_locate (playhead_cursor->current_frame ());
1255 _pending_initial_locate = true;
1259 /* These signals can all be emitted by a non-GUI thread. Therefore the
1260 handlers for them must not attempt to directly interact with the GUI,
1261 but use PBD::Signal<T>::connect() which accepts an event loop
1262 ("context") where the handler will be asked to run.
1265 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1266 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1267 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1268 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1269 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1270 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1271 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1272 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1273 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1274 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1275 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1276 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1277 _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1278 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1280 playhead_cursor->show ();
1282 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1283 Config->map_parameters (pc);
1284 _session->config.map_parameters (pc);
1286 restore_ruler_visibility ();
1287 //tempo_map_changed (PropertyChange (0));
1288 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1290 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1291 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1294 super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1295 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1298 switch (_snap_type) {
1299 case SnapToRegionStart:
1300 case SnapToRegionEnd:
1301 case SnapToRegionSync:
1302 case SnapToRegionBoundary:
1303 build_region_boundary_cache ();
1310 /* register for undo history */
1311 _session->register_with_memento_command_factory(id(), this);
1313 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1315 start_updating_meters ();
1319 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1321 if (a->get_name() == "RegionMenu") {
1322 /* When the main menu's region menu is opened, we setup the actions so that they look right
1323 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1324 so we resensitize all region actions when the entered regionview or the region selection
1325 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1326 happens after the region context menu is opened. So we set a flag here, too.
1330 sensitize_the_right_region_actions ();
1331 _last_region_menu_was_main = true;
1336 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1338 using namespace Menu_Helpers;
1340 void (Editor::*emf)(FadeShape);
1341 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1344 images = &_xfade_in_images;
1345 emf = &Editor::set_fade_in_shape;
1347 images = &_xfade_out_images;
1348 emf = &Editor::set_fade_out_shape;
1353 _("Linear (for highly correlated material)"),
1354 *(*images)[FadeLinear],
1355 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1359 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1363 _("Constant power"),
1364 *(*images)[FadeConstantPower],
1365 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1368 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1373 *(*images)[FadeSymmetric],
1374 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1378 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1383 *(*images)[FadeSlow],
1384 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1387 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1392 *(*images)[FadeFast],
1393 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1396 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1399 /** Pop up a context menu for when the user clicks on a start crossfade */
1401 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1403 using namespace Menu_Helpers;
1404 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1407 MenuList& items (xfade_in_context_menu.items());
1410 if (arv->audio_region()->fade_in_active()) {
1411 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1413 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1416 items.push_back (SeparatorElem());
1417 fill_xfade_menu (items, true);
1419 xfade_in_context_menu.popup (button, time);
1422 /** Pop up a context menu for when the user clicks on an end crossfade */
1424 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1426 using namespace Menu_Helpers;
1427 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1430 MenuList& items (xfade_out_context_menu.items());
1433 if (arv->audio_region()->fade_out_active()) {
1434 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1436 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1439 items.push_back (SeparatorElem());
1440 fill_xfade_menu (items, false);
1442 xfade_out_context_menu.popup (button, time);
1446 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1448 using namespace Menu_Helpers;
1449 Menu* (Editor::*build_menu_function)();
1452 switch (item_type) {
1454 case RegionViewName:
1455 case RegionViewNameHighlight:
1456 case LeftFrameHandle:
1457 case RightFrameHandle:
1458 if (with_selection) {
1459 build_menu_function = &Editor::build_track_selection_context_menu;
1461 build_menu_function = &Editor::build_track_region_context_menu;
1466 if (with_selection) {
1467 build_menu_function = &Editor::build_track_selection_context_menu;
1469 build_menu_function = &Editor::build_track_context_menu;
1474 if (clicked_routeview->track()) {
1475 build_menu_function = &Editor::build_track_context_menu;
1477 build_menu_function = &Editor::build_track_bus_context_menu;
1482 /* probably shouldn't happen but if it does, we don't care */
1486 menu = (this->*build_menu_function)();
1487 menu->set_name ("ArdourContextMenu");
1489 /* now handle specific situations */
1491 switch (item_type) {
1493 case RegionViewName:
1494 case RegionViewNameHighlight:
1495 case LeftFrameHandle:
1496 case RightFrameHandle:
1497 if (!with_selection) {
1498 if (region_edit_menu_split_item) {
1499 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1500 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1502 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1505 if (region_edit_menu_split_multichannel_item) {
1506 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1507 region_edit_menu_split_multichannel_item->set_sensitive (true);
1509 region_edit_menu_split_multichannel_item->set_sensitive (false);
1522 /* probably shouldn't happen but if it does, we don't care */
1526 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1528 /* Bounce to disk */
1530 using namespace Menu_Helpers;
1531 MenuList& edit_items = menu->items();
1533 edit_items.push_back (SeparatorElem());
1535 switch (clicked_routeview->audio_track()->freeze_state()) {
1536 case AudioTrack::NoFreeze:
1537 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1540 case AudioTrack::Frozen:
1541 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1544 case AudioTrack::UnFrozen:
1545 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1551 if (item_type == StreamItem && clicked_routeview) {
1552 clicked_routeview->build_underlay_menu(menu);
1555 /* When the region menu is opened, we setup the actions so that they look right
1558 sensitize_the_right_region_actions ();
1559 _last_region_menu_was_main = false;
1561 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1562 menu->popup (button, time);
1566 Editor::build_track_context_menu ()
1568 using namespace Menu_Helpers;
1570 MenuList& edit_items = track_context_menu.items();
1573 add_dstream_context_items (edit_items);
1574 return &track_context_menu;
1578 Editor::build_track_bus_context_menu ()
1580 using namespace Menu_Helpers;
1582 MenuList& edit_items = track_context_menu.items();
1585 add_bus_context_items (edit_items);
1586 return &track_context_menu;
1590 Editor::build_track_region_context_menu ()
1592 using namespace Menu_Helpers;
1593 MenuList& edit_items = track_region_context_menu.items();
1596 /* we've just cleared the track region context menu, so the menu that these
1597 two items were on will have disappeared; stop them dangling.
1599 region_edit_menu_split_item = 0;
1600 region_edit_menu_split_multichannel_item = 0;
1602 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1605 boost::shared_ptr<Track> tr;
1606 boost::shared_ptr<Playlist> pl;
1608 if ((tr = rtv->track())) {
1609 add_region_context_items (edit_items, tr);
1613 add_dstream_context_items (edit_items);
1615 return &track_region_context_menu;
1619 Editor::analyze_region_selection ()
1621 if (analysis_window == 0) {
1622 analysis_window = new AnalysisWindow();
1625 analysis_window->set_session(_session);
1627 analysis_window->show_all();
1630 analysis_window->set_regionmode();
1631 analysis_window->analyze();
1633 analysis_window->present();
1637 Editor::analyze_range_selection()
1639 if (analysis_window == 0) {
1640 analysis_window = new AnalysisWindow();
1643 analysis_window->set_session(_session);
1645 analysis_window->show_all();
1648 analysis_window->set_rangemode();
1649 analysis_window->analyze();
1651 analysis_window->present();
1655 Editor::build_track_selection_context_menu ()
1657 using namespace Menu_Helpers;
1658 MenuList& edit_items = track_selection_context_menu.items();
1659 edit_items.clear ();
1661 add_selection_context_items (edit_items);
1662 // edit_items.push_back (SeparatorElem());
1663 // add_dstream_context_items (edit_items);
1665 return &track_selection_context_menu;
1669 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1671 using namespace Menu_Helpers;
1673 /* OK, stick the region submenu at the top of the list, and then add
1677 RegionSelection rs = get_regions_from_selection_and_entered ();
1679 string::size_type pos = 0;
1680 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1682 /* we have to hack up the region name because "_" has a special
1683 meaning for menu titles.
1686 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1687 menu_item_name.replace (pos, 1, "__");
1691 if (_popup_region_menu_item == 0) {
1692 _popup_region_menu_item = new MenuItem (menu_item_name);
1693 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1694 _popup_region_menu_item->show ();
1696 _popup_region_menu_item->set_label (menu_item_name);
1699 const framepos_t position = get_preferred_edit_position (false, true);
1701 edit_items.push_back (*_popup_region_menu_item);
1702 if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1703 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1705 edit_items.push_back (SeparatorElem());
1708 /** Add context menu items relevant to selection ranges.
1709 * @param edit_items List to add the items to.
1712 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1714 using namespace Menu_Helpers;
1716 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1717 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1719 edit_items.push_back (SeparatorElem());
1720 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1722 edit_items.push_back (SeparatorElem());
1724 edit_items.push_back (
1726 _("Move Range Start to Previous Region Boundary"),
1727 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1731 edit_items.push_back (
1733 _("Move Range Start to Next Region Boundary"),
1734 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1738 edit_items.push_back (
1740 _("Move Range End to Previous Region Boundary"),
1741 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1745 edit_items.push_back (
1747 _("Move Range End to Next Region Boundary"),
1748 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1752 edit_items.push_back (SeparatorElem());
1753 edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1754 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1756 edit_items.push_back (SeparatorElem());
1757 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1759 edit_items.push_back (SeparatorElem());
1760 edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1761 edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1763 edit_items.push_back (SeparatorElem());
1764 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1766 edit_items.push_back (SeparatorElem());
1767 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1768 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1769 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1771 edit_items.push_back (SeparatorElem());
1772 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1773 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1774 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1775 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1776 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1777 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1778 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1784 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1786 using namespace Menu_Helpers;
1790 Menu *play_menu = manage (new Menu);
1791 MenuList& play_items = play_menu->items();
1792 play_menu->set_name ("ArdourContextMenu");
1794 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1795 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1796 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1797 play_items.push_back (SeparatorElem());
1798 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1800 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1804 Menu *select_menu = manage (new Menu);
1805 MenuList& select_items = select_menu->items();
1806 select_menu->set_name ("ArdourContextMenu");
1808 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1809 select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
1810 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1811 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1812 select_items.push_back (SeparatorElem());
1813 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1814 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1815 select_items.push_back (SeparatorElem());
1816 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1817 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1818 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1819 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1820 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1821 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1822 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1824 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1828 Menu *cutnpaste_menu = manage (new Menu);
1829 MenuList& cutnpaste_items = cutnpaste_menu->items();
1830 cutnpaste_menu->set_name ("ArdourContextMenu");
1832 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1833 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1834 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1836 cutnpaste_items.push_back (SeparatorElem());
1838 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1839 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1841 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1843 /* Adding new material */
1845 edit_items.push_back (SeparatorElem());
1846 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1847 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1851 Menu *nudge_menu = manage (new Menu());
1852 MenuList& nudge_items = nudge_menu->items();
1853 nudge_menu->set_name ("ArdourContextMenu");
1855 edit_items.push_back (SeparatorElem());
1856 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1857 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1858 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1859 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1861 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1865 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1867 using namespace Menu_Helpers;
1871 Menu *play_menu = manage (new Menu);
1872 MenuList& play_items = play_menu->items();
1873 play_menu->set_name ("ArdourContextMenu");
1875 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1876 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1877 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1881 Menu *select_menu = manage (new Menu);
1882 MenuList& select_items = select_menu->items();
1883 select_menu->set_name ("ArdourContextMenu");
1885 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1886 select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
1887 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1888 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1889 select_items.push_back (SeparatorElem());
1890 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1891 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1892 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1893 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1895 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1899 Menu *cutnpaste_menu = manage (new Menu);
1900 MenuList& cutnpaste_items = cutnpaste_menu->items();
1901 cutnpaste_menu->set_name ("ArdourContextMenu");
1903 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1904 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1905 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1907 Menu *nudge_menu = manage (new Menu());
1908 MenuList& nudge_items = nudge_menu->items();
1909 nudge_menu->set_name ("ArdourContextMenu");
1911 edit_items.push_back (SeparatorElem());
1912 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1913 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1914 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1915 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1917 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1921 Editor::snap_type() const
1927 Editor::snap_mode() const
1933 Editor::set_snap_to (SnapType st)
1935 unsigned int snap_ind = (unsigned int)st;
1939 if (snap_ind > snap_type_strings.size() - 1) {
1941 _snap_type = (SnapType)snap_ind;
1944 string str = snap_type_strings[snap_ind];
1946 if (str != snap_type_selector.get_text()) {
1947 snap_type_selector.set_text (str);
1952 switch (_snap_type) {
1953 case SnapToBeatDiv128:
1954 case SnapToBeatDiv64:
1955 case SnapToBeatDiv32:
1956 case SnapToBeatDiv28:
1957 case SnapToBeatDiv24:
1958 case SnapToBeatDiv20:
1959 case SnapToBeatDiv16:
1960 case SnapToBeatDiv14:
1961 case SnapToBeatDiv12:
1962 case SnapToBeatDiv10:
1963 case SnapToBeatDiv8:
1964 case SnapToBeatDiv7:
1965 case SnapToBeatDiv6:
1966 case SnapToBeatDiv5:
1967 case SnapToBeatDiv4:
1968 case SnapToBeatDiv3:
1969 case SnapToBeatDiv2: {
1970 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
1971 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
1973 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
1974 current_bbt_points_begin, current_bbt_points_end);
1975 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
1976 current_bbt_points_begin, current_bbt_points_end);
1977 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
1981 case SnapToRegionStart:
1982 case SnapToRegionEnd:
1983 case SnapToRegionSync:
1984 case SnapToRegionBoundary:
1985 build_region_boundary_cache ();
1993 SnapChanged (); /* EMIT SIGNAL */
1997 Editor::set_snap_mode (SnapMode mode)
1999 string str = snap_mode_strings[(int)mode];
2001 if (_internal_editing) {
2002 internal_snap_mode = mode;
2004 pre_internal_snap_mode = mode;
2009 if (str != snap_mode_selector.get_text ()) {
2010 snap_mode_selector.set_text (str);
2016 Editor::set_edit_point_preference (EditPoint ep, bool force)
2018 bool changed = (_edit_point != ep);
2021 string str = edit_point_strings[(int)ep];
2023 if (str != edit_point_selector.get_text ()) {
2024 edit_point_selector.set_text (str);
2027 set_canvas_cursor ();
2029 if (!force && !changed) {
2033 const char* action=NULL;
2035 switch (_edit_point) {
2036 case EditAtPlayhead:
2037 action = "edit-at-playhead";
2039 case EditAtSelectedMarker:
2040 action = "edit-at-marker";
2043 action = "edit-at-mouse";
2047 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2049 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2053 bool in_track_canvas;
2055 if (!mouse_frame (foo, in_track_canvas)) {
2056 in_track_canvas = false;
2059 reset_canvas_action_sensitivity (in_track_canvas);
2065 Editor::set_state (const XMLNode& node, int /*version*/)
2067 const XMLProperty* prop;
2074 g.base_width = default_width;
2075 g.base_height = default_height;
2079 if ((geometry = find_named_node (node, "geometry")) != 0) {
2083 if ((prop = geometry->property("x_size")) == 0) {
2084 prop = geometry->property ("x-size");
2087 g.base_width = atoi(prop->value());
2089 if ((prop = geometry->property("y_size")) == 0) {
2090 prop = geometry->property ("y-size");
2093 g.base_height = atoi(prop->value());
2096 if ((prop = geometry->property ("x_pos")) == 0) {
2097 prop = geometry->property ("x-pos");
2100 x = atoi (prop->value());
2103 if ((prop = geometry->property ("y_pos")) == 0) {
2104 prop = geometry->property ("y-pos");
2107 y = atoi (prop->value());
2111 set_default_size (g.base_width, g.base_height);
2114 if (_session && (prop = node.property ("playhead"))) {
2116 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2117 playhead_cursor->set_position (pos);
2119 playhead_cursor->set_position (0);
2122 if ((prop = node.property ("mixer-width"))) {
2123 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2126 if ((prop = node.property ("zoom-focus"))) {
2127 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2130 if ((prop = node.property ("zoom"))) {
2131 /* older versions of ardour used floating point samples_per_pixel */
2132 double f = PBD::atof (prop->value());
2133 reset_zoom (llrintf (f));
2135 reset_zoom (samples_per_pixel);
2138 if ((prop = node.property ("visible-track-count"))) {
2139 set_visible_track_count (PBD::atoi (prop->value()));
2142 if ((prop = node.property ("snap-to"))) {
2143 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2146 if ((prop = node.property ("snap-mode"))) {
2147 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2150 if ((prop = node.property ("internal-snap-to"))) {
2151 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2154 if ((prop = node.property ("internal-snap-mode"))) {
2155 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2158 if ((prop = node.property ("pre-internal-snap-to"))) {
2159 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2163 if ((prop = node.property ("pre-internal-snap-mode"))) {
2164 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2167 if ((prop = node.property ("mouse-mode"))) {
2168 MouseMode m = str2mousemode(prop->value());
2169 set_mouse_mode (m, true);
2171 set_mouse_mode (MouseObject, true);
2174 if ((prop = node.property ("left-frame")) != 0) {
2176 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2180 reset_x_origin (pos);
2184 if ((prop = node.property ("y-origin")) != 0) {
2185 reset_y_origin (atof (prop->value ()));
2188 if ((prop = node.property ("internal-edit"))) {
2189 bool yn = string_is_affirmative (prop->value());
2190 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2192 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2193 tact->set_active (!yn);
2194 tact->set_active (yn);
2198 if ((prop = node.property ("join-object-range"))) {
2199 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2200 bool yn = string_is_affirmative (prop->value());
2202 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2203 tact->set_active (!yn);
2204 tact->set_active (yn);
2206 set_mouse_mode(mouse_mode, true);
2209 if ((prop = node.property ("edit-point"))) {
2210 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2213 if ((prop = node.property ("show-measures"))) {
2214 bool yn = string_is_affirmative (prop->value());
2215 _show_measures = yn;
2216 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2218 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2219 /* do it twice to force the change */
2220 tact->set_active (!yn);
2221 tact->set_active (yn);
2225 if ((prop = node.property ("follow-playhead"))) {
2226 bool yn = string_is_affirmative (prop->value());
2227 set_follow_playhead (yn);
2228 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2230 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2231 if (tact->get_active() != yn) {
2232 tact->set_active (yn);
2237 if ((prop = node.property ("stationary-playhead"))) {
2238 bool yn = string_is_affirmative (prop->value());
2239 set_stationary_playhead (yn);
2240 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2242 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2243 if (tact->get_active() != yn) {
2244 tact->set_active (yn);
2249 if ((prop = node.property ("region-list-sort-type"))) {
2250 RegionListSortType st;
2251 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2254 if ((prop = node.property ("show-editor-mixer"))) {
2256 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2259 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2260 bool yn = string_is_affirmative (prop->value());
2262 /* do it twice to force the change */
2264 tact->set_active (!yn);
2265 tact->set_active (yn);
2268 if ((prop = node.property ("show-editor-list"))) {
2270 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2273 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2274 bool yn = string_is_affirmative (prop->value());
2276 /* do it twice to force the change */
2278 tact->set_active (!yn);
2279 tact->set_active (yn);
2282 if ((prop = node.property (X_("editor-list-page")))) {
2283 _the_notebook.set_current_page (atoi (prop->value ()));
2286 if ((prop = node.property (X_("show-marker-lines")))) {
2287 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2289 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2290 bool yn = string_is_affirmative (prop->value ());
2292 tact->set_active (!yn);
2293 tact->set_active (yn);
2296 XMLNodeList children = node.children ();
2297 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2298 selection->set_state (**i, Stateful::current_state_version);
2299 _regions->set_state (**i);
2302 if ((prop = node.property ("maximised"))) {
2303 bool yn = string_is_affirmative (prop->value());
2304 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2306 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2307 bool fs = tact && tact->get_active();
2309 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2313 if ((prop = node.property ("nudge-clock-value"))) {
2315 sscanf (prop->value().c_str(), "%" PRId64, &f);
2316 nudge_clock->set (f);
2318 nudge_clock->set_mode (AudioClock::Timecode);
2319 nudge_clock->set (_session->frame_rate() * 5, true);
2326 Editor::get_state ()
2328 XMLNode* node = new XMLNode ("Editor");
2331 id().print (buf, sizeof (buf));
2332 node->add_property ("id", buf);
2334 if (is_realized()) {
2335 Glib::RefPtr<Gdk::Window> win = get_window();
2337 int x, y, width, height;
2338 win->get_root_origin(x, y);
2339 win->get_size(width, height);
2341 XMLNode* geometry = new XMLNode ("geometry");
2343 snprintf(buf, sizeof(buf), "%d", width);
2344 geometry->add_property("x-size", string(buf));
2345 snprintf(buf, sizeof(buf), "%d", height);
2346 geometry->add_property("y-size", string(buf));
2347 snprintf(buf, sizeof(buf), "%d", x);
2348 geometry->add_property("x-pos", string(buf));
2349 snprintf(buf, sizeof(buf), "%d", y);
2350 geometry->add_property("y-pos", string(buf));
2351 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2352 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2353 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2354 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2355 geometry->add_property("edit-vertical-pane-pos", string(buf));
2357 node->add_child_nocopy (*geometry);
2360 maybe_add_mixer_strip_width (*node);
2362 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2364 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2365 node->add_property ("zoom", buf);
2366 node->add_property ("snap-to", enum_2_string (_snap_type));
2367 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2368 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2369 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2370 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2371 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2372 node->add_property ("edit-point", enum_2_string (_edit_point));
2373 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2374 node->add_property ("visible-track-count", buf);
2376 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2377 node->add_property ("playhead", buf);
2378 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2379 node->add_property ("left-frame", buf);
2380 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2381 node->add_property ("y-origin", buf);
2383 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2384 node->add_property ("maximised", _maximised ? "yes" : "no");
2385 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2386 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2387 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2388 node->add_property ("mouse-mode", enum2str(mouse_mode));
2389 node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2390 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2392 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2394 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2395 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2398 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2400 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2401 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2404 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2405 node->add_property (X_("editor-list-page"), buf);
2407 if (button_bindings) {
2408 XMLNode* bb = new XMLNode (X_("Buttons"));
2409 button_bindings->save (*bb);
2410 node->add_child_nocopy (*bb);
2413 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2415 node->add_child_nocopy (selection->get_state ());
2416 node->add_child_nocopy (_regions->get_state ());
2418 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2419 node->add_property ("nudge-clock-value", buf);
2426 /** @param y y offset from the top of all trackviews.
2427 * @return pair: TimeAxisView that y is over, layer index.
2428 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2429 * in stacked or expanded region display mode, otherwise 0.
2431 std::pair<TimeAxisView *, double>
2432 Editor::trackview_by_y_position (double y)
2434 for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2436 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2442 return std::make_pair ( (TimeAxisView *) 0, 0);
2445 /** Snap a position to the grid, if appropriate, taking into account current
2446 * grid settings and also the state of any snap modifier keys that may be pressed.
2447 * @param start Position to snap.
2448 * @param event Event to get current key modifier information from, or 0.
2451 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2453 if (!_session || !event) {
2457 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2458 if (_snap_mode == SnapOff) {
2459 snap_to_internal (start, direction, for_mark);
2462 if (_snap_mode != SnapOff) {
2463 snap_to_internal (start, direction, for_mark);
2469 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2471 if (!_session || _snap_mode == SnapOff) {
2475 snap_to_internal (start, direction, for_mark);
2479 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2481 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2482 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2484 switch (_snap_type) {
2485 case SnapToTimecodeFrame:
2486 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2487 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2489 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2493 case SnapToTimecodeSeconds:
2494 if (_session->config.get_timecode_offset_negative()) {
2495 start += _session->config.get_timecode_offset ();
2497 start -= _session->config.get_timecode_offset ();
2499 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2500 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2502 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2505 if (_session->config.get_timecode_offset_negative()) {
2506 start -= _session->config.get_timecode_offset ();
2508 start += _session->config.get_timecode_offset ();
2512 case SnapToTimecodeMinutes:
2513 if (_session->config.get_timecode_offset_negative()) {
2514 start += _session->config.get_timecode_offset ();
2516 start -= _session->config.get_timecode_offset ();
2518 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2519 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2521 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2523 if (_session->config.get_timecode_offset_negative()) {
2524 start -= _session->config.get_timecode_offset ();
2526 start += _session->config.get_timecode_offset ();
2530 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2536 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2538 const framepos_t one_second = _session->frame_rate();
2539 const framepos_t one_minute = _session->frame_rate() * 60;
2540 framepos_t presnap = start;
2544 switch (_snap_type) {
2545 case SnapToTimecodeFrame:
2546 case SnapToTimecodeSeconds:
2547 case SnapToTimecodeMinutes:
2548 return timecode_snap_to_internal (start, direction, for_mark);
2551 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2552 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2554 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2559 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2560 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2562 start = (framepos_t) floor ((double) start / one_second) * one_second;
2567 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2568 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2570 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2575 start = _session->tempo_map().round_to_bar (start, direction);
2579 start = _session->tempo_map().round_to_beat (start, direction);
2582 case SnapToBeatDiv128:
2583 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2585 case SnapToBeatDiv64:
2586 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2588 case SnapToBeatDiv32:
2589 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2591 case SnapToBeatDiv28:
2592 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2594 case SnapToBeatDiv24:
2595 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2597 case SnapToBeatDiv20:
2598 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2600 case SnapToBeatDiv16:
2601 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2603 case SnapToBeatDiv14:
2604 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2606 case SnapToBeatDiv12:
2607 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2609 case SnapToBeatDiv10:
2610 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2612 case SnapToBeatDiv8:
2613 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2615 case SnapToBeatDiv7:
2616 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2618 case SnapToBeatDiv6:
2619 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2621 case SnapToBeatDiv5:
2622 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2624 case SnapToBeatDiv4:
2625 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2627 case SnapToBeatDiv3:
2628 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2630 case SnapToBeatDiv2:
2631 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2639 _session->locations()->marks_either_side (start, before, after);
2641 if (before == max_framepos && after == max_framepos) {
2642 /* No marks to snap to, so just don't snap */
2644 } else if (before == max_framepos) {
2646 } else if (after == max_framepos) {
2648 } else if (before != max_framepos && after != max_framepos) {
2649 /* have before and after */
2650 if ((start - before) < (after - start)) {
2659 case SnapToRegionStart:
2660 case SnapToRegionEnd:
2661 case SnapToRegionSync:
2662 case SnapToRegionBoundary:
2663 if (!region_boundary_cache.empty()) {
2665 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2666 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2668 if (direction > 0) {
2669 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2671 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2674 if (next != region_boundary_cache.begin ()) {
2679 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2680 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2682 if (start > (p + n) / 2) {
2691 switch (_snap_mode) {
2697 if (presnap > start) {
2698 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2702 } else if (presnap < start) {
2703 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2709 /* handled at entry */
2717 Editor::setup_toolbar ()
2719 HBox* mode_box = manage(new HBox);
2720 mode_box->set_border_width (2);
2721 mode_box->set_spacing(4);
2723 HBox* mouse_mode_box = manage (new HBox);
2724 HBox* mouse_mode_hbox = manage (new HBox);
2725 VBox* mouse_mode_vbox = manage (new VBox);
2726 Alignment* mouse_mode_align = manage (new Alignment);
2728 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
2729 // mouse_mode_size_group->add_widget (smart_mode_button);
2730 mouse_mode_size_group->add_widget (mouse_move_button);
2731 mouse_mode_size_group->add_widget (mouse_select_button);
2732 mouse_mode_size_group->add_widget (mouse_zoom_button);
2733 mouse_mode_size_group->add_widget (mouse_gain_button);
2734 mouse_mode_size_group->add_widget (mouse_timefx_button);
2735 mouse_mode_size_group->add_widget (mouse_audition_button);
2736 mouse_mode_size_group->add_widget (mouse_draw_button);
2737 mouse_mode_size_group->add_widget (internal_edit_button);
2739 /* make them just a bit bigger */
2740 mouse_move_button.set_size_request (-1, 30);
2742 mouse_mode_hbox->set_spacing (2);
2744 if (!ARDOUR::Profile->get_trx()) {
2745 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2748 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2749 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2750 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2752 if (!ARDOUR::Profile->get_trx()) {
2753 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2754 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2755 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2756 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2757 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
2760 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2762 mouse_mode_align->add (*mouse_mode_vbox);
2763 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2765 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2767 edit_mode_strings.push_back (edit_mode_to_string (Slide));
2768 if (!Profile->get_sae()) {
2769 edit_mode_strings.push_back (edit_mode_to_string (Splice));
2771 edit_mode_strings.push_back (edit_mode_to_string (Lock));
2773 edit_mode_selector.set_name ("mouse mode button");
2774 edit_mode_selector.set_size_request (65, -1);
2775 edit_mode_selector.add_elements (ArdourButton::Inset);
2777 if (!ARDOUR::Profile->get_trx()) {
2778 mode_box->pack_start (edit_mode_selector, false, false);
2780 mode_box->pack_start (*mouse_mode_box, false, false);
2782 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2783 _mouse_mode_tearoff->set_name ("MouseModeBase");
2784 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2786 if (Profile->get_sae()) {
2787 _mouse_mode_tearoff->set_can_be_torn_off (false);
2790 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2791 &_mouse_mode_tearoff->tearoff_window()));
2792 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2793 &_mouse_mode_tearoff->tearoff_window(), 1));
2794 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2795 &_mouse_mode_tearoff->tearoff_window()));
2796 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2797 &_mouse_mode_tearoff->tearoff_window(), 1));
2801 _zoom_box.set_spacing (2);
2802 _zoom_box.set_border_width (2);
2806 zoom_in_button.set_name ("zoom button");
2807 // zoom_in_button.add_elements ( ArdourButton::Inset );
2808 zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2809 zoom_in_button.set_image(::get_icon ("zoom_in"));
2810 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2811 zoom_in_button.set_related_action (act);
2813 zoom_out_button.set_name ("zoom button");
2814 // zoom_out_button.add_elements ( ArdourButton::Inset );
2815 zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2816 zoom_out_button.set_image(::get_icon ("zoom_out"));
2817 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2818 zoom_out_button.set_related_action (act);
2820 zoom_out_full_button.set_name ("zoom button");
2821 // zoom_out_full_button.add_elements ( ArdourButton::Inset );
2822 zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2823 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2824 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2825 zoom_out_full_button.set_related_action (act);
2827 zoom_focus_selector.set_name ("zoom button");
2828 zoom_focus_selector.set_size_request (80, -1);
2829 // zoom_focus_selector.add_elements (ArdourButton::Inset);
2831 if (!ARDOUR::Profile->get_trx()) {
2832 _zoom_box.pack_start (zoom_out_button, false, false);
2833 _zoom_box.pack_start (zoom_in_button, false, false);
2834 _zoom_box.pack_start (zoom_out_full_button, false, false);
2835 _zoom_box.pack_start (zoom_focus_selector, false, false);
2837 mode_box->pack_start (zoom_out_button, false, false);
2838 mode_box->pack_start (zoom_in_button, false, false);
2841 /* Track zoom buttons */
2842 visible_tracks_selector.set_name ("zoom button");
2843 // visible_tracks_selector.add_elements ( ArdourButton::Inset );
2844 set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
2846 tav_expand_button.set_name ("zoom button");
2847 // tav_expand_button.add_elements ( ArdourButton::FlatFace );
2848 tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2849 tav_expand_button.set_size_request (-1, 20);
2850 tav_expand_button.set_image(::get_icon ("tav_exp"));
2851 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2852 tav_expand_button.set_related_action (act);
2854 tav_shrink_button.set_name ("zoom button");
2855 // tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2856 tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2857 tav_shrink_button.set_size_request (-1, 20);
2858 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2859 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2860 tav_shrink_button.set_related_action (act);
2862 if (!ARDOUR::Profile->get_trx()) {
2863 _zoom_box.pack_start (visible_tracks_selector);
2865 _zoom_box.pack_start (tav_shrink_button);
2866 _zoom_box.pack_start (tav_expand_button);
2868 if (!ARDOUR::Profile->get_trx()) {
2869 _zoom_tearoff = manage (new TearOff (_zoom_box));
2871 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2872 &_zoom_tearoff->tearoff_window()));
2873 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2874 &_zoom_tearoff->tearoff_window(), 0));
2875 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2876 &_zoom_tearoff->tearoff_window()));
2877 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2878 &_zoom_tearoff->tearoff_window(), 0));
2881 snap_box.set_spacing (2);
2882 snap_box.set_border_width (2);
2884 snap_type_selector.set_name ("mouse mode button");
2885 snap_type_selector.set_size_request (140, -1);
2886 snap_type_selector.add_elements (ArdourButton::Inset);
2888 snap_mode_selector.set_name ("mouse mode button");
2889 snap_mode_selector.set_size_request (85, -1);
2890 snap_mode_selector.add_elements (ArdourButton::Inset);
2892 edit_point_selector.set_name ("mouse mode button");
2893 edit_point_selector.set_size_request (85, -1);
2894 edit_point_selector.add_elements (ArdourButton::Inset);
2896 snap_box.pack_start (snap_mode_selector, false, false);
2897 snap_box.pack_start (snap_type_selector, false, false);
2898 snap_box.pack_start (edit_point_selector, false, false);
2902 HBox *nudge_box = manage (new HBox);
2903 nudge_box->set_spacing (2);
2904 nudge_box->set_border_width (2);
2906 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
2907 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
2909 nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2910 nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2912 nudge_box->pack_start (nudge_backward_button, false, false);
2913 nudge_box->pack_start (nudge_forward_button, false, false);
2914 nudge_box->pack_start (*nudge_clock, false, false);
2917 /* Pack everything in... */
2919 HBox* hbox = manage (new HBox);
2920 hbox->set_spacing(10);
2922 _tools_tearoff = manage (new TearOff (*hbox));
2923 _tools_tearoff->set_name ("MouseModeBase");
2924 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
2926 if (Profile->get_sae()) {
2927 _tools_tearoff->set_can_be_torn_off (false);
2930 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2931 &_tools_tearoff->tearoff_window()));
2932 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2933 &_tools_tearoff->tearoff_window(), 0));
2934 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2935 &_tools_tearoff->tearoff_window()));
2936 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2937 &_tools_tearoff->tearoff_window(), 0));
2939 toolbar_hbox.set_spacing (10);
2940 toolbar_hbox.set_border_width (1);
2942 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
2943 if (!ARDOUR::Profile->get_trx()) {
2944 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
2945 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
2948 if (!ARDOUR::Profile->get_trx()) {
2949 hbox->pack_start (snap_box, false, false);
2950 if (!Profile->get_small_screen()) {
2951 hbox->pack_start (*nudge_box, false, false);
2953 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
2956 hbox->pack_start (panic_box, false, false);
2960 toolbar_base.set_name ("ToolBarBase");
2961 toolbar_base.add (toolbar_hbox);
2963 _toolbar_viewport.add (toolbar_base);
2964 /* stick to the required height but allow width to vary if there's not enough room */
2965 _toolbar_viewport.set_size_request (1, -1);
2967 toolbar_frame.set_shadow_type (SHADOW_OUT);
2968 toolbar_frame.set_name ("BaseFrame");
2969 toolbar_frame.add (_toolbar_viewport);
2973 Editor::build_edit_point_menu ()
2975 using namespace Menu_Helpers;
2977 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
2978 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
2979 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
2983 Editor::build_edit_mode_menu ()
2985 using namespace Menu_Helpers;
2987 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
2988 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
2989 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
2993 Editor::build_snap_mode_menu ()
2995 using namespace Menu_Helpers;
2997 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
2998 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
2999 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3003 Editor::build_snap_type_menu ()
3005 using namespace Menu_Helpers;
3007 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3008 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3009 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3010 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3011 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3012 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3013 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3014 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3015 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3016 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3017 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3018 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3019 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3020 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3021 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3022 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3023 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3024 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3025 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3026 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3027 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3028 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3029 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3030 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3031 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3032 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3033 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3034 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3035 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3036 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3040 Editor::setup_tooltips ()
3042 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3043 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3044 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3045 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3046 ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3047 ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3048 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3049 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3050 ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3051 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3052 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3053 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3054 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3055 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3056 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3057 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3058 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3059 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3060 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3061 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3062 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3063 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3064 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3065 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3069 Editor::convert_drop_to_paths (
3070 vector<string>& paths,
3071 const RefPtr<Gdk::DragContext>& /*context*/,
3074 const SelectionData& data,
3078 if (_session == 0) {
3082 vector<string> uris = data.get_uris();
3086 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3087 are actually URI lists. So do it by hand.
3090 if (data.get_target() != "text/plain") {
3094 /* Parse the "uri-list" format that Nautilus provides,
3095 where each pathname is delimited by \r\n.
3097 THERE MAY BE NO NULL TERMINATING CHAR!!!
3100 string txt = data.get_text();
3104 p = (char *) malloc (txt.length() + 1);
3105 txt.copy (p, txt.length(), 0);
3106 p[txt.length()] = '\0';
3112 while (g_ascii_isspace (*p))
3116 while (*q && (*q != '\n') && (*q != '\r')) {
3123 while (q > p && g_ascii_isspace (*q))
3128 uris.push_back (string (p, q - p + 1));
3132 p = strchr (p, '\n');
3144 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3145 if ((*i).substr (0,7) == "file://") {
3146 paths.push_back (Glib::filename_from_uri (*i));
3154 Editor::new_tempo_section ()
3159 Editor::map_transport_state ()
3161 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3163 if (_session && _session->transport_stopped()) {
3164 have_pending_keyboard_selection = false;
3167 update_loop_range_view ();
3173 Editor::begin_reversible_command (string name)
3176 _session->begin_reversible_command (name);
3181 Editor::begin_reversible_command (GQuark q)
3184 _session->begin_reversible_command (q);
3189 Editor::commit_reversible_command ()
3192 _session->commit_reversible_command ();
3197 Editor::history_changed ()
3201 if (undo_action && _session) {
3202 if (_session->undo_depth() == 0) {
3203 label = S_("Command|Undo");
3205 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3207 undo_action->property_label() = label;
3210 if (redo_action && _session) {
3211 if (_session->redo_depth() == 0) {
3214 label = string_compose(_("Redo (%1)"), _session->next_redo());
3216 redo_action->property_label() = label;
3221 Editor::duplicate_range (bool with_dialog)
3225 RegionSelection rs = get_regions_from_selection_and_entered ();
3227 if ( selection->time.length() == 0 && rs.empty()) {
3233 ArdourDialog win (_("Duplicate"));
3234 Label label (_("Number of duplications:"));
3235 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3236 SpinButton spinner (adjustment, 0.0, 1);
3239 win.get_vbox()->set_spacing (12);
3240 win.get_vbox()->pack_start (hbox);
3241 hbox.set_border_width (6);
3242 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3244 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3245 place, visually. so do this by hand.
3248 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3249 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3250 spinner.grab_focus();
3256 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3257 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3258 win.set_default_response (RESPONSE_ACCEPT);
3260 spinner.grab_focus ();
3262 switch (win.run ()) {
3263 case RESPONSE_ACCEPT:
3269 times = adjustment.get_value();
3272 if ((current_mouse_mode() == Editing::MouseRange)) {
3273 if (selection->time.length()) {
3274 duplicate_selection (times);
3276 } else if (get_smart_mode()) {
3277 if (selection->time.length()) {
3278 duplicate_selection (times);
3280 duplicate_some_regions (rs, times);
3282 duplicate_some_regions (rs, times);
3287 Editor::set_edit_mode (EditMode m)
3289 Config->set_edit_mode (m);
3293 Editor::cycle_edit_mode ()
3295 switch (Config->get_edit_mode()) {
3297 if (Profile->get_sae()) {
3298 Config->set_edit_mode (Lock);
3300 Config->set_edit_mode (Splice);
3304 Config->set_edit_mode (Lock);
3307 Config->set_edit_mode (Slide);
3313 Editor::edit_mode_selection_done ( EditMode m )
3315 Config->set_edit_mode ( m );
3319 Editor::snap_type_selection_done (SnapType snaptype)
3321 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3323 ract->set_active ();
3328 Editor::snap_mode_selection_done (SnapMode mode)
3330 RefPtr<RadioAction> ract = snap_mode_action (mode);
3333 ract->set_active (true);
3338 Editor::cycle_edit_point (bool with_marker)
3340 switch (_edit_point) {
3342 set_edit_point_preference (EditAtPlayhead);
3344 case EditAtPlayhead:
3346 set_edit_point_preference (EditAtSelectedMarker);
3348 set_edit_point_preference (EditAtMouse);
3351 case EditAtSelectedMarker:
3352 set_edit_point_preference (EditAtMouse);
3358 Editor::edit_point_selection_done (EditPoint ep)
3360 set_edit_point_preference ( ep );
3364 Editor::build_zoom_focus_menu ()
3366 using namespace Menu_Helpers;
3368 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3369 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3370 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3371 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3372 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3373 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3377 Editor::zoom_focus_selection_done ( ZoomFocus f )
3379 RefPtr<RadioAction> ract = zoom_focus_action (f);
3381 ract->set_active ();
3386 Editor::build_track_count_menu ()
3388 using namespace Menu_Helpers;
3390 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3391 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3392 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3393 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3394 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3395 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3396 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3397 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3398 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3399 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3400 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3401 visible_tracks_selector.AddMenuElem (MenuElem (_("all"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3405 Editor::set_visible_track_count (int32_t n)
3407 _visible_track_count = n;
3409 /* if the canvas hasn't really been allocated any size yet, just
3410 record the desired number of visible tracks and return. when canvas
3411 allocation happens, we will get called again and then we can do the
3415 if (_visible_canvas_height <= 1) {
3422 if (_visible_track_count > 0) {
3423 h = _visible_canvas_height / _visible_track_count;
3424 std::ostringstream s;
3425 s << _visible_track_count;
3427 } else if (_visible_track_count == 0) {
3428 h = _visible_canvas_height / track_views.size();
3431 /* negative value means that the visible track count has
3432 been overridden by explicit track height changes.
3434 visible_tracks_selector.set_text (X_("*"));
3438 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3439 (*i)->set_height (h);
3442 if (str != visible_tracks_selector.get_text()) {
3443 visible_tracks_selector.set_text (str);
3448 Editor::override_visible_track_count ()
3450 _visible_track_count = -_visible_track_count;
3454 Editor::edit_controls_button_release (GdkEventButton* ev)
3456 if (Keyboard::is_context_menu_event (ev)) {
3457 ARDOUR_UI::instance()->add_route (this);
3458 } else if (ev->button == 1) {
3459 selection->clear_tracks ();
3466 Editor::mouse_select_button_release (GdkEventButton* ev)
3468 /* this handles just right-clicks */
3470 if (ev->button != 3) {
3478 Editor::set_zoom_focus (ZoomFocus f)
3480 string str = zoom_focus_strings[(int)f];
3482 if (str != zoom_focus_selector.get_text()) {
3483 zoom_focus_selector.set_text (str);
3486 if (zoom_focus != f) {
3493 Editor::cycle_zoom_focus ()
3495 switch (zoom_focus) {
3497 set_zoom_focus (ZoomFocusRight);
3499 case ZoomFocusRight:
3500 set_zoom_focus (ZoomFocusCenter);
3502 case ZoomFocusCenter:
3503 set_zoom_focus (ZoomFocusPlayhead);
3505 case ZoomFocusPlayhead:
3506 set_zoom_focus (ZoomFocusMouse);
3508 case ZoomFocusMouse:
3509 set_zoom_focus (ZoomFocusEdit);
3512 set_zoom_focus (ZoomFocusLeft);
3518 Editor::ensure_float (Window& win)
3520 win.set_transient_for (*this);
3524 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3526 /* recover or initialize pane positions. do this here rather than earlier because
3527 we don't want the positions to change the child allocations, which they seem to do.
3533 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3542 XMLNode* geometry = find_named_node (*node, "geometry");
3544 if (which == static_cast<Paned*> (&edit_pane)) {
3546 if (done & Horizontal) {
3550 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3551 _notebook_shrunk = string_is_affirmative (prop->value ());
3554 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3555 /* initial allocation is 90% to canvas, 10% to notebook */
3556 pos = (int) floor (alloc.get_width() * 0.90f);
3557 snprintf (buf, sizeof(buf), "%d", pos);
3559 pos = atoi (prop->value());
3562 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3563 edit_pane.set_position (pos);
3566 done = (Pane) (done | Horizontal);
3568 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3570 if (done & Vertical) {
3574 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3575 /* initial allocation is 90% to canvas, 10% to summary */
3576 pos = (int) floor (alloc.get_height() * 0.90f);
3577 snprintf (buf, sizeof(buf), "%d", pos);
3580 pos = atoi (prop->value());
3583 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3584 editor_summary_pane.set_position (pos);
3587 done = (Pane) (done | Vertical);
3592 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3594 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3595 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3596 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3597 top_hbox.remove (toolbar_frame);
3602 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3604 if (toolbar_frame.get_parent() == 0) {
3605 top_hbox.pack_end (toolbar_frame);
3610 Editor::set_show_measures (bool yn)
3612 if (_show_measures != yn) {
3615 if ((_show_measures = yn) == true) {
3617 tempo_lines->show();
3620 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3621 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3623 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3624 draw_measures (begin, end);
3632 Editor::toggle_follow_playhead ()
3634 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3636 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3637 set_follow_playhead (tact->get_active());
3641 /** @param yn true to follow playhead, otherwise false.
3642 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3645 Editor::set_follow_playhead (bool yn, bool catch_up)
3647 if (_follow_playhead != yn) {
3648 if ((_follow_playhead = yn) == true && catch_up) {
3650 reset_x_origin_to_follow_playhead ();
3657 Editor::toggle_stationary_playhead ()
3659 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3661 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3662 set_stationary_playhead (tact->get_active());
3667 Editor::set_stationary_playhead (bool yn)
3669 if (_stationary_playhead != yn) {
3670 if ((_stationary_playhead = yn) == true) {
3672 // FIXME need a 3.0 equivalent of this 2.X call
3673 // update_current_screen ();
3680 Editor::playlist_selector () const
3682 return *_playlist_selector;
3686 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3690 switch (_snap_type) {
3695 case SnapToBeatDiv128:
3698 case SnapToBeatDiv64:
3701 case SnapToBeatDiv32:
3704 case SnapToBeatDiv28:
3707 case SnapToBeatDiv24:
3710 case SnapToBeatDiv20:
3713 case SnapToBeatDiv16:
3716 case SnapToBeatDiv14:
3719 case SnapToBeatDiv12:
3722 case SnapToBeatDiv10:
3725 case SnapToBeatDiv8:
3728 case SnapToBeatDiv7:
3731 case SnapToBeatDiv6:
3734 case SnapToBeatDiv5:
3737 case SnapToBeatDiv4:
3740 case SnapToBeatDiv3:
3743 case SnapToBeatDiv2:
3749 return _session->tempo_map().meter_at (position).divisions_per_bar();
3754 case SnapToTimecodeFrame:
3755 case SnapToTimecodeSeconds:
3756 case SnapToTimecodeMinutes:
3759 case SnapToRegionStart:
3760 case SnapToRegionEnd:
3761 case SnapToRegionSync:
3762 case SnapToRegionBoundary:
3772 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3776 ret = nudge_clock->current_duration (pos);
3777 next = ret + 1; /* XXXX fix me */
3783 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3785 ArdourDialog dialog (_("Playlist Deletion"));
3786 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3787 "If it is kept, its audio files will not be cleaned.\n"
3788 "If it is deleted, audio files used by it alone will be cleaned."),
3791 dialog.set_position (WIN_POS_CENTER);
3792 dialog.get_vbox()->pack_start (label);
3796 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3797 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3798 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3800 switch (dialog.run ()) {
3801 case RESPONSE_ACCEPT:
3802 /* delete the playlist */
3806 case RESPONSE_REJECT:
3807 /* keep the playlist */
3819 Editor::audio_region_selection_covers (framepos_t where)
3821 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3822 if ((*a)->region()->covers (where)) {
3831 Editor::prepare_for_cleanup ()
3833 cut_buffer->clear_regions ();
3834 cut_buffer->clear_playlists ();
3836 selection->clear_regions ();
3837 selection->clear_playlists ();
3839 _regions->suspend_redisplay ();
3843 Editor::finish_cleanup ()
3845 _regions->resume_redisplay ();
3849 Editor::transport_loop_location()
3852 return _session->locations()->auto_loop_location();
3859 Editor::transport_punch_location()
3862 return _session->locations()->auto_punch_location();
3869 Editor::control_layout_scroll (GdkEventScroll* ev)
3871 if (Keyboard::some_magic_widget_has_focus()) {
3875 switch (ev->direction) {
3877 scroll_tracks_up_line ();
3881 case GDK_SCROLL_DOWN:
3882 scroll_tracks_down_line ();
3886 /* no left/right handling yet */
3894 Editor::session_state_saved (string)
3897 _snapshots->redisplay ();
3901 Editor::update_tearoff_visibility()
3903 bool visible = Config->get_keep_tearoffs();
3904 _mouse_mode_tearoff->set_visible (visible);
3905 _tools_tearoff->set_visible (visible);
3906 if (_zoom_tearoff) {
3907 _zoom_tearoff->set_visible (visible);
3912 Editor::maximise_editing_space ()
3924 Editor::restore_editing_space ()
3936 * Make new playlists for a given track and also any others that belong
3937 * to the same active route group with the `select' property.
3942 Editor::new_playlists (TimeAxisView* v)
3944 begin_reversible_command (_("new playlists"));
3945 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3946 _session->playlists->get (playlists);
3947 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
3948 commit_reversible_command ();
3952 * Use a copy of the current playlist for a given track and also any others that belong
3953 * to the same active route group with the `select' property.
3958 Editor::copy_playlists (TimeAxisView* v)
3960 begin_reversible_command (_("copy playlists"));
3961 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3962 _session->playlists->get (playlists);
3963 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
3964 commit_reversible_command ();
3967 /** Clear the current playlist for a given track and also any others that belong
3968 * to the same active route group with the `select' property.
3973 Editor::clear_playlists (TimeAxisView* v)
3975 begin_reversible_command (_("clear playlists"));
3976 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3977 _session->playlists->get (playlists);
3978 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
3979 commit_reversible_command ();
3983 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
3985 atv.use_new_playlist (sz > 1 ? false : true, playlists);
3989 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
3991 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
3995 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
3997 atv.clear_playlist ();
4001 Editor::on_key_press_event (GdkEventKey* ev)
4003 return key_press_focus_accelerator_handler (*this, ev);
4007 Editor::on_key_release_event (GdkEventKey* ev)
4009 return Gtk::Window::on_key_release_event (ev);
4010 // return key_press_focus_accelerator_handler (*this, ev);
4013 /** Queue up a change to the viewport x origin.
4014 * @param frame New x origin.
4017 Editor::reset_x_origin (framepos_t frame)
4019 pending_visual_change.add (VisualChange::TimeOrigin);
4020 pending_visual_change.time_origin = frame;
4021 ensure_visual_change_idle_handler ();
4025 Editor::reset_y_origin (double y)
4027 pending_visual_change.add (VisualChange::YOrigin);
4028 pending_visual_change.y_origin = y;
4029 ensure_visual_change_idle_handler ();
4033 Editor::reset_zoom (framecnt_t spp)
4035 clamp_samples_per_pixel (spp);
4037 if (spp == samples_per_pixel) {
4041 pending_visual_change.add (VisualChange::ZoomLevel);
4042 pending_visual_change.samples_per_pixel = spp;
4043 ensure_visual_change_idle_handler ();
4047 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4049 reset_x_origin (frame);
4052 if (!no_save_visual) {
4053 undo_visual_stack.push_back (current_visual_state(false));
4057 Editor::VisualState::VisualState (bool with_tracks)
4058 : gui_state (with_tracks ? new GUIObjectState : 0)
4062 Editor::VisualState::~VisualState ()
4067 Editor::VisualState*
4068 Editor::current_visual_state (bool with_tracks)
4070 VisualState* vs = new VisualState (with_tracks);
4071 vs->y_position = vertical_adjustment.get_value();
4072 vs->samples_per_pixel = samples_per_pixel;
4073 vs->leftmost_frame = leftmost_frame;
4074 vs->zoom_focus = zoom_focus;
4077 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4084 Editor::undo_visual_state ()
4086 if (undo_visual_stack.empty()) {
4090 VisualState* vs = undo_visual_stack.back();
4091 undo_visual_stack.pop_back();
4094 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4096 use_visual_state (*vs);
4100 Editor::redo_visual_state ()
4102 if (redo_visual_stack.empty()) {
4106 VisualState* vs = redo_visual_stack.back();
4107 redo_visual_stack.pop_back();
4109 undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4111 use_visual_state (*vs);
4115 Editor::swap_visual_state ()
4117 if (undo_visual_stack.empty()) {
4118 redo_visual_state ();
4120 undo_visual_state ();
4125 Editor::use_visual_state (VisualState& vs)
4127 PBD::Unwinder<bool> nsv (no_save_visual, true);
4129 _routes->suspend_redisplay ();
4131 vertical_adjustment.set_value (vs.y_position);
4133 set_zoom_focus (vs.zoom_focus);
4134 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4137 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4139 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4140 (*i)->reset_visual_state ();
4144 _routes->update_visibility ();
4145 _routes->resume_redisplay ();
4148 /** This is the core function that controls the zoom level of the canvas. It is called
4149 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4150 * @param fpu New frames per unit; should already have been clamped so that it is sensible.
4153 Editor::set_samples_per_pixel (framecnt_t spp)
4155 clamp_samples_per_pixel (spp);
4156 samples_per_pixel = spp;
4159 tempo_lines->tempo_map_changed();
4162 /* convert fpu to frame count */
4164 framepos_t frames = samples_per_pixel * _visible_canvas_width;
4166 if (samples_per_pixel != zoom_range_clock->current_duration()) {
4167 zoom_range_clock->set (frames);
4170 bool const showing_time_selection = selection->time.length() > 0;
4172 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4173 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4174 (*i)->reshow_selection (selection->time);
4178 ZoomChanged (); /* EMIT_SIGNAL */
4180 ArdourCanvas::GtkCanvasViewport* c;
4182 c = get_track_canvas();
4184 c->canvas()->zoomed ();
4187 if (playhead_cursor) {
4188 playhead_cursor->set_position (playhead_cursor->current_frame ());
4191 refresh_location_display();
4192 _summary->set_overlays_dirty ();
4194 update_marker_labels ();
4200 Editor::queue_visual_videotimeline_update ()
4203 * pending_visual_change.add (VisualChange::VideoTimeline);
4204 * or maybe even more specific: which videotimeline-image
4205 * currently it calls update_video_timeline() to update
4206 * _all outdated_ images on the video-timeline.
4207 * see 'exposeimg()' in video_image_frame.cc
4209 ensure_visual_change_idle_handler ();
4213 Editor::ensure_visual_change_idle_handler ()
4215 if (pending_visual_change.idle_handler_id < 0) {
4216 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4217 pending_visual_change.being_handled = false;
4222 Editor::_idle_visual_changer (void* arg)
4224 return static_cast<Editor*>(arg)->idle_visual_changer ();
4228 Editor::idle_visual_changer ()
4230 /* set_horizontal_position() below (and maybe other calls) call
4231 gtk_main_iteration(), so it's possible that a signal will be handled
4232 half-way through this method. If this signal wants an
4233 idle_visual_changer we must schedule another one after this one, so
4234 mark the idle_handler_id as -1 here to allow that. Also make a note
4235 that we are doing the visual change, so that changes in response to
4236 super-rapid-screen-update can be dropped if we are still processing
4240 pending_visual_change.idle_handler_id = -1;
4241 pending_visual_change.being_handled = true;
4243 VisualChange vc = pending_visual_change;
4245 pending_visual_change.pending = (VisualChange::Type) 0;
4247 visual_changer (vc);
4249 pending_visual_change.being_handled = false;
4251 return 0; /* this is always a one-shot call */
4255 Editor::visual_changer (const VisualChange& vc)
4257 double const last_time_origin = horizontal_position ();
4259 if (vc.pending & VisualChange::ZoomLevel) {
4260 set_samples_per_pixel (vc.samples_per_pixel);
4262 compute_fixed_ruler_scale ();
4264 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4265 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4267 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4268 current_bbt_points_begin, current_bbt_points_end);
4269 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4270 current_bbt_points_begin, current_bbt_points_end);
4271 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4273 update_video_timeline();
4276 if (vc.pending & VisualChange::TimeOrigin) {
4277 set_horizontal_position (vc.time_origin / samples_per_pixel);
4280 if (vc.pending & VisualChange::YOrigin) {
4281 vertical_adjustment.set_value (vc.y_origin);
4284 if (last_time_origin == horizontal_position ()) {
4285 /* changed signal not emitted */
4286 update_fixed_rulers ();
4287 redisplay_tempo (true);
4290 if (!(vc.pending & VisualChange::ZoomLevel)) {
4291 update_video_timeline();
4294 _summary->set_overlays_dirty ();
4297 struct EditorOrderTimeAxisSorter {
4298 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4299 return a->order () < b->order ();
4304 Editor::sort_track_selection (TrackViewList& sel)
4306 EditorOrderTimeAxisSorter cmp;
4311 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4314 framepos_t where = 0;
4315 EditPoint ep = _edit_point;
4317 if (from_context_menu && (ep == EditAtMouse)) {
4318 return canvas_event_sample (&context_click_event, 0, 0);
4321 if (entered_marker) {
4322 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4323 return entered_marker->position();
4326 if (ignore_playhead && ep == EditAtPlayhead) {
4327 ep = EditAtSelectedMarker;
4331 case EditAtPlayhead:
4332 where = _session->audible_frame();
4333 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4336 case EditAtSelectedMarker:
4337 if (!selection->markers.empty()) {
4339 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4342 where = loc->start();
4346 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4354 if (!mouse_frame (where, ignored)) {
4355 /* XXX not right but what can we do ? */
4359 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4367 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4369 if (!_session) return;
4371 begin_reversible_command (cmd);
4375 if ((tll = transport_loop_location()) == 0) {
4376 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4377 XMLNode &before = _session->locations()->get_state();
4378 _session->locations()->add (loc, true);
4379 _session->set_auto_loop_location (loc);
4380 XMLNode &after = _session->locations()->get_state();
4381 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4383 XMLNode &before = tll->get_state();
4384 tll->set_hidden (false, this);
4385 tll->set (start, end);
4386 XMLNode &after = tll->get_state();
4387 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4390 commit_reversible_command ();
4394 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4396 if (!_session) return;
4398 begin_reversible_command (cmd);
4402 if ((tpl = transport_punch_location()) == 0) {
4403 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4404 XMLNode &before = _session->locations()->get_state();
4405 _session->locations()->add (loc, true);
4406 _session->set_auto_punch_location (loc);
4407 XMLNode &after = _session->locations()->get_state();
4408 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4411 XMLNode &before = tpl->get_state();
4412 tpl->set_hidden (false, this);
4413 tpl->set (start, end);
4414 XMLNode &after = tpl->get_state();
4415 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4418 commit_reversible_command ();
4421 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4422 * @param rs List to which found regions are added.
4423 * @param where Time to look at.
4424 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4427 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4429 const TrackViewList* tracks;
4432 tracks = &track_views;
4437 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4439 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4442 boost::shared_ptr<Track> tr;
4443 boost::shared_ptr<Playlist> pl;
4445 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4447 boost::shared_ptr<RegionList> regions = pl->regions_at (
4448 (framepos_t) floor ( (double) where * tr->speed()));
4450 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4451 RegionView* rv = rtv->view()->find_view (*i);
4462 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4464 const TrackViewList* tracks;
4467 tracks = &track_views;
4472 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4473 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4475 boost::shared_ptr<Track> tr;
4476 boost::shared_ptr<Playlist> pl;
4478 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4480 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4481 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4483 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4485 RegionView* rv = rtv->view()->find_view (*i);
4496 /** Get regions using the following method:
4498 * Make a region list using the selected regions, unless
4499 * the edit point is `mouse' and the mouse is over an unselected
4500 * region. In this case, use just that region.
4502 * If the edit point is not 'mouse', and there are no regions selected,
4503 * search the list of selected tracks and return regions that are under
4504 * the edit point on these tracks. If there are no selected tracks and
4505 * 'No Selection = All Tracks' is active, search all tracks,
4507 * The rationale here is that the mouse edit point is special in that
4508 * its position describes both a time and a track; the other edit
4509 * modes only describe a time. Hence if the edit point is `mouse' we
4510 * ignore selected tracks, as we assume the user means something by
4511 * pointing at a particular track. Also in this case we take note of
4512 * the region directly under the edit point, as there is always just one
4513 * (rather than possibly several with non-mouse edit points).
4517 Editor::get_regions_from_selection_and_edit_point ()
4519 RegionSelection regions;
4521 if (_edit_point == EditAtMouse && entered_regionview && !selection->regions.contains (entered_regionview)) {
4522 regions.add (entered_regionview);
4524 regions = selection->regions;
4528 if (regions.empty() && _edit_point != EditAtMouse) {
4529 TrackViewList tracks = selection->tracks;
4531 if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
4532 /* tracks is empty (no track selected), and 'No Selection = All Tracks'
4533 * is enabled, so consider all tracks
4535 tracks = track_views;
4538 if (!tracks.empty()) {
4539 /* no region selected or entered, but some selected tracks:
4540 * act on all regions on the selected tracks at the edit point
4542 framepos_t const where = get_preferred_edit_position ();
4543 get_regions_at(regions, where, tracks);
4549 /** Start with regions that are selected, or the entered regionview if none are selected.
4550 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4551 * of the regions that we started with.
4555 Editor::get_regions_from_selection_and_entered ()
4557 RegionSelection regions = selection->regions;
4559 if (regions.empty() && entered_regionview) {
4560 regions.add (entered_regionview);
4567 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4569 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4571 RouteTimeAxisView* tatv;
4573 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4575 boost::shared_ptr<Playlist> pl;
4576 vector<boost::shared_ptr<Region> > results;
4578 boost::shared_ptr<Track> tr;
4580 if ((tr = tatv->track()) == 0) {
4585 if ((pl = (tr->playlist())) != 0) {
4586 if (src_comparison) {
4587 pl->get_source_equivalent_regions (region, results);
4589 pl->get_region_list_equivalent_regions (region, results);
4593 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4594 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4595 regions.push_back (marv);
4604 Editor::show_rhythm_ferret ()
4606 if (rhythm_ferret == 0) {
4607 rhythm_ferret = new RhythmFerret(*this);
4610 rhythm_ferret->set_session (_session);
4611 rhythm_ferret->show ();
4612 rhythm_ferret->present ();
4616 Editor::first_idle ()
4618 MessageDialog* dialog = 0;
4620 if (track_views.size() > 1) {
4621 dialog = new MessageDialog (
4623 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4627 ARDOUR_UI::instance()->flush_pending ();
4630 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4634 // first idle adds route children (automation tracks), so we need to redisplay here
4635 _routes->redisplay ();
4642 Editor::_idle_resize (gpointer arg)
4644 return ((Editor*)arg)->idle_resize ();
4648 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4650 if (resize_idle_id < 0) {
4651 resize_idle_id = g_idle_add (_idle_resize, this);
4652 _pending_resize_amount = 0;
4655 /* make a note of the smallest resulting height, so that we can clamp the
4656 lower limit at TimeAxisView::hSmall */
4658 int32_t min_resulting = INT32_MAX;
4660 _pending_resize_amount += h;
4661 _pending_resize_view = view;
4663 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4665 if (selection->tracks.contains (_pending_resize_view)) {
4666 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4667 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4671 if (min_resulting < 0) {
4676 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4677 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4681 /** Handle pending resizing of tracks */
4683 Editor::idle_resize ()
4685 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4687 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4688 selection->tracks.contains (_pending_resize_view)) {
4690 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4691 if (*i != _pending_resize_view) {
4692 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4697 _pending_resize_amount = 0;
4698 _group_tabs->set_dirty ();
4699 resize_idle_id = -1;
4707 ENSURE_GUI_THREAD (*this, &Editor::located);
4710 playhead_cursor->set_position (_session->audible_frame ());
4711 if (_follow_playhead && !_pending_initial_locate) {
4712 reset_x_origin_to_follow_playhead ();
4716 _pending_locate_request = false;
4717 _pending_initial_locate = false;
4721 Editor::region_view_added (RegionView *)
4723 _summary->set_dirty ();
4727 Editor::region_view_removed ()
4729 _summary->set_dirty ();
4733 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4735 TrackViewList::const_iterator j = track_views.begin ();
4736 while (j != track_views.end()) {
4737 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4738 if (rtv && rtv->route() == r) {
4749 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4753 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4754 TimeAxisView* tv = axis_view_from_route (*i);
4764 Editor::add_routes (RouteList& routes)
4766 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4768 RouteTimeAxisView *rtv;
4769 list<RouteTimeAxisView*> new_views;
4771 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4772 boost::shared_ptr<Route> route = (*x);
4774 if (route->is_auditioner() || route->is_monitor()) {
4778 DataType dt = route->input()->default_type();
4780 if (dt == ARDOUR::DataType::AUDIO) {
4781 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4782 rtv->set_route (route);
4783 } else if (dt == ARDOUR::DataType::MIDI) {
4784 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
4785 rtv->set_route (route);
4787 throw unknown_type();
4790 new_views.push_back (rtv);
4791 track_views.push_back (rtv);
4793 rtv->effective_gain_display ();
4795 if (internal_editing()) {
4796 rtv->enter_internal_edit_mode ();
4798 rtv->leave_internal_edit_mode ();
4801 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4802 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4805 if (new_views.size() > 0) {
4806 _routes->routes_added (new_views);
4807 _summary->routes_added (new_views);
4810 if (show_editor_mixer_when_tracks_arrive) {
4811 show_editor_mixer (true);
4814 editor_list_button.set_sensitive (true);
4818 Editor::timeaxisview_deleted (TimeAxisView *tv)
4820 if (_session && _session->deletion_in_progress()) {
4821 /* the situation is under control */
4825 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
4827 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
4829 _routes->route_removed (tv);
4831 if (tv == entered_track) {
4835 TimeAxisView::Children c = tv->get_child_list ();
4836 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
4837 if (entered_track == i->get()) {
4842 /* remove it from the list of track views */
4844 TrackViewList::iterator i;
4846 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
4847 i = track_views.erase (i);
4850 /* update whatever the current mixer strip is displaying, if revelant */
4852 boost::shared_ptr<Route> route;
4855 route = rtav->route ();
4858 if (current_mixer_strip && current_mixer_strip->route() == route) {
4860 TimeAxisView* next_tv;
4862 if (track_views.empty()) {
4864 } else if (i == track_views.end()) {
4865 next_tv = track_views.front();
4872 set_selected_mixer_strip (*next_tv);
4874 /* make the editor mixer strip go away setting the
4875 * button to inactive (which also unticks the menu option)
4878 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
4884 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
4886 if (apply_to_selection) {
4887 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
4889 TrackSelection::iterator j = i;
4892 hide_track_in_display (*i, false);
4897 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
4899 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
4900 // this will hide the mixer strip
4901 set_selected_mixer_strip (*tv);
4904 _routes->hide_track_in_display (*tv);
4909 Editor::sync_track_view_list_and_routes ()
4911 track_views = TrackViewList (_routes->views ());
4913 _summary->set_dirty ();
4914 _group_tabs->set_dirty ();
4916 return false; // do not call again (until needed)
4920 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
4922 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4927 /** Find a RouteTimeAxisView by the ID of its route */
4929 Editor::get_route_view_by_route_id (const PBD::ID& id) const
4931 RouteTimeAxisView* v;
4933 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4934 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
4935 if(v->route()->id() == id) {
4945 Editor::fit_route_group (RouteGroup *g)
4947 TrackViewList ts = axis_views_from_routes (g->route_list ());
4952 Editor::consider_auditioning (boost::shared_ptr<Region> region)
4954 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
4957 _session->cancel_audition ();
4961 if (_session->is_auditioning()) {
4962 _session->cancel_audition ();
4963 if (r == last_audition_region) {
4968 _session->audition_region (r);
4969 last_audition_region = r;
4974 Editor::hide_a_region (boost::shared_ptr<Region> r)
4976 r->set_hidden (true);
4980 Editor::show_a_region (boost::shared_ptr<Region> r)
4982 r->set_hidden (false);
4986 Editor::audition_region_from_region_list ()
4988 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
4992 Editor::hide_region_from_region_list ()
4994 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
4998 Editor::show_region_in_region_list ()
5000 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5004 Editor::step_edit_status_change (bool yn)
5007 start_step_editing ();
5009 stop_step_editing ();
5014 Editor::start_step_editing ()
5016 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5020 Editor::stop_step_editing ()
5022 step_edit_connection.disconnect ();
5026 Editor::check_step_edit ()
5028 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5029 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5031 mtv->check_step_edit ();
5035 return true; // do it again, till we stop
5039 Editor::scroll_press (Direction dir)
5041 ++_scroll_callbacks;
5043 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5044 /* delay the first auto-repeat */
5050 scroll_backward (1);
5058 scroll_tracks_up_line ();
5062 scroll_tracks_down_line ();
5066 /* do hacky auto-repeat */
5067 if (!_scroll_connection.connected ()) {
5069 _scroll_connection = Glib::signal_timeout().connect (
5070 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5073 _scroll_callbacks = 0;
5080 Editor::scroll_release ()
5082 _scroll_connection.disconnect ();
5085 /** Queue a change for the Editor viewport x origin to follow the playhead */
5087 Editor::reset_x_origin_to_follow_playhead ()
5089 framepos_t const frame = playhead_cursor->current_frame ();
5091 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5093 if (_session->transport_speed() < 0) {
5095 if (frame > (current_page_samples() / 2)) {
5096 center_screen (frame-(current_page_samples()/2));
5098 center_screen (current_page_samples()/2);
5105 if (frame < leftmost_frame) {
5107 if (_session->transport_rolling()) {
5108 /* rolling; end up with the playhead at the right of the page */
5109 l = frame - current_page_samples ();
5111 /* not rolling: end up with the playhead 1/4 of the way along the page */
5112 l = frame - current_page_samples() / 4;
5116 if (_session->transport_rolling()) {
5117 /* rolling: end up with the playhead on the left of the page */
5120 /* not rolling: end up with the playhead 3/4 of the way along the page */
5121 l = frame - 3 * current_page_samples() / 4;
5129 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5135 Editor::super_rapid_screen_update ()
5137 if (!_session || !_session->engine().running()) {
5141 /* METERING / MIXER STRIPS */
5143 /* update track meters, if required */
5144 if (is_mapped() && meters_running) {
5145 RouteTimeAxisView* rtv;
5146 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5147 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5148 rtv->fast_update ();
5153 /* and any current mixer strip */
5154 if (current_mixer_strip) {
5155 current_mixer_strip->fast_update ();
5158 /* PLAYHEAD AND VIEWPORT */
5160 framepos_t const frame = _session->audible_frame();
5162 /* There are a few reasons why we might not update the playhead / viewport stuff:
5164 * 1. we don't update things when there's a pending locate request, otherwise
5165 * when the editor requests a locate there is a chance that this method
5166 * will move the playhead before the locate request is processed, causing
5168 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5169 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5172 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5174 last_update_frame = frame;
5176 if (!_dragging_playhead) {
5177 playhead_cursor->set_position (frame);
5180 if (!_stationary_playhead) {
5182 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5183 /* We only do this if we aren't already
5184 handling a visual change (ie if
5185 pending_visual_change.being_handled is
5186 false) so that these requests don't stack
5187 up there are too many of them to handle in
5190 reset_x_origin_to_follow_playhead ();
5195 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5199 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5200 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5201 if (target <= 0.0) {
5204 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5205 target = (target * 0.15) + (current * 0.85);
5211 set_horizontal_position (current);
5220 Editor::session_going_away ()
5222 _have_idled = false;
5224 _session_connections.drop_connections ();
5226 super_rapid_screen_update_connection.disconnect ();
5228 selection->clear ();
5229 cut_buffer->clear ();
5231 clicked_regionview = 0;
5232 clicked_axisview = 0;
5233 clicked_routeview = 0;
5234 entered_regionview = 0;
5236 last_update_frame = 0;
5239 playhead_cursor->hide ();
5241 /* rip everything out of the list displays */
5245 _route_groups->clear ();
5247 /* do this first so that deleting a track doesn't reset cms to null
5248 and thus cause a leak.
5251 if (current_mixer_strip) {
5252 if (current_mixer_strip->get_parent() != 0) {
5253 global_hpacker.remove (*current_mixer_strip);
5255 delete current_mixer_strip;
5256 current_mixer_strip = 0;
5259 /* delete all trackviews */
5261 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5264 track_views.clear ();
5266 zoom_range_clock->set_session (0);
5267 nudge_clock->set_session (0);
5269 editor_list_button.set_active(false);
5270 editor_list_button.set_sensitive(false);
5272 /* clear tempo/meter rulers */
5273 remove_metric_marks ();
5275 clear_marker_display ();
5277 stop_step_editing ();
5279 /* get rid of any existing editor mixer strip */
5281 WindowTitle title(Glib::get_application_name());
5282 title += _("Editor");
5284 set_title (title.get_string());
5286 SessionHandlePtr::session_going_away ();
5291 Editor::show_editor_list (bool yn)
5294 _the_notebook.show ();
5296 _the_notebook.hide ();
5301 Editor::change_region_layering_order (bool from_context_menu)
5303 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5305 if (!clicked_routeview) {
5306 if (layering_order_editor) {
5307 layering_order_editor->hide ();
5312 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5318 boost::shared_ptr<Playlist> pl = track->playlist();
5324 if (layering_order_editor == 0) {
5325 layering_order_editor = new RegionLayeringOrderEditor (*this);
5328 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5329 layering_order_editor->maybe_present ();
5333 Editor::update_region_layering_order_editor ()
5335 if (layering_order_editor && layering_order_editor->is_visible ()) {
5336 change_region_layering_order (true);
5341 Editor::setup_fade_images ()
5343 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5344 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5345 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5346 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5347 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5349 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5350 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5351 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5352 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5353 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5355 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5356 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5357 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5358 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5359 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5361 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5362 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5363 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5364 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5365 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5369 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5371 Editor::action_menu_item (std::string const & name)
5373 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5376 return *manage (a->create_menu_item ());
5380 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5382 EventBox* b = manage (new EventBox);
5383 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5384 Label* l = manage (new Label (name));
5388 _the_notebook.append_page (widget, *b);
5392 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5394 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5395 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5398 if (ev->type == GDK_2BUTTON_PRESS) {
5400 /* double-click on a notebook tab shrinks or expands the notebook */
5402 if (_notebook_shrunk) {
5403 if (pre_notebook_shrink_pane_width) {
5404 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5406 _notebook_shrunk = false;
5408 pre_notebook_shrink_pane_width = edit_pane.get_position();
5410 /* this expands the LHS of the edit pane to cover the notebook
5411 PAGE but leaves the tabs visible.
5413 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5414 _notebook_shrunk = true;
5422 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5424 using namespace Menu_Helpers;
5426 MenuList& items = _control_point_context_menu.items ();
5429 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5430 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5431 if (!can_remove_control_point (item)) {
5432 items.back().set_sensitive (false);
5435 _control_point_context_menu.popup (event->button.button, event->button.time);
5439 Editor::zoom_vertical_modifier_released()
5441 _stepping_axis_view = 0;