2 Copyright (C) 2000-2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* Note: public Editor methods are documented in public_editor.h */
30 #include "ardour_ui.h"
32 * ardour_ui.h include was moved to the top of the list
33 * due to a conflicting definition of 'Style' between
34 * Apple's MacTypes.h and BarController.
37 #include <boost/none.hpp>
39 #include <sigc++/bind.h>
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
48 #include "pbd/timersub.h"
50 #include <glibmm/miscutils.h>
51 #include <glibmm/uriutils.h>
52 #include <gtkmm/image.h>
53 #include <gdkmm/color.h>
54 #include <gdkmm/bitmap.h>
56 #include <gtkmm/menu.h>
57 #include <gtkmm/menuitem.h>
59 #include "gtkmm2ext/bindings.h"
60 #include "gtkmm2ext/grouped_buttons.h"
61 #include "gtkmm2ext/gtk_ui.h"
62 #include "gtkmm2ext/tearoff.h"
63 #include "gtkmm2ext/utils.h"
64 #include "gtkmm2ext/window_title.h"
65 #include "gtkmm2ext/choice.h"
66 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
68 #include "ardour/audio_track.h"
69 #include "ardour/audioengine.h"
70 #include "ardour/audioregion.h"
71 #include "ardour/location.h"
72 #include "ardour/profile.h"
73 #include "ardour/route_group.h"
74 #include "ardour/session_playlists.h"
75 #include "ardour/tempo.h"
76 #include "ardour/utils.h"
78 #include "canvas/debug.h"
79 #include "canvas/text.h"
81 #include "control_protocol/control_protocol.h"
85 #include "analysis_window.h"
86 #include "audio_clock.h"
87 #include "audio_region_view.h"
88 #include "audio_streamview.h"
89 #include "audio_time_axis.h"
90 #include "automation_time_axis.h"
91 #include "bundle_manager.h"
92 #include "crossfade_edit.h"
96 #include "editor_cursors.h"
97 #include "editor_drag.h"
98 #include "editor_group_tabs.h"
99 #include "editor_locations.h"
100 #include "editor_regions.h"
101 #include "editor_route_groups.h"
102 #include "editor_routes.h"
103 #include "editor_snapshots.h"
104 #include "editor_summary.h"
105 #include "global_port_matrix.h"
106 #include "gui_object.h"
107 #include "gui_thread.h"
108 #include "keyboard.h"
110 #include "midi_time_axis.h"
111 #include "mixer_strip.h"
112 #include "mixer_ui.h"
113 #include "mouse_cursors.h"
114 #include "playlist_selector.h"
115 #include "public_editor.h"
116 #include "region_layering_order_editor.h"
117 #include "rgb_macros.h"
118 #include "rhythm_ferret.h"
119 #include "selection.h"
121 #include "tempo_lines.h"
122 #include "time_axis_view.h"
124 #include "verbose_cursor.h"
129 using namespace ARDOUR;
130 using namespace ARDOUR_UI_UTILS;
133 using namespace Glib;
134 using namespace Gtkmm2ext;
135 using namespace Editing;
137 using PBD::internationalize;
139 using Gtkmm2ext::Keyboard;
141 const double Editor::timebar_height = 15.0;
143 static const gchar *_snap_type_strings[] = {
145 N_("Timecode Frames"),
146 N_("Timecode Seconds"),
147 N_("Timecode Minutes"),
177 static const gchar *_snap_mode_strings[] = {
184 static const gchar *_edit_point_strings[] = {
191 static const gchar *_zoom_focus_strings[] = {
201 #ifdef USE_RUBBERBAND
202 static const gchar *_rb_opt_strings[] = {
205 N_("Balanced multitimbral mixture"),
206 N_("Unpitched percussion with stable notes"),
207 N_("Crisp monophonic instrumental"),
208 N_("Unpitched solo percussion"),
209 N_("Resample without preserving pitch"),
215 pane_size_watcher (Paned* pane)
217 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
221 Quartz: impossible to access
223 so stop that by preventing it from ever getting too narrow. 35
224 pixels is basically a rough guess at the tab width.
229 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
231 gint pos = pane->get_position ();
233 if (pos > max_width_of_lhs) {
234 pane->set_position (max_width_of_lhs);
239 : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
241 /* time display buttons */
242 , minsec_label (_("Mins:Secs"))
243 , bbt_label (_("Bars:Beats"))
244 , timecode_label (_("Timecode"))
245 , samples_label (_("Samples"))
246 , tempo_label (_("Tempo"))
247 , meter_label (_("Meter"))
248 , mark_label (_("Location Markers"))
249 , range_mark_label (_("Range Markers"))
250 , transport_mark_label (_("Loop/Punch Ranges"))
251 , cd_mark_label (_("CD Markers"))
252 , videotl_label (_("Video Timeline"))
253 , edit_packer (4, 4, true)
255 /* the values here don't matter: layout widgets
256 reset them as needed.
259 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
260 , horizontal_adjustment (0.0, 0.0, 1e16)
261 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
263 , controls_layout (unused_adjustment, vertical_adjustment)
265 /* tool bar related */
267 , toolbar_selection_clock_table (2,3)
268 , _mouse_mode_tearoff (0)
269 , automation_mode_button (_("mode"))
273 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
277 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
278 , meters_running(false)
279 , _pending_locate_request (false)
280 , _pending_initial_locate (false)
281 , _last_cut_copy_source_track (0)
283 , _region_selection_change_updates_region_list (true)
284 , _following_mixer_selection (false)
285 , _control_point_toggled_on_press (false)
286 , _stepping_axis_view (0)
290 /* we are a singleton */
292 PublicEditor::_instance = this;
296 selection = new Selection (this);
297 cut_buffer = new Selection (this);
299 clicked_regionview = 0;
300 clicked_axisview = 0;
301 clicked_routeview = 0;
302 clicked_control_point = 0;
303 last_update_frame = 0;
304 pre_press_cursor = 0;
305 _drags = new DragManager (this);
308 current_mixer_strip = 0;
311 snap_type_strings = I18N (_snap_type_strings);
312 snap_mode_strings = I18N (_snap_mode_strings);
313 zoom_focus_strings = I18N (_zoom_focus_strings);
314 edit_point_strings = I18N (_edit_point_strings);
315 #ifdef USE_RUBBERBAND
316 rb_opt_strings = I18N (_rb_opt_strings);
320 build_edit_mode_menu();
321 build_zoom_focus_menu();
322 build_track_count_menu();
323 build_snap_mode_menu();
324 build_snap_type_menu();
325 build_edit_point_menu();
327 snap_threshold = 5.0;
328 bbt_beat_subdivision = 4;
329 _visible_canvas_width = 0;
330 _visible_canvas_height = 0;
331 autoscroll_horizontal_allowed = false;
332 autoscroll_vertical_allowed = false;
337 current_interthread_info = 0;
338 _show_measures = true;
340 show_gain_after_trim = false;
342 have_pending_keyboard_selection = false;
343 _follow_playhead = true;
344 _stationary_playhead = false;
345 editor_ruler_menu = 0;
346 no_ruler_shown_update = false;
348 range_marker_menu = 0;
349 marker_menu_item = 0;
350 tempo_or_meter_marker_menu = 0;
351 transport_marker_menu = 0;
352 new_transport_marker_menu = 0;
353 editor_mixer_strip_width = Wide;
354 show_editor_mixer_when_tracks_arrive = false;
355 region_edit_menu_split_multichannel_item = 0;
356 region_edit_menu_split_item = 0;
359 current_stepping_trackview = 0;
361 entered_regionview = 0;
363 clear_entered_track = false;
366 button_release_can_deselect = true;
367 _dragging_playhead = false;
368 _dragging_edit_point = false;
369 select_new_marker = false;
371 layering_order_editor = 0;
372 no_save_visual = false;
374 within_track_canvas = false;
376 scrubbing_direction = 0;
380 location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
381 location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
382 location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
383 location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
384 location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
386 zoom_focus = ZoomFocusLeft;
387 _edit_point = EditAtMouse;
388 _internal_editing = false;
389 current_canvas_cursor = 0;
390 _visible_track_count = 16;
392 samples_per_pixel = 2048; /* too early to use reset_zoom () */
394 _scroll_callbacks = 0;
396 bbt_label.set_name ("EditorRulerLabel");
397 bbt_label.set_size_request (-1, (int)timebar_height);
398 bbt_label.set_alignment (1.0, 0.5);
399 bbt_label.set_padding (5,0);
401 bbt_label.set_no_show_all();
402 minsec_label.set_name ("EditorRulerLabel");
403 minsec_label.set_size_request (-1, (int)timebar_height);
404 minsec_label.set_alignment (1.0, 0.5);
405 minsec_label.set_padding (5,0);
406 minsec_label.hide ();
407 minsec_label.set_no_show_all();
408 timecode_label.set_name ("EditorRulerLabel");
409 timecode_label.set_size_request (-1, (int)timebar_height);
410 timecode_label.set_alignment (1.0, 0.5);
411 timecode_label.set_padding (5,0);
412 timecode_label.hide ();
413 timecode_label.set_no_show_all();
414 samples_label.set_name ("EditorRulerLabel");
415 samples_label.set_size_request (-1, (int)timebar_height);
416 samples_label.set_alignment (1.0, 0.5);
417 samples_label.set_padding (5,0);
418 samples_label.hide ();
419 samples_label.set_no_show_all();
421 tempo_label.set_name ("EditorRulerLabel");
422 tempo_label.set_size_request (-1, (int)timebar_height);
423 tempo_label.set_alignment (1.0, 0.5);
424 tempo_label.set_padding (5,0);
426 tempo_label.set_no_show_all();
428 meter_label.set_name ("EditorRulerLabel");
429 meter_label.set_size_request (-1, (int)timebar_height);
430 meter_label.set_alignment (1.0, 0.5);
431 meter_label.set_padding (5,0);
433 meter_label.set_no_show_all();
435 if (Profile->get_trx()) {
436 mark_label.set_text (_("Markers"));
438 mark_label.set_name ("EditorRulerLabel");
439 mark_label.set_size_request (-1, (int)timebar_height);
440 mark_label.set_alignment (1.0, 0.5);
441 mark_label.set_padding (5,0);
443 mark_label.set_no_show_all();
445 cd_mark_label.set_name ("EditorRulerLabel");
446 cd_mark_label.set_size_request (-1, (int)timebar_height);
447 cd_mark_label.set_alignment (1.0, 0.5);
448 cd_mark_label.set_padding (5,0);
449 cd_mark_label.hide();
450 cd_mark_label.set_no_show_all();
452 videotl_bar_height = 4;
453 videotl_label.set_name ("EditorRulerLabel");
454 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
455 videotl_label.set_alignment (1.0, 0.5);
456 videotl_label.set_padding (5,0);
457 videotl_label.hide();
458 videotl_label.set_no_show_all();
460 range_mark_label.set_name ("EditorRulerLabel");
461 range_mark_label.set_size_request (-1, (int)timebar_height);
462 range_mark_label.set_alignment (1.0, 0.5);
463 range_mark_label.set_padding (5,0);
464 range_mark_label.hide();
465 range_mark_label.set_no_show_all();
467 transport_mark_label.set_name ("EditorRulerLabel");
468 transport_mark_label.set_size_request (-1, (int)timebar_height);
469 transport_mark_label.set_alignment (1.0, 0.5);
470 transport_mark_label.set_padding (5,0);
471 transport_mark_label.hide();
472 transport_mark_label.set_no_show_all();
474 initialize_canvas ();
476 _summary = new EditorSummary (this);
478 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
479 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
481 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
483 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
484 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
486 edit_controls_vbox.set_spacing (0);
487 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
488 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
490 HBox* h = manage (new HBox);
491 _group_tabs = new EditorGroupTabs (this);
492 if (!ARDOUR::Profile->get_trx()) {
493 h->pack_start (*_group_tabs, PACK_SHRINK);
495 h->pack_start (edit_controls_vbox);
496 controls_layout.add (*h);
498 controls_layout.set_name ("EditControlsBase");
499 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
500 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
501 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
503 _cursors = new MouseCursors;
504 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
505 cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
507 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
509 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
510 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
511 pad_line_1->set_outline_color (0xFF0000FF);
517 edit_packer.set_col_spacings (0);
518 edit_packer.set_row_spacings (0);
519 edit_packer.set_homogeneous (false);
520 edit_packer.set_border_width (0);
521 edit_packer.set_name ("EditorWindow");
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 /* labels for the time bars */
528 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
530 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
532 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
534 bottom_hbox.set_border_width (2);
535 bottom_hbox.set_spacing (3);
537 _route_groups = new EditorRouteGroups (this);
538 _routes = new EditorRoutes (this);
539 _regions = new EditorRegions (this);
540 _snapshots = new EditorSnapshots (this);
541 _locations = new EditorLocations (this);
543 add_notebook_page (_("Regions"), _regions->widget ());
544 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
545 add_notebook_page (_("Snapshots"), _snapshots->widget ());
546 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
547 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
549 _the_notebook.set_show_tabs (true);
550 _the_notebook.set_scrollable (true);
551 _the_notebook.popup_disable ();
552 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
553 _the_notebook.show_all ();
555 _notebook_shrunk = false;
557 editor_summary_pane.pack1(edit_packer);
559 Button* summary_arrows_left_left = manage (new Button);
560 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
561 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
562 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
564 Button* summary_arrows_left_right = manage (new Button);
565 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
566 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
567 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
569 VBox* summary_arrows_left = manage (new VBox);
570 summary_arrows_left->pack_start (*summary_arrows_left_left);
571 summary_arrows_left->pack_start (*summary_arrows_left_right);
573 Button* summary_arrows_right_up = manage (new Button);
574 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
575 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
576 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
578 Button* summary_arrows_right_down = manage (new Button);
579 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
580 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
581 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
583 VBox* summary_arrows_right = manage (new VBox);
584 summary_arrows_right->pack_start (*summary_arrows_right_up);
585 summary_arrows_right->pack_start (*summary_arrows_right_down);
587 Frame* summary_frame = manage (new Frame);
588 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
590 summary_frame->add (*_summary);
591 summary_frame->show ();
593 _summary_hbox.pack_start (*summary_arrows_left, false, false);
594 _summary_hbox.pack_start (*summary_frame, true, true);
595 _summary_hbox.pack_start (*summary_arrows_right, false, false);
597 if (!ARDOUR::Profile->get_trx()) {
598 editor_summary_pane.pack2 (_summary_hbox);
601 edit_pane.pack1 (editor_summary_pane, true, true);
602 if (!ARDOUR::Profile->get_trx()) {
603 edit_pane.pack2 (_the_notebook, false, true);
606 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
608 /* XXX: editor_summary_pane might need similar to the edit_pane */
610 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
612 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
613 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
615 top_hbox.pack_start (toolbar_frame);
617 HBox *hbox = manage (new HBox);
618 hbox->pack_start (edit_pane, true, true);
620 global_vpacker.pack_start (top_hbox, false, false);
621 global_vpacker.pack_start (*hbox, true, true);
623 global_hpacker.pack_start (global_vpacker, true, true);
625 set_name ("EditorWindow");
626 add_accel_group (ActionManager::ui_manager->get_accel_group());
628 status_bar_hpacker.show ();
630 vpacker.pack_end (status_bar_hpacker, false, false);
631 vpacker.pack_end (global_hpacker, true, true);
633 /* register actions now so that set_state() can find them and set toggles/checks etc */
636 /* when we start using our own keybinding system for the editor, this
637 * will be uncommented
643 set_zoom_focus (zoom_focus);
644 set_visible_track_count (_visible_track_count);
645 _snap_type = SnapToBeat;
646 set_snap_to (_snap_type);
647 _snap_mode = SnapOff;
648 set_snap_mode (_snap_mode);
649 set_mouse_mode (MouseObject, true);
650 pre_internal_mouse_mode = MouseObject;
651 pre_internal_snap_type = _snap_type;
652 pre_internal_snap_mode = _snap_mode;
653 internal_snap_type = _snap_type;
654 internal_snap_mode = _snap_mode;
655 set_edit_point_preference (EditAtMouse, true);
657 _playlist_selector = new PlaylistSelector();
658 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
660 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
664 nudge_forward_button.set_name ("nudge button");
665 // nudge_forward_button.add_elements (ArdourButton::Inset);
666 nudge_forward_button.set_image(::get_icon("nudge_right"));
668 nudge_backward_button.set_name ("nudge button");
669 // nudge_backward_button.add_elements (ArdourButton::Inset);
670 nudge_backward_button.set_image(::get_icon("nudge_left"));
672 fade_context_menu.set_name ("ArdourContextMenu");
674 /* icons, titles, WM stuff */
676 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
677 Glib::RefPtr<Gdk::Pixbuf> icon;
679 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
680 window_icons.push_back (icon);
682 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
683 window_icons.push_back (icon);
685 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
686 window_icons.push_back (icon);
688 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
689 window_icons.push_back (icon);
691 if (!window_icons.empty()) {
692 // set_icon_list (window_icons);
693 set_default_icon_list (window_icons);
696 WindowTitle title(Glib::get_application_name());
697 title += _("Editor");
698 set_title (title.get_string());
699 set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
702 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
704 signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
705 signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
707 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
709 /* allow external control surfaces/protocols to do various things */
711 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
712 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
713 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
714 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
715 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
716 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
717 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
718 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
719 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
720 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
721 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
722 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
723 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
724 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
726 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
727 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
728 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
729 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
730 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
732 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
734 /* problematic: has to return a value and thus cannot be x-thread */
736 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
738 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
739 ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
741 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
743 _ignore_region_action = false;
744 _last_region_menu_was_main = false;
745 _popup_region_menu_item = 0;
747 _show_marker_lines = false;
749 /* Button bindings */
751 button_bindings = new Bindings;
753 XMLNode* node = button_settings();
755 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
756 button_bindings->load (**i);
762 /* grab current parameter state */
763 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
764 ARDOUR_UI::config()->map_parameters (pc);
766 setup_fade_images ();
773 delete button_bindings;
775 delete _route_groups;
776 delete _track_canvas_viewport;
781 Editor::button_settings () const
783 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
784 XMLNode* node = find_named_node (*settings, X_("Buttons"));
787 node = new XMLNode (X_("Buttons"));
794 Editor::add_toplevel_controls (Container& cont)
796 vpacker.pack_start (cont, false, false);
801 Editor::get_smart_mode () const
803 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
807 Editor::catch_vanishing_regionview (RegionView *rv)
809 /* note: the selection will take care of the vanishing
810 audioregionview by itself.
813 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
817 if (clicked_regionview == rv) {
818 clicked_regionview = 0;
821 if (entered_regionview == rv) {
822 set_entered_regionview (0);
825 if (!_all_region_actions_sensitized) {
826 sensitize_all_region_actions (true);
831 Editor::set_entered_regionview (RegionView* rv)
833 if (rv == entered_regionview) {
837 if (entered_regionview) {
838 entered_regionview->exited ();
841 entered_regionview = rv;
843 if (entered_regionview != 0) {
844 entered_regionview->entered (internal_editing ());
847 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
848 /* This RegionView entry might have changed what region actions
849 are allowed, so sensitize them all in case a key is pressed.
851 sensitize_all_region_actions (true);
856 Editor::set_entered_track (TimeAxisView* tav)
859 entered_track->exited ();
865 entered_track->entered ();
870 Editor::show_window ()
872 if (!is_visible ()) {
875 /* XXX: this is a bit unfortunate; it would probably
876 be nicer if we could just call show () above rather
877 than needing the show_all ()
880 /* re-hide stuff if necessary */
881 editor_list_button_toggled ();
882 parameter_changed ("show-summary");
883 parameter_changed ("show-group-tabs");
884 parameter_changed ("show-zoom-tools");
886 /* now reset all audio_time_axis heights, because widgets might need
892 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
893 tv = (static_cast<TimeAxisView*>(*i));
897 if (current_mixer_strip) {
898 current_mixer_strip->hide_things ();
899 current_mixer_strip->parameter_changed ("mixer-strip-visibility");
907 Editor::instant_save ()
909 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
914 _session->add_instant_xml(get_state());
916 Config->add_instant_xml(get_state());
921 Editor::control_vertical_zoom_in_all ()
923 tav_zoom_smooth (false, true);
927 Editor::control_vertical_zoom_out_all ()
929 tav_zoom_smooth (true, true);
933 Editor::control_vertical_zoom_in_selected ()
935 tav_zoom_smooth (false, false);
939 Editor::control_vertical_zoom_out_selected ()
941 tav_zoom_smooth (true, false);
945 Editor::control_view (uint32_t view)
947 goto_visual_state (view);
951 Editor::control_unselect ()
953 selection->clear_tracks ();
957 Editor::control_select (uint32_t rid, Selection::Operation op)
959 /* handles the (static) signal from the ControlProtocol class that
960 * requests setting the selected track to a given RID
967 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
973 TimeAxisView* tav = axis_view_from_route (r);
978 selection->add (tav);
980 case Selection::Toggle:
981 selection->toggle (tav);
983 case Selection::Extend:
986 selection->set (tav);
990 selection->clear_tracks ();
995 Editor::control_step_tracks_up ()
997 scroll_tracks_up_line ();
1001 Editor::control_step_tracks_down ()
1003 scroll_tracks_down_line ();
1007 Editor::control_scroll (float fraction)
1009 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1015 double step = fraction * current_page_samples();
1018 _control_scroll_target is an optional<T>
1020 it acts like a pointer to an framepos_t, with
1021 a operator conversion to boolean to check
1022 that it has a value could possibly use
1023 playhead_cursor->current_frame to store the
1024 value and a boolean in the class to know
1025 when it's out of date
1028 if (!_control_scroll_target) {
1029 _control_scroll_target = _session->transport_frame();
1030 _dragging_playhead = true;
1033 if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
1034 *_control_scroll_target = 0;
1035 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1036 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1038 *_control_scroll_target += (framepos_t) floor (step);
1041 /* move visuals, we'll catch up with it later */
1043 playhead_cursor->set_position (*_control_scroll_target);
1044 UpdateAllTransportClocks (*_control_scroll_target);
1046 if (*_control_scroll_target > (current_page_samples() / 2)) {
1047 /* try to center PH in window */
1048 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1054 Now we do a timeout to actually bring the session to the right place
1055 according to the playhead. This is to avoid reading disk buffers on every
1056 call to control_scroll, which is driven by ScrollTimeline and therefore
1057 probably by a control surface wheel which can generate lots of events.
1059 /* cancel the existing timeout */
1061 control_scroll_connection.disconnect ();
1063 /* add the next timeout */
1065 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1069 Editor::deferred_control_scroll (framepos_t /*target*/)
1071 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1072 // reset for next stream
1073 _control_scroll_target = boost::none;
1074 _dragging_playhead = false;
1079 Editor::access_action (std::string action_group, std::string action_item)
1085 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1088 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1096 Editor::on_realize ()
1098 Window::on_realize ();
1101 if (ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1102 start_lock_event_timing ();
1105 signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
1109 Editor::start_lock_event_timing ()
1111 /* check if we should lock the GUI every 30 seconds */
1113 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1117 Editor::generic_event_handler (GdkEvent* ev)
1120 case GDK_BUTTON_PRESS:
1121 case GDK_BUTTON_RELEASE:
1122 case GDK_MOTION_NOTIFY:
1124 case GDK_KEY_RELEASE:
1125 gettimeofday (&last_event_time, 0);
1134 Editor::lock_timeout_callback ()
1136 struct timeval now, delta;
1138 gettimeofday (&now, 0);
1140 timersub (&now, &last_event_time, &delta);
1142 if (delta.tv_sec > ARDOUR_UI::config()->get_lock_gui_after_seconds()) {
1144 /* don't call again. Returning false will effectively
1145 disconnect us from the timer callback.
1147 unlock() will call start_lock_event_timing() to get things
1157 Editor::map_position_change (framepos_t frame)
1159 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1161 if (_session == 0) {
1165 if (_follow_playhead) {
1166 center_screen (frame);
1169 playhead_cursor->set_position (frame);
1173 Editor::center_screen (framepos_t frame)
1175 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1177 /* if we're off the page, then scroll.
1180 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1181 center_screen_internal (frame, page);
1186 Editor::center_screen_internal (framepos_t frame, float page)
1191 frame -= (framepos_t) page;
1196 reset_x_origin (frame);
1201 Editor::update_title ()
1203 ENSURE_GUI_THREAD (*this, &Editor::update_title)
1206 bool dirty = _session->dirty();
1208 string session_name;
1210 if (_session->snap_name() != _session->name()) {
1211 session_name = _session->snap_name();
1213 session_name = _session->name();
1217 session_name = "*" + session_name;
1220 WindowTitle title(session_name);
1221 title += Glib::get_application_name();
1222 set_title (title.get_string());
1224 /* ::session_going_away() will have taken care of it */
1229 Editor::set_session (Session *t)
1231 SessionHandlePtr::set_session (t);
1237 _playlist_selector->set_session (_session);
1238 nudge_clock->set_session (_session);
1239 _summary->set_session (_session);
1240 _group_tabs->set_session (_session);
1241 _route_groups->set_session (_session);
1242 _regions->set_session (_session);
1243 _snapshots->set_session (_session);
1244 _routes->set_session (_session);
1245 _locations->set_session (_session);
1247 if (rhythm_ferret) {
1248 rhythm_ferret->set_session (_session);
1251 if (analysis_window) {
1252 analysis_window->set_session (_session);
1256 sfbrowser->set_session (_session);
1259 compute_fixed_ruler_scale ();
1261 /* Make sure we have auto loop and auto punch ranges */
1263 Location* loc = _session->locations()->auto_loop_location();
1265 loc->set_name (_("Loop"));
1268 loc = _session->locations()->auto_punch_location();
1271 loc->set_name (_("Punch"));
1274 refresh_location_display ();
1276 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1277 the selected Marker; this needs the LocationMarker list to be available.
1279 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1280 set_state (*node, Stateful::loading_state_version);
1282 /* catch up with the playhead */
1284 _session->request_locate (playhead_cursor->current_frame ());
1285 _pending_initial_locate = true;
1289 /* These signals can all be emitted by a non-GUI thread. Therefore the
1290 handlers for them must not attempt to directly interact with the GUI,
1291 but use PBD::Signal<T>::connect() which accepts an event loop
1292 ("context") where the handler will be asked to run.
1295 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1296 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1297 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1298 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1299 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1300 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1301 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1302 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1303 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1304 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1305 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1306 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1307 _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1308 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1310 playhead_cursor->show ();
1312 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1313 Config->map_parameters (pc);
1314 _session->config.map_parameters (pc);
1316 restore_ruler_visibility ();
1317 //tempo_map_changed (PropertyChange (0));
1318 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1320 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1321 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1324 super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1325 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1328 switch (_snap_type) {
1329 case SnapToRegionStart:
1330 case SnapToRegionEnd:
1331 case SnapToRegionSync:
1332 case SnapToRegionBoundary:
1333 build_region_boundary_cache ();
1340 /* register for undo history */
1341 _session->register_with_memento_command_factory(id(), this);
1343 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1345 start_updating_meters ();
1349 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1351 if (a->get_name() == "RegionMenu") {
1352 /* When the main menu's region menu is opened, we setup the actions so that they look right
1353 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1354 so we resensitize all region actions when the entered regionview or the region selection
1355 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1356 happens after the region context menu is opened. So we set a flag here, too.
1360 sensitize_the_right_region_actions ();
1361 _last_region_menu_was_main = true;
1366 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1368 using namespace Menu_Helpers;
1370 void (Editor::*emf)(FadeShape);
1371 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1374 images = &_xfade_in_images;
1375 emf = &Editor::set_fade_in_shape;
1377 images = &_xfade_out_images;
1378 emf = &Editor::set_fade_out_shape;
1383 _("Linear (for highly correlated material)"),
1384 *(*images)[FadeLinear],
1385 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1389 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1393 _("Constant power"),
1394 *(*images)[FadeConstantPower],
1395 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1398 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1403 *(*images)[FadeSymmetric],
1404 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1408 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1413 *(*images)[FadeSlow],
1414 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1417 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1422 *(*images)[FadeFast],
1423 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1426 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1429 /** Pop up a context menu for when the user clicks on a start crossfade */
1431 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1433 using namespace Menu_Helpers;
1434 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1437 MenuList& items (xfade_in_context_menu.items());
1440 if (arv->audio_region()->fade_in_active()) {
1441 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1443 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1446 items.push_back (SeparatorElem());
1447 fill_xfade_menu (items, true);
1449 xfade_in_context_menu.popup (button, time);
1452 /** Pop up a context menu for when the user clicks on an end crossfade */
1454 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1456 using namespace Menu_Helpers;
1457 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1460 MenuList& items (xfade_out_context_menu.items());
1463 if (arv->audio_region()->fade_out_active()) {
1464 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1466 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1469 items.push_back (SeparatorElem());
1470 fill_xfade_menu (items, false);
1472 xfade_out_context_menu.popup (button, time);
1476 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1478 using namespace Menu_Helpers;
1479 Menu* (Editor::*build_menu_function)();
1482 switch (item_type) {
1484 case RegionViewName:
1485 case RegionViewNameHighlight:
1486 case LeftFrameHandle:
1487 case RightFrameHandle:
1488 if (with_selection) {
1489 build_menu_function = &Editor::build_track_selection_context_menu;
1491 build_menu_function = &Editor::build_track_region_context_menu;
1496 if (with_selection) {
1497 build_menu_function = &Editor::build_track_selection_context_menu;
1499 build_menu_function = &Editor::build_track_context_menu;
1504 if (clicked_routeview->track()) {
1505 build_menu_function = &Editor::build_track_context_menu;
1507 build_menu_function = &Editor::build_track_bus_context_menu;
1512 /* probably shouldn't happen but if it does, we don't care */
1516 menu = (this->*build_menu_function)();
1517 menu->set_name ("ArdourContextMenu");
1519 /* now handle specific situations */
1521 switch (item_type) {
1523 case RegionViewName:
1524 case RegionViewNameHighlight:
1525 case LeftFrameHandle:
1526 case RightFrameHandle:
1527 if (!with_selection) {
1528 if (region_edit_menu_split_item) {
1529 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1530 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1532 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1535 if (region_edit_menu_split_multichannel_item) {
1536 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1537 region_edit_menu_split_multichannel_item->set_sensitive (true);
1539 region_edit_menu_split_multichannel_item->set_sensitive (false);
1552 /* probably shouldn't happen but if it does, we don't care */
1556 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1558 /* Bounce to disk */
1560 using namespace Menu_Helpers;
1561 MenuList& edit_items = menu->items();
1563 edit_items.push_back (SeparatorElem());
1565 switch (clicked_routeview->audio_track()->freeze_state()) {
1566 case AudioTrack::NoFreeze:
1567 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1570 case AudioTrack::Frozen:
1571 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1574 case AudioTrack::UnFrozen:
1575 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1581 if (item_type == StreamItem && clicked_routeview) {
1582 clicked_routeview->build_underlay_menu(menu);
1585 /* When the region menu is opened, we setup the actions so that they look right
1588 sensitize_the_right_region_actions ();
1589 _last_region_menu_was_main = false;
1591 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1592 menu->popup (button, time);
1596 Editor::build_track_context_menu ()
1598 using namespace Menu_Helpers;
1600 MenuList& edit_items = track_context_menu.items();
1603 add_dstream_context_items (edit_items);
1604 return &track_context_menu;
1608 Editor::build_track_bus_context_menu ()
1610 using namespace Menu_Helpers;
1612 MenuList& edit_items = track_context_menu.items();
1615 add_bus_context_items (edit_items);
1616 return &track_context_menu;
1620 Editor::build_track_region_context_menu ()
1622 using namespace Menu_Helpers;
1623 MenuList& edit_items = track_region_context_menu.items();
1626 /* we've just cleared the track region context menu, so the menu that these
1627 two items were on will have disappeared; stop them dangling.
1629 region_edit_menu_split_item = 0;
1630 region_edit_menu_split_multichannel_item = 0;
1632 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1635 boost::shared_ptr<Track> tr;
1636 boost::shared_ptr<Playlist> pl;
1638 if ((tr = rtv->track())) {
1639 add_region_context_items (edit_items, tr);
1643 add_dstream_context_items (edit_items);
1645 return &track_region_context_menu;
1649 Editor::analyze_region_selection ()
1651 if (analysis_window == 0) {
1652 analysis_window = new AnalysisWindow();
1655 analysis_window->set_session(_session);
1657 analysis_window->show_all();
1660 analysis_window->set_regionmode();
1661 analysis_window->analyze();
1663 analysis_window->present();
1667 Editor::analyze_range_selection()
1669 if (analysis_window == 0) {
1670 analysis_window = new AnalysisWindow();
1673 analysis_window->set_session(_session);
1675 analysis_window->show_all();
1678 analysis_window->set_rangemode();
1679 analysis_window->analyze();
1681 analysis_window->present();
1685 Editor::build_track_selection_context_menu ()
1687 using namespace Menu_Helpers;
1688 MenuList& edit_items = track_selection_context_menu.items();
1689 edit_items.clear ();
1691 add_selection_context_items (edit_items);
1692 // edit_items.push_back (SeparatorElem());
1693 // add_dstream_context_items (edit_items);
1695 return &track_selection_context_menu;
1699 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1701 using namespace Menu_Helpers;
1703 /* OK, stick the region submenu at the top of the list, and then add
1707 RegionSelection rs = get_regions_from_selection_and_entered ();
1709 string::size_type pos = 0;
1710 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1712 /* we have to hack up the region name because "_" has a special
1713 meaning for menu titles.
1716 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1717 menu_item_name.replace (pos, 1, "__");
1721 if (_popup_region_menu_item == 0) {
1722 _popup_region_menu_item = new MenuItem (menu_item_name);
1723 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1724 _popup_region_menu_item->show ();
1726 _popup_region_menu_item->set_label (menu_item_name);
1729 const framepos_t position = get_preferred_edit_position (false, true);
1731 edit_items.push_back (*_popup_region_menu_item);
1732 if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1733 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1735 edit_items.push_back (SeparatorElem());
1738 /** Add context menu items relevant to selection ranges.
1739 * @param edit_items List to add the items to.
1742 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1744 using namespace Menu_Helpers;
1746 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1747 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1749 edit_items.push_back (SeparatorElem());
1750 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1752 edit_items.push_back (SeparatorElem());
1754 edit_items.push_back (
1756 _("Move Range Start to Previous Region Boundary"),
1757 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1761 edit_items.push_back (
1763 _("Move Range Start to Next Region Boundary"),
1764 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1768 edit_items.push_back (
1770 _("Move Range End to Previous Region Boundary"),
1771 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1775 edit_items.push_back (
1777 _("Move Range End to Next Region Boundary"),
1778 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1782 edit_items.push_back (SeparatorElem());
1783 edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1784 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1786 edit_items.push_back (SeparatorElem());
1787 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1789 edit_items.push_back (SeparatorElem());
1790 edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1791 edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1793 edit_items.push_back (SeparatorElem());
1794 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1796 edit_items.push_back (SeparatorElem());
1797 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1798 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1799 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1801 edit_items.push_back (SeparatorElem());
1802 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1803 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1804 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1805 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1806 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1807 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1808 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1814 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1816 using namespace Menu_Helpers;
1820 Menu *play_menu = manage (new Menu);
1821 MenuList& play_items = play_menu->items();
1822 play_menu->set_name ("ArdourContextMenu");
1824 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1825 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1826 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1827 play_items.push_back (SeparatorElem());
1828 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1830 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1834 Menu *select_menu = manage (new Menu);
1835 MenuList& select_items = select_menu->items();
1836 select_menu->set_name ("ArdourContextMenu");
1838 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1839 select_items.push_back (MenuElem (_("Select All Regions"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_regions), Selection::Set)));
1840 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1841 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1842 select_items.push_back (SeparatorElem());
1843 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1844 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1845 select_items.push_back (SeparatorElem());
1846 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1847 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1848 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1849 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1850 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1851 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1852 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1854 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1858 Menu *cutnpaste_menu = manage (new Menu);
1859 MenuList& cutnpaste_items = cutnpaste_menu->items();
1860 cutnpaste_menu->set_name ("ArdourContextMenu");
1862 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1863 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1864 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1866 cutnpaste_items.push_back (SeparatorElem());
1868 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1869 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1871 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1873 /* Adding new material */
1875 edit_items.push_back (SeparatorElem());
1876 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1877 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1881 Menu *nudge_menu = manage (new Menu());
1882 MenuList& nudge_items = nudge_menu->items();
1883 nudge_menu->set_name ("ArdourContextMenu");
1885 edit_items.push_back (SeparatorElem());
1886 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1887 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1888 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1889 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1891 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1895 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1897 using namespace Menu_Helpers;
1901 Menu *play_menu = manage (new Menu);
1902 MenuList& play_items = play_menu->items();
1903 play_menu->set_name ("ArdourContextMenu");
1905 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1906 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1907 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1911 Menu *select_menu = manage (new Menu);
1912 MenuList& select_items = select_menu->items();
1913 select_menu->set_name ("ArdourContextMenu");
1915 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1916 select_items.push_back (MenuElem (_("Select All Regions"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_regions), Selection::Set)));
1917 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1918 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1919 select_items.push_back (SeparatorElem());
1920 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1921 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1922 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1923 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1925 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1929 Menu *cutnpaste_menu = manage (new Menu);
1930 MenuList& cutnpaste_items = cutnpaste_menu->items();
1931 cutnpaste_menu->set_name ("ArdourContextMenu");
1933 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1934 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1935 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1937 Menu *nudge_menu = manage (new Menu());
1938 MenuList& nudge_items = nudge_menu->items();
1939 nudge_menu->set_name ("ArdourContextMenu");
1941 edit_items.push_back (SeparatorElem());
1942 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1943 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1944 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1945 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1947 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1951 Editor::snap_type() const
1957 Editor::snap_mode() const
1963 Editor::set_snap_to (SnapType st)
1965 unsigned int snap_ind = (unsigned int)st;
1969 if (snap_ind > snap_type_strings.size() - 1) {
1971 _snap_type = (SnapType)snap_ind;
1974 string str = snap_type_strings[snap_ind];
1976 if (str != snap_type_selector.get_text()) {
1977 snap_type_selector.set_text (str);
1982 switch (_snap_type) {
1983 case SnapToBeatDiv128:
1984 case SnapToBeatDiv64:
1985 case SnapToBeatDiv32:
1986 case SnapToBeatDiv28:
1987 case SnapToBeatDiv24:
1988 case SnapToBeatDiv20:
1989 case SnapToBeatDiv16:
1990 case SnapToBeatDiv14:
1991 case SnapToBeatDiv12:
1992 case SnapToBeatDiv10:
1993 case SnapToBeatDiv8:
1994 case SnapToBeatDiv7:
1995 case SnapToBeatDiv6:
1996 case SnapToBeatDiv5:
1997 case SnapToBeatDiv4:
1998 case SnapToBeatDiv3:
1999 case SnapToBeatDiv2: {
2000 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2001 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2003 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
2004 current_bbt_points_begin, current_bbt_points_end);
2005 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
2006 current_bbt_points_begin, current_bbt_points_end);
2007 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2011 case SnapToRegionStart:
2012 case SnapToRegionEnd:
2013 case SnapToRegionSync:
2014 case SnapToRegionBoundary:
2015 build_region_boundary_cache ();
2023 SnapChanged (); /* EMIT SIGNAL */
2027 Editor::set_snap_mode (SnapMode mode)
2029 string str = snap_mode_strings[(int)mode];
2031 if (_internal_editing) {
2032 internal_snap_mode = mode;
2034 pre_internal_snap_mode = mode;
2039 if (str != snap_mode_selector.get_text ()) {
2040 snap_mode_selector.set_text (str);
2046 Editor::set_edit_point_preference (EditPoint ep, bool force)
2048 bool changed = (_edit_point != ep);
2051 string str = edit_point_strings[(int)ep];
2053 if (str != edit_point_selector.get_text ()) {
2054 edit_point_selector.set_text (str);
2057 reset_canvas_cursor ();
2059 if (!force && !changed) {
2063 const char* action=NULL;
2065 switch (_edit_point) {
2066 case EditAtPlayhead:
2067 action = "edit-at-playhead";
2069 case EditAtSelectedMarker:
2070 action = "edit-at-marker";
2073 action = "edit-at-mouse";
2077 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2079 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2083 bool in_track_canvas;
2085 if (!mouse_frame (foo, in_track_canvas)) {
2086 in_track_canvas = false;
2089 reset_canvas_action_sensitivity (in_track_canvas);
2095 Editor::set_state (const XMLNode& node, int /*version*/)
2097 const XMLProperty* prop;
2104 g.base_width = default_width;
2105 g.base_height = default_height;
2109 if ((geometry = find_named_node (node, "geometry")) != 0) {
2113 if ((prop = geometry->property("x_size")) == 0) {
2114 prop = geometry->property ("x-size");
2117 g.base_width = atoi(prop->value());
2119 if ((prop = geometry->property("y_size")) == 0) {
2120 prop = geometry->property ("y-size");
2123 g.base_height = atoi(prop->value());
2126 if ((prop = geometry->property ("x_pos")) == 0) {
2127 prop = geometry->property ("x-pos");
2130 x = atoi (prop->value());
2133 if ((prop = geometry->property ("y_pos")) == 0) {
2134 prop = geometry->property ("y-pos");
2137 y = atoi (prop->value());
2141 set_default_size (g.base_width, g.base_height);
2144 if (_session && (prop = node.property ("playhead"))) {
2146 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2147 playhead_cursor->set_position (pos);
2149 playhead_cursor->set_position (0);
2152 if ((prop = node.property ("mixer-width"))) {
2153 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2156 if ((prop = node.property ("zoom-focus"))) {
2157 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2160 if ((prop = node.property ("zoom"))) {
2161 /* older versions of ardour used floating point samples_per_pixel */
2162 double f = PBD::atof (prop->value());
2163 reset_zoom (llrintf (f));
2165 reset_zoom (samples_per_pixel);
2168 if ((prop = node.property ("visible-track-count"))) {
2169 set_visible_track_count (PBD::atoi (prop->value()));
2172 if ((prop = node.property ("snap-to"))) {
2173 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2176 if ((prop = node.property ("snap-mode"))) {
2177 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2180 if ((prop = node.property ("internal-snap-to"))) {
2181 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2184 if ((prop = node.property ("internal-snap-mode"))) {
2185 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2188 if ((prop = node.property ("pre-internal-snap-to"))) {
2189 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2193 if ((prop = node.property ("pre-internal-snap-mode"))) {
2194 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2197 if ((prop = node.property ("mouse-mode"))) {
2198 MouseMode m = str2mousemode(prop->value());
2199 set_mouse_mode (m, true);
2201 set_mouse_mode (MouseObject, true);
2204 if ((prop = node.property ("left-frame")) != 0) {
2206 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2210 reset_x_origin (pos);
2214 if ((prop = node.property ("y-origin")) != 0) {
2215 reset_y_origin (atof (prop->value ()));
2218 if ((prop = node.property ("internal-edit"))) {
2219 bool yn = string_is_affirmative (prop->value());
2220 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2222 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2223 tact->set_active (!yn);
2224 tact->set_active (yn);
2228 if ((prop = node.property ("join-object-range"))) {
2229 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2230 bool yn = string_is_affirmative (prop->value());
2232 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2233 tact->set_active (!yn);
2234 tact->set_active (yn);
2236 set_mouse_mode(mouse_mode, true);
2239 if ((prop = node.property ("edit-point"))) {
2240 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2243 if ((prop = node.property ("show-measures"))) {
2244 bool yn = string_is_affirmative (prop->value());
2245 _show_measures = yn;
2246 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2248 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2249 /* do it twice to force the change */
2250 tact->set_active (!yn);
2251 tact->set_active (yn);
2255 if ((prop = node.property ("follow-playhead"))) {
2256 bool yn = string_is_affirmative (prop->value());
2257 set_follow_playhead (yn);
2258 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2260 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2261 if (tact->get_active() != yn) {
2262 tact->set_active (yn);
2267 if ((prop = node.property ("stationary-playhead"))) {
2268 bool yn = string_is_affirmative (prop->value());
2269 set_stationary_playhead (yn);
2270 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2272 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2273 if (tact->get_active() != yn) {
2274 tact->set_active (yn);
2279 if ((prop = node.property ("region-list-sort-type"))) {
2280 RegionListSortType st;
2281 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2284 if ((prop = node.property ("show-editor-mixer"))) {
2286 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2289 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2290 bool yn = string_is_affirmative (prop->value());
2292 /* do it twice to force the change */
2294 tact->set_active (!yn);
2295 tact->set_active (yn);
2298 if ((prop = node.property ("show-editor-list"))) {
2300 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2303 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2304 bool yn = string_is_affirmative (prop->value());
2306 /* do it twice to force the change */
2308 tact->set_active (!yn);
2309 tact->set_active (yn);
2312 if ((prop = node.property (X_("editor-list-page")))) {
2313 _the_notebook.set_current_page (atoi (prop->value ()));
2316 if ((prop = node.property (X_("show-marker-lines")))) {
2317 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2319 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2320 bool yn = string_is_affirmative (prop->value ());
2322 tact->set_active (!yn);
2323 tact->set_active (yn);
2326 XMLNodeList children = node.children ();
2327 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2328 selection->set_state (**i, Stateful::current_state_version);
2329 _regions->set_state (**i);
2332 if ((prop = node.property ("maximised"))) {
2333 bool yn = string_is_affirmative (prop->value());
2334 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2336 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2337 bool fs = tact && tact->get_active();
2339 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2343 if ((prop = node.property ("nudge-clock-value"))) {
2345 sscanf (prop->value().c_str(), "%" PRId64, &f);
2346 nudge_clock->set (f);
2348 nudge_clock->set_mode (AudioClock::Timecode);
2349 nudge_clock->set (_session->frame_rate() * 5, true);
2356 Editor::get_state ()
2358 XMLNode* node = new XMLNode ("Editor");
2361 id().print (buf, sizeof (buf));
2362 node->add_property ("id", buf);
2364 if (is_realized()) {
2365 Glib::RefPtr<Gdk::Window> win = get_window();
2367 int x, y, width, height;
2368 win->get_root_origin(x, y);
2369 win->get_size(width, height);
2371 XMLNode* geometry = new XMLNode ("geometry");
2373 snprintf(buf, sizeof(buf), "%d", width);
2374 geometry->add_property("x-size", string(buf));
2375 snprintf(buf, sizeof(buf), "%d", height);
2376 geometry->add_property("y-size", string(buf));
2377 snprintf(buf, sizeof(buf), "%d", x);
2378 geometry->add_property("x-pos", string(buf));
2379 snprintf(buf, sizeof(buf), "%d", y);
2380 geometry->add_property("y-pos", string(buf));
2381 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2382 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2383 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2384 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2385 geometry->add_property("edit-vertical-pane-pos", string(buf));
2387 node->add_child_nocopy (*geometry);
2390 maybe_add_mixer_strip_width (*node);
2392 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2394 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2395 node->add_property ("zoom", buf);
2396 node->add_property ("snap-to", enum_2_string (_snap_type));
2397 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2398 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2399 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2400 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2401 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2402 node->add_property ("edit-point", enum_2_string (_edit_point));
2403 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2404 node->add_property ("visible-track-count", buf);
2406 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2407 node->add_property ("playhead", buf);
2408 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2409 node->add_property ("left-frame", buf);
2410 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2411 node->add_property ("y-origin", buf);
2413 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2414 node->add_property ("maximised", _maximised ? "yes" : "no");
2415 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2416 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2417 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2418 node->add_property ("mouse-mode", enum2str(mouse_mode));
2419 node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2420 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2422 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2424 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2425 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2428 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2430 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2431 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2434 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2435 node->add_property (X_("editor-list-page"), buf);
2437 if (button_bindings) {
2438 XMLNode* bb = new XMLNode (X_("Buttons"));
2439 button_bindings->save (*bb);
2440 node->add_child_nocopy (*bb);
2443 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2445 node->add_child_nocopy (selection->get_state ());
2446 node->add_child_nocopy (_regions->get_state ());
2448 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2449 node->add_property ("nudge-clock-value", buf);
2454 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2455 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2457 * @return pair: TimeAxisView that y is over, layer index.
2459 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2460 * in stacked or expanded region display mode, otherwise 0.
2462 std::pair<TimeAxisView *, double>
2463 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2465 if (!trackview_relative_offset) {
2466 y -= _trackview_group->canvas_origin().y;
2470 return std::make_pair ( (TimeAxisView *) 0, 0);
2473 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2475 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2482 return std::make_pair ( (TimeAxisView *) 0, 0);
2485 /** Snap a position to the grid, if appropriate, taking into account current
2486 * grid settings and also the state of any snap modifier keys that may be pressed.
2487 * @param start Position to snap.
2488 * @param event Event to get current key modifier information from, or 0.
2491 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2493 if (!_session || !event) {
2497 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2498 if (_snap_mode == SnapOff) {
2499 snap_to_internal (start, direction, for_mark);
2502 if (_snap_mode != SnapOff) {
2503 snap_to_internal (start, direction, for_mark);
2509 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2511 if (!_session || _snap_mode == SnapOff) {
2515 snap_to_internal (start, direction, for_mark);
2519 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2521 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2522 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2524 switch (_snap_type) {
2525 case SnapToTimecodeFrame:
2526 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2527 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2529 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2533 case SnapToTimecodeSeconds:
2534 if (_session->config.get_timecode_offset_negative()) {
2535 start += _session->config.get_timecode_offset ();
2537 start -= _session->config.get_timecode_offset ();
2539 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2540 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2542 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2545 if (_session->config.get_timecode_offset_negative()) {
2546 start -= _session->config.get_timecode_offset ();
2548 start += _session->config.get_timecode_offset ();
2552 case SnapToTimecodeMinutes:
2553 if (_session->config.get_timecode_offset_negative()) {
2554 start += _session->config.get_timecode_offset ();
2556 start -= _session->config.get_timecode_offset ();
2558 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2559 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2561 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2563 if (_session->config.get_timecode_offset_negative()) {
2564 start -= _session->config.get_timecode_offset ();
2566 start += _session->config.get_timecode_offset ();
2570 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2576 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2578 const framepos_t one_second = _session->frame_rate();
2579 const framepos_t one_minute = _session->frame_rate() * 60;
2580 framepos_t presnap = start;
2584 switch (_snap_type) {
2585 case SnapToTimecodeFrame:
2586 case SnapToTimecodeSeconds:
2587 case SnapToTimecodeMinutes:
2588 return timecode_snap_to_internal (start, direction, for_mark);
2591 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2592 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2594 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2599 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2600 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2602 start = (framepos_t) floor ((double) start / one_second) * one_second;
2607 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2608 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2610 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2615 start = _session->tempo_map().round_to_bar (start, direction);
2619 start = _session->tempo_map().round_to_beat (start, direction);
2622 case SnapToBeatDiv128:
2623 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2625 case SnapToBeatDiv64:
2626 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2628 case SnapToBeatDiv32:
2629 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2631 case SnapToBeatDiv28:
2632 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2634 case SnapToBeatDiv24:
2635 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2637 case SnapToBeatDiv20:
2638 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2640 case SnapToBeatDiv16:
2641 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2643 case SnapToBeatDiv14:
2644 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2646 case SnapToBeatDiv12:
2647 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2649 case SnapToBeatDiv10:
2650 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2652 case SnapToBeatDiv8:
2653 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2655 case SnapToBeatDiv7:
2656 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2658 case SnapToBeatDiv6:
2659 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2661 case SnapToBeatDiv5:
2662 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2664 case SnapToBeatDiv4:
2665 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2667 case SnapToBeatDiv3:
2668 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2670 case SnapToBeatDiv2:
2671 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2679 _session->locations()->marks_either_side (start, before, after);
2681 if (before == max_framepos && after == max_framepos) {
2682 /* No marks to snap to, so just don't snap */
2684 } else if (before == max_framepos) {
2686 } else if (after == max_framepos) {
2688 } else if (before != max_framepos && after != max_framepos) {
2689 /* have before and after */
2690 if ((start - before) < (after - start)) {
2699 case SnapToRegionStart:
2700 case SnapToRegionEnd:
2701 case SnapToRegionSync:
2702 case SnapToRegionBoundary:
2703 if (!region_boundary_cache.empty()) {
2705 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2706 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2708 if (direction > 0) {
2709 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2711 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2714 if (next != region_boundary_cache.begin ()) {
2719 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2720 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2722 if (start > (p + n) / 2) {
2731 switch (_snap_mode) {
2737 if (presnap > start) {
2738 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2742 } else if (presnap < start) {
2743 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2749 /* handled at entry */
2757 Editor::setup_toolbar ()
2759 HBox* mode_box = manage(new HBox);
2760 mode_box->set_border_width (2);
2761 mode_box->set_spacing(4);
2763 HBox* mouse_mode_box = manage (new HBox);
2764 HBox* mouse_mode_hbox = manage (new HBox);
2765 VBox* mouse_mode_vbox = manage (new VBox);
2766 Alignment* mouse_mode_align = manage (new Alignment);
2768 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
2769 // mouse_mode_size_group->add_widget (smart_mode_button);
2770 mouse_mode_size_group->add_widget (mouse_move_button);
2771 mouse_mode_size_group->add_widget (mouse_select_button);
2772 mouse_mode_size_group->add_widget (mouse_zoom_button);
2773 mouse_mode_size_group->add_widget (mouse_gain_button);
2774 mouse_mode_size_group->add_widget (mouse_timefx_button);
2775 mouse_mode_size_group->add_widget (mouse_audition_button);
2776 mouse_mode_size_group->add_widget (mouse_draw_button);
2777 mouse_mode_size_group->add_widget (internal_edit_button);
2779 /* make them just a bit bigger */
2780 mouse_move_button.set_size_request (-1, 30);
2782 mouse_mode_hbox->set_spacing (2);
2784 if (!ARDOUR::Profile->get_trx()) {
2785 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2788 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2789 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2790 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2792 if (!ARDOUR::Profile->get_trx()) {
2793 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2794 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2795 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2796 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2797 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
2800 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2802 mouse_mode_align->add (*mouse_mode_vbox);
2803 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2805 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2807 edit_mode_selector.set_name ("mouse mode button");
2808 edit_mode_selector.set_size_request (65, -1);
2809 edit_mode_selector.add_elements (ArdourButton::Inset);
2811 if (!ARDOUR::Profile->get_trx()) {
2812 mode_box->pack_start (edit_mode_selector, false, false);
2814 mode_box->pack_start (*mouse_mode_box, false, false);
2816 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2817 _mouse_mode_tearoff->set_name ("MouseModeBase");
2818 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2820 if (Profile->get_sae()) {
2821 _mouse_mode_tearoff->set_can_be_torn_off (false);
2824 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2825 &_mouse_mode_tearoff->tearoff_window()));
2826 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2827 &_mouse_mode_tearoff->tearoff_window(), 1));
2828 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2829 &_mouse_mode_tearoff->tearoff_window()));
2830 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2831 &_mouse_mode_tearoff->tearoff_window(), 1));
2835 _zoom_box.set_spacing (2);
2836 _zoom_box.set_border_width (2);
2840 zoom_in_button.set_name ("zoom button");
2841 // zoom_in_button.add_elements ( ArdourButton::Inset );
2842 zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2843 zoom_in_button.set_image(::get_icon ("zoom_in"));
2844 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2845 zoom_in_button.set_related_action (act);
2847 zoom_out_button.set_name ("zoom button");
2848 // zoom_out_button.add_elements ( ArdourButton::Inset );
2849 zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2850 zoom_out_button.set_image(::get_icon ("zoom_out"));
2851 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2852 zoom_out_button.set_related_action (act);
2854 zoom_out_full_button.set_name ("zoom button");
2855 // zoom_out_full_button.add_elements ( ArdourButton::Inset );
2856 zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2857 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2858 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2859 zoom_out_full_button.set_related_action (act);
2861 zoom_focus_selector.set_name ("zoom button");
2862 zoom_focus_selector.set_size_request (80, -1);
2863 // zoom_focus_selector.add_elements (ArdourButton::Inset);
2865 if (!ARDOUR::Profile->get_trx()) {
2866 _zoom_box.pack_start (zoom_out_button, false, false);
2867 _zoom_box.pack_start (zoom_in_button, false, false);
2868 _zoom_box.pack_start (zoom_out_full_button, false, false);
2869 _zoom_box.pack_start (zoom_focus_selector, false, false);
2871 mode_box->pack_start (zoom_out_button, false, false);
2872 mode_box->pack_start (zoom_in_button, false, false);
2875 /* Track zoom buttons */
2876 visible_tracks_selector.set_name ("zoom button");
2877 // visible_tracks_selector.add_elements ( ArdourButton::Inset );
2878 set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
2880 tav_expand_button.set_name ("zoom button");
2881 // tav_expand_button.add_elements ( ArdourButton::FlatFace );
2882 tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2883 tav_expand_button.set_size_request (-1, 20);
2884 tav_expand_button.set_image(::get_icon ("tav_exp"));
2885 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2886 tav_expand_button.set_related_action (act);
2888 tav_shrink_button.set_name ("zoom button");
2889 // tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2890 tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2891 tav_shrink_button.set_size_request (-1, 20);
2892 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2893 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2894 tav_shrink_button.set_related_action (act);
2896 if (!ARDOUR::Profile->get_trx()) {
2897 _zoom_box.pack_start (visible_tracks_selector);
2899 _zoom_box.pack_start (tav_shrink_button);
2900 _zoom_box.pack_start (tav_expand_button);
2902 if (!ARDOUR::Profile->get_trx()) {
2903 _zoom_tearoff = manage (new TearOff (_zoom_box));
2905 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2906 &_zoom_tearoff->tearoff_window()));
2907 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2908 &_zoom_tearoff->tearoff_window(), 0));
2909 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2910 &_zoom_tearoff->tearoff_window()));
2911 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2912 &_zoom_tearoff->tearoff_window(), 0));
2915 snap_box.set_spacing (2);
2916 snap_box.set_border_width (2);
2918 snap_type_selector.set_name ("mouse mode button");
2919 snap_type_selector.set_size_request (140, -1);
2920 snap_type_selector.add_elements (ArdourButton::Inset);
2922 snap_mode_selector.set_name ("mouse mode button");
2923 snap_mode_selector.set_size_request (85, -1);
2924 snap_mode_selector.add_elements (ArdourButton::Inset);
2926 edit_point_selector.set_name ("mouse mode button");
2927 edit_point_selector.set_size_request (85, -1);
2928 edit_point_selector.add_elements (ArdourButton::Inset);
2930 snap_box.pack_start (snap_mode_selector, false, false);
2931 snap_box.pack_start (snap_type_selector, false, false);
2932 snap_box.pack_start (edit_point_selector, false, false);
2936 HBox *nudge_box = manage (new HBox);
2937 nudge_box->set_spacing (2);
2938 nudge_box->set_border_width (2);
2940 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
2941 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
2943 nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2944 nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2946 nudge_box->pack_start (nudge_backward_button, false, false);
2947 nudge_box->pack_start (nudge_forward_button, false, false);
2948 nudge_box->pack_start (*nudge_clock, false, false);
2951 /* Pack everything in... */
2953 HBox* hbox = manage (new HBox);
2954 hbox->set_spacing(10);
2956 _tools_tearoff = manage (new TearOff (*hbox));
2957 _tools_tearoff->set_name ("MouseModeBase");
2958 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
2960 if (Profile->get_sae()) {
2961 _tools_tearoff->set_can_be_torn_off (false);
2964 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2965 &_tools_tearoff->tearoff_window()));
2966 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2967 &_tools_tearoff->tearoff_window(), 0));
2968 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2969 &_tools_tearoff->tearoff_window()));
2970 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2971 &_tools_tearoff->tearoff_window(), 0));
2973 toolbar_hbox.set_spacing (10);
2974 toolbar_hbox.set_border_width (1);
2976 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
2977 if (!ARDOUR::Profile->get_trx()) {
2978 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
2979 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
2982 if (!ARDOUR::Profile->get_trx()) {
2983 hbox->pack_start (snap_box, false, false);
2984 if (!Profile->get_small_screen()) {
2985 hbox->pack_start (*nudge_box, false, false);
2987 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
2990 hbox->pack_start (panic_box, false, false);
2994 toolbar_base.set_name ("ToolBarBase");
2995 toolbar_base.add (toolbar_hbox);
2997 _toolbar_viewport.add (toolbar_base);
2998 /* stick to the required height but allow width to vary if there's not enough room */
2999 _toolbar_viewport.set_size_request (1, -1);
3001 toolbar_frame.set_shadow_type (SHADOW_OUT);
3002 toolbar_frame.set_name ("BaseFrame");
3003 toolbar_frame.add (_toolbar_viewport);
3007 Editor::build_edit_point_menu ()
3009 using namespace Menu_Helpers;
3011 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3012 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3013 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3017 Editor::build_edit_mode_menu ()
3019 using namespace Menu_Helpers;
3021 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3022 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3023 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Ripple), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3024 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3028 Editor::build_snap_mode_menu ()
3030 using namespace Menu_Helpers;
3032 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
3033 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
3034 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3038 Editor::build_snap_type_menu ()
3040 using namespace Menu_Helpers;
3042 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3043 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3044 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3045 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3046 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3047 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3048 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3049 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3050 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3051 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3052 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3053 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3054 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3055 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3056 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3057 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3058 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3059 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3060 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3061 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3062 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3063 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3064 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3065 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3066 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3067 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3068 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3069 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3070 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3071 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3075 Editor::setup_tooltips ()
3077 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3078 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3079 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3080 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3081 ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3082 ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3083 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3084 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3085 ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3086 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3087 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3088 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3089 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3090 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3091 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3092 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3093 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3094 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3095 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3096 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3097 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3098 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3099 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3100 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3104 Editor::convert_drop_to_paths (
3105 vector<string>& paths,
3106 const RefPtr<Gdk::DragContext>& /*context*/,
3109 const SelectionData& data,
3113 if (_session == 0) {
3117 vector<string> uris = data.get_uris();
3121 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3122 are actually URI lists. So do it by hand.
3125 if (data.get_target() != "text/plain") {
3129 /* Parse the "uri-list" format that Nautilus provides,
3130 where each pathname is delimited by \r\n.
3132 THERE MAY BE NO NULL TERMINATING CHAR!!!
3135 string txt = data.get_text();
3139 p = (char *) malloc (txt.length() + 1);
3140 txt.copy (p, txt.length(), 0);
3141 p[txt.length()] = '\0';
3147 while (g_ascii_isspace (*p))
3151 while (*q && (*q != '\n') && (*q != '\r')) {
3158 while (q > p && g_ascii_isspace (*q))
3163 uris.push_back (string (p, q - p + 1));
3167 p = strchr (p, '\n');
3179 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3180 if ((*i).substr (0,7) == "file://") {
3181 paths.push_back (Glib::filename_from_uri (*i));
3189 Editor::new_tempo_section ()
3194 Editor::map_transport_state ()
3196 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3198 if (_session && _session->transport_stopped()) {
3199 have_pending_keyboard_selection = false;
3202 update_loop_range_view ();
3208 Editor::begin_reversible_command (string name)
3211 _session->begin_reversible_command (name);
3216 Editor::begin_reversible_command (GQuark q)
3219 _session->begin_reversible_command (q);
3224 Editor::commit_reversible_command ()
3227 _session->commit_reversible_command ();
3232 Editor::history_changed ()
3236 if (undo_action && _session) {
3237 if (_session->undo_depth() == 0) {
3238 label = S_("Command|Undo");
3240 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3242 undo_action->property_label() = label;
3245 if (redo_action && _session) {
3246 if (_session->redo_depth() == 0) {
3249 label = string_compose(_("Redo (%1)"), _session->next_redo());
3251 redo_action->property_label() = label;
3256 Editor::duplicate_range (bool with_dialog)
3260 RegionSelection rs = get_regions_from_selection_and_entered ();
3262 if ( selection->time.length() == 0 && rs.empty()) {
3268 ArdourDialog win (_("Duplicate"));
3269 Label label (_("Number of duplications:"));
3270 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3271 SpinButton spinner (adjustment, 0.0, 1);
3274 win.get_vbox()->set_spacing (12);
3275 win.get_vbox()->pack_start (hbox);
3276 hbox.set_border_width (6);
3277 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3279 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3280 place, visually. so do this by hand.
3283 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3284 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3285 spinner.grab_focus();
3291 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3292 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3293 win.set_default_response (RESPONSE_ACCEPT);
3295 spinner.grab_focus ();
3297 switch (win.run ()) {
3298 case RESPONSE_ACCEPT:
3304 times = adjustment.get_value();
3307 if ((current_mouse_mode() == Editing::MouseRange)) {
3308 if (selection->time.length()) {
3309 duplicate_selection (times);
3311 } else if (get_smart_mode()) {
3312 if (selection->time.length()) {
3313 duplicate_selection (times);
3315 duplicate_some_regions (rs, times);
3317 duplicate_some_regions (rs, times);
3322 Editor::set_edit_mode (EditMode m)
3324 Config->set_edit_mode (m);
3328 Editor::cycle_edit_mode ()
3330 switch (Config->get_edit_mode()) {
3332 if (Profile->get_sae()) {
3333 Config->set_edit_mode (Lock);
3335 Config->set_edit_mode (Ripple);
3340 Config->set_edit_mode (Lock);
3343 Config->set_edit_mode (Slide);
3349 Editor::edit_mode_selection_done ( EditMode m )
3351 Config->set_edit_mode ( m );
3355 Editor::snap_type_selection_done (SnapType snaptype)
3357 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3359 ract->set_active ();
3364 Editor::snap_mode_selection_done (SnapMode mode)
3366 RefPtr<RadioAction> ract = snap_mode_action (mode);
3369 ract->set_active (true);
3374 Editor::cycle_edit_point (bool with_marker)
3376 switch (_edit_point) {
3378 set_edit_point_preference (EditAtPlayhead);
3380 case EditAtPlayhead:
3382 set_edit_point_preference (EditAtSelectedMarker);
3384 set_edit_point_preference (EditAtMouse);
3387 case EditAtSelectedMarker:
3388 set_edit_point_preference (EditAtMouse);
3394 Editor::edit_point_selection_done (EditPoint ep)
3396 set_edit_point_preference ( ep );
3400 Editor::build_zoom_focus_menu ()
3402 using namespace Menu_Helpers;
3404 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3405 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3406 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3407 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3408 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3409 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3413 Editor::zoom_focus_selection_done ( ZoomFocus f )
3415 RefPtr<RadioAction> ract = zoom_focus_action (f);
3417 ract->set_active ();
3422 Editor::build_track_count_menu ()
3424 using namespace Menu_Helpers;
3426 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3427 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3428 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3429 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3430 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3431 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3432 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3433 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3434 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3435 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3436 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3437 visible_tracks_selector.AddMenuElem (MenuElem (_("all"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3441 Editor::set_visible_track_count (int32_t n)
3443 _visible_track_count = n;
3445 /* if the canvas hasn't really been allocated any size yet, just
3446 record the desired number of visible tracks and return. when canvas
3447 allocation happens, we will get called again and then we can do the
3451 if (_visible_canvas_height <= 1) {
3458 if (_visible_track_count > 0) {
3459 h = _visible_canvas_height / _visible_track_count;
3460 std::ostringstream s;
3461 s << _visible_track_count;
3463 } else if (_visible_track_count == 0) {
3464 h = _visible_canvas_height / track_views.size();
3467 /* negative value means that the visible track count has
3468 been overridden by explicit track height changes.
3470 visible_tracks_selector.set_text (X_("*"));
3474 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3475 (*i)->set_height (h);
3478 if (str != visible_tracks_selector.get_text()) {
3479 visible_tracks_selector.set_text (str);
3484 Editor::override_visible_track_count ()
3486 _visible_track_count = -_visible_track_count;
3490 Editor::edit_controls_button_release (GdkEventButton* ev)
3492 if (Keyboard::is_context_menu_event (ev)) {
3493 ARDOUR_UI::instance()->add_route (this);
3494 } else if (ev->button == 1) {
3495 selection->clear_tracks ();
3502 Editor::mouse_select_button_release (GdkEventButton* ev)
3504 /* this handles just right-clicks */
3506 if (ev->button != 3) {
3514 Editor::set_zoom_focus (ZoomFocus f)
3516 string str = zoom_focus_strings[(int)f];
3518 if (str != zoom_focus_selector.get_text()) {
3519 zoom_focus_selector.set_text (str);
3522 if (zoom_focus != f) {
3529 Editor::cycle_zoom_focus ()
3531 switch (zoom_focus) {
3533 set_zoom_focus (ZoomFocusRight);
3535 case ZoomFocusRight:
3536 set_zoom_focus (ZoomFocusCenter);
3538 case ZoomFocusCenter:
3539 set_zoom_focus (ZoomFocusPlayhead);
3541 case ZoomFocusPlayhead:
3542 set_zoom_focus (ZoomFocusMouse);
3544 case ZoomFocusMouse:
3545 set_zoom_focus (ZoomFocusEdit);
3548 set_zoom_focus (ZoomFocusLeft);
3554 Editor::ensure_float (Window& win)
3556 win.set_transient_for (*this);
3560 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3562 /* recover or initialize pane positions. do this here rather than earlier because
3563 we don't want the positions to change the child allocations, which they seem to do.
3569 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3578 XMLNode* geometry = find_named_node (*node, "geometry");
3580 if (which == static_cast<Paned*> (&edit_pane)) {
3582 if (done & Horizontal) {
3586 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3587 _notebook_shrunk = string_is_affirmative (prop->value ());
3590 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3591 /* initial allocation is 90% to canvas, 10% to notebook */
3592 pos = (int) floor (alloc.get_width() * 0.90f);
3593 snprintf (buf, sizeof(buf), "%d", pos);
3595 pos = atoi (prop->value());
3598 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3599 edit_pane.set_position (pos);
3602 done = (Pane) (done | Horizontal);
3604 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3606 if (done & Vertical) {
3610 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3611 /* initial allocation is 90% to canvas, 10% to summary */
3612 pos = (int) floor (alloc.get_height() * 0.90f);
3613 snprintf (buf, sizeof(buf), "%d", pos);
3616 pos = atoi (prop->value());
3619 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3620 editor_summary_pane.set_position (pos);
3623 done = (Pane) (done | Vertical);
3628 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3630 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3631 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3632 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3633 top_hbox.remove (toolbar_frame);
3638 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3640 if (toolbar_frame.get_parent() == 0) {
3641 top_hbox.pack_end (toolbar_frame);
3646 Editor::set_show_measures (bool yn)
3648 if (_show_measures != yn) {
3651 if ((_show_measures = yn) == true) {
3653 tempo_lines->show();
3656 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3657 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3659 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3660 draw_measures (begin, end);
3668 Editor::toggle_follow_playhead ()
3670 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3672 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3673 set_follow_playhead (tact->get_active());
3677 /** @param yn true to follow playhead, otherwise false.
3678 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3681 Editor::set_follow_playhead (bool yn, bool catch_up)
3683 if (_follow_playhead != yn) {
3684 if ((_follow_playhead = yn) == true && catch_up) {
3686 reset_x_origin_to_follow_playhead ();
3693 Editor::toggle_stationary_playhead ()
3695 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3697 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3698 set_stationary_playhead (tact->get_active());
3703 Editor::set_stationary_playhead (bool yn)
3705 if (_stationary_playhead != yn) {
3706 if ((_stationary_playhead = yn) == true) {
3708 // FIXME need a 3.0 equivalent of this 2.X call
3709 // update_current_screen ();
3716 Editor::playlist_selector () const
3718 return *_playlist_selector;
3722 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3726 switch (_snap_type) {
3731 case SnapToBeatDiv128:
3734 case SnapToBeatDiv64:
3737 case SnapToBeatDiv32:
3740 case SnapToBeatDiv28:
3743 case SnapToBeatDiv24:
3746 case SnapToBeatDiv20:
3749 case SnapToBeatDiv16:
3752 case SnapToBeatDiv14:
3755 case SnapToBeatDiv12:
3758 case SnapToBeatDiv10:
3761 case SnapToBeatDiv8:
3764 case SnapToBeatDiv7:
3767 case SnapToBeatDiv6:
3770 case SnapToBeatDiv5:
3773 case SnapToBeatDiv4:
3776 case SnapToBeatDiv3:
3779 case SnapToBeatDiv2:
3785 return _session->tempo_map().meter_at (position).divisions_per_bar();
3790 case SnapToTimecodeFrame:
3791 case SnapToTimecodeSeconds:
3792 case SnapToTimecodeMinutes:
3795 case SnapToRegionStart:
3796 case SnapToRegionEnd:
3797 case SnapToRegionSync:
3798 case SnapToRegionBoundary:
3808 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3812 ret = nudge_clock->current_duration (pos);
3813 next = ret + 1; /* XXXX fix me */
3819 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3821 ArdourDialog dialog (_("Playlist Deletion"));
3822 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3823 "If it is kept, its audio files will not be cleaned.\n"
3824 "If it is deleted, audio files used by it alone will be cleaned."),
3827 dialog.set_position (WIN_POS_CENTER);
3828 dialog.get_vbox()->pack_start (label);
3832 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3833 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3834 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3836 switch (dialog.run ()) {
3837 case RESPONSE_ACCEPT:
3838 /* delete the playlist */
3842 case RESPONSE_REJECT:
3843 /* keep the playlist */
3855 Editor::audio_region_selection_covers (framepos_t where)
3857 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3858 if ((*a)->region()->covers (where)) {
3867 Editor::prepare_for_cleanup ()
3869 cut_buffer->clear_regions ();
3870 cut_buffer->clear_playlists ();
3872 selection->clear_regions ();
3873 selection->clear_playlists ();
3875 _regions->suspend_redisplay ();
3879 Editor::finish_cleanup ()
3881 _regions->resume_redisplay ();
3885 Editor::transport_loop_location()
3888 return _session->locations()->auto_loop_location();
3895 Editor::transport_punch_location()
3898 return _session->locations()->auto_punch_location();
3905 Editor::control_layout_scroll (GdkEventScroll* ev)
3907 /* Just forward to the normal canvas scroll method. The coordinate
3908 systems are different but since the canvas is always larger than the
3909 track headers, and aligned with the trackview area, this will work.
3911 In the not too distant future this layout is going away anyway and
3912 headers will be on the canvas.
3914 return canvas_scroll_event (ev, false);
3918 Editor::session_state_saved (string)
3921 _snapshots->redisplay ();
3925 Editor::update_tearoff_visibility()
3927 bool visible = Config->get_keep_tearoffs();
3928 _mouse_mode_tearoff->set_visible (visible);
3929 _tools_tearoff->set_visible (visible);
3930 if (_zoom_tearoff) {
3931 _zoom_tearoff->set_visible (visible);
3936 Editor::maximise_editing_space ()
3948 Editor::restore_editing_space ()
3960 * Make new playlists for a given track and also any others that belong
3961 * to the same active route group with the `select' property.
3966 Editor::new_playlists (TimeAxisView* v)
3968 begin_reversible_command (_("new playlists"));
3969 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3970 _session->playlists->get (playlists);
3971 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
3972 commit_reversible_command ();
3976 * Use a copy of the current playlist for a given track and also any others that belong
3977 * to the same active route group with the `select' property.
3982 Editor::copy_playlists (TimeAxisView* v)
3984 begin_reversible_command (_("copy playlists"));
3985 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3986 _session->playlists->get (playlists);
3987 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
3988 commit_reversible_command ();
3991 /** Clear the current playlist for a given track and also any others that belong
3992 * to the same active route group with the `select' property.
3997 Editor::clear_playlists (TimeAxisView* v)
3999 begin_reversible_command (_("clear playlists"));
4000 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4001 _session->playlists->get (playlists);
4002 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4003 commit_reversible_command ();
4007 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4009 atv.use_new_playlist (sz > 1 ? false : true, playlists);
4013 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4015 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4019 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4021 atv.clear_playlist ();
4025 Editor::on_key_press_event (GdkEventKey* ev)
4027 return key_press_focus_accelerator_handler (*this, ev);
4031 Editor::on_key_release_event (GdkEventKey* ev)
4033 return Gtk::Window::on_key_release_event (ev);
4034 // return key_press_focus_accelerator_handler (*this, ev);
4037 /** Queue up a change to the viewport x origin.
4038 * @param frame New x origin.
4041 Editor::reset_x_origin (framepos_t frame)
4043 pending_visual_change.add (VisualChange::TimeOrigin);
4044 pending_visual_change.time_origin = frame;
4045 ensure_visual_change_idle_handler ();
4049 Editor::reset_y_origin (double y)
4051 pending_visual_change.add (VisualChange::YOrigin);
4052 pending_visual_change.y_origin = y;
4053 ensure_visual_change_idle_handler ();
4057 Editor::reset_zoom (framecnt_t spp)
4059 if (spp == samples_per_pixel) {
4063 pending_visual_change.add (VisualChange::ZoomLevel);
4064 pending_visual_change.samples_per_pixel = spp;
4065 ensure_visual_change_idle_handler ();
4069 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4071 reset_x_origin (frame);
4074 if (!no_save_visual) {
4075 undo_visual_stack.push_back (current_visual_state(false));
4079 Editor::VisualState::VisualState (bool with_tracks)
4080 : gui_state (with_tracks ? new GUIObjectState : 0)
4084 Editor::VisualState::~VisualState ()
4089 Editor::VisualState*
4090 Editor::current_visual_state (bool with_tracks)
4092 VisualState* vs = new VisualState (with_tracks);
4093 vs->y_position = vertical_adjustment.get_value();
4094 vs->samples_per_pixel = samples_per_pixel;
4095 vs->leftmost_frame = leftmost_frame;
4096 vs->zoom_focus = zoom_focus;
4099 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4106 Editor::undo_visual_state ()
4108 if (undo_visual_stack.empty()) {
4112 VisualState* vs = undo_visual_stack.back();
4113 undo_visual_stack.pop_back();
4116 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4118 use_visual_state (*vs);
4122 Editor::redo_visual_state ()
4124 if (redo_visual_stack.empty()) {
4128 VisualState* vs = redo_visual_stack.back();
4129 redo_visual_stack.pop_back();
4131 undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4133 use_visual_state (*vs);
4137 Editor::swap_visual_state ()
4139 if (undo_visual_stack.empty()) {
4140 redo_visual_state ();
4142 undo_visual_state ();
4147 Editor::use_visual_state (VisualState& vs)
4149 PBD::Unwinder<bool> nsv (no_save_visual, true);
4150 DisplaySuspender ds;
4152 vertical_adjustment.set_value (vs.y_position);
4154 set_zoom_focus (vs.zoom_focus);
4155 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4158 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4160 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4161 (*i)->reset_visual_state ();
4165 _routes->update_visibility ();
4168 /** This is the core function that controls the zoom level of the canvas. It is called
4169 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4170 * @param spp new number of samples per pixel
4173 Editor::set_samples_per_pixel (framecnt_t spp)
4179 const framecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->frame_rate() : 48000);
4180 const framecnt_t lots_of_pixels = 4000;
4182 /* if the zoom level is greater than what you'd get trying to display 3
4183 * days of audio on a really big screen, then it's too big.
4186 if (spp * lots_of_pixels > three_days) {
4190 samples_per_pixel = spp;
4193 tempo_lines->tempo_map_changed();
4196 bool const showing_time_selection = selection->time.length() > 0;
4198 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4199 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4200 (*i)->reshow_selection (selection->time);
4204 ZoomChanged (); /* EMIT_SIGNAL */
4206 ArdourCanvas::GtkCanvasViewport* c;
4208 c = get_track_canvas();
4210 c->canvas()->zoomed ();
4213 if (playhead_cursor) {
4214 playhead_cursor->set_position (playhead_cursor->current_frame ());
4217 refresh_location_display();
4218 _summary->set_overlays_dirty ();
4220 update_marker_labels ();
4226 Editor::queue_visual_videotimeline_update ()
4229 * pending_visual_change.add (VisualChange::VideoTimeline);
4230 * or maybe even more specific: which videotimeline-image
4231 * currently it calls update_video_timeline() to update
4232 * _all outdated_ images on the video-timeline.
4233 * see 'exposeimg()' in video_image_frame.cc
4235 ensure_visual_change_idle_handler ();
4239 Editor::ensure_visual_change_idle_handler ()
4241 if (pending_visual_change.idle_handler_id < 0) {
4242 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4243 pending_visual_change.being_handled = false;
4248 Editor::_idle_visual_changer (void* arg)
4250 return static_cast<Editor*>(arg)->idle_visual_changer ();
4254 Editor::idle_visual_changer ()
4256 /* set_horizontal_position() below (and maybe other calls) call
4257 gtk_main_iteration(), so it's possible that a signal will be handled
4258 half-way through this method. If this signal wants an
4259 idle_visual_changer we must schedule another one after this one, so
4260 mark the idle_handler_id as -1 here to allow that. Also make a note
4261 that we are doing the visual change, so that changes in response to
4262 super-rapid-screen-update can be dropped if we are still processing
4266 pending_visual_change.idle_handler_id = -1;
4267 pending_visual_change.being_handled = true;
4269 VisualChange vc = pending_visual_change;
4271 pending_visual_change.pending = (VisualChange::Type) 0;
4273 visual_changer (vc);
4275 pending_visual_change.being_handled = false;
4277 return 0; /* this is always a one-shot call */
4281 Editor::visual_changer (const VisualChange& vc)
4283 double const last_time_origin = horizontal_position ();
4285 if (vc.pending & VisualChange::ZoomLevel) {
4286 set_samples_per_pixel (vc.samples_per_pixel);
4288 compute_fixed_ruler_scale ();
4290 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4291 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4293 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4294 current_bbt_points_begin, current_bbt_points_end);
4295 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4296 current_bbt_points_begin, current_bbt_points_end);
4297 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4299 update_video_timeline();
4302 if (vc.pending & VisualChange::TimeOrigin) {
4303 set_horizontal_position (vc.time_origin / samples_per_pixel);
4306 if (vc.pending & VisualChange::YOrigin) {
4307 vertical_adjustment.set_value (vc.y_origin);
4310 if (last_time_origin == horizontal_position ()) {
4311 /* changed signal not emitted */
4312 update_fixed_rulers ();
4313 redisplay_tempo (true);
4316 if (!(vc.pending & VisualChange::ZoomLevel)) {
4317 update_video_timeline();
4320 _summary->set_overlays_dirty ();
4323 struct EditorOrderTimeAxisSorter {
4324 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4325 return a->order () < b->order ();
4330 Editor::sort_track_selection (TrackViewList& sel)
4332 EditorOrderTimeAxisSorter cmp;
4337 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4340 framepos_t where = 0;
4341 EditPoint ep = _edit_point;
4343 if (from_context_menu && (ep == EditAtMouse)) {
4344 return canvas_event_sample (&context_click_event, 0, 0);
4347 if (entered_marker) {
4348 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4349 return entered_marker->position();
4352 if (ignore_playhead && ep == EditAtPlayhead) {
4353 ep = EditAtSelectedMarker;
4357 case EditAtPlayhead:
4358 where = _session->audible_frame();
4359 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4362 case EditAtSelectedMarker:
4363 if (!selection->markers.empty()) {
4365 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4368 where = loc->start();
4372 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4380 if (!mouse_frame (where, ignored)) {
4381 /* XXX not right but what can we do ? */
4385 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4393 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4395 if (!_session) return;
4397 begin_reversible_command (cmd);
4401 if ((tll = transport_loop_location()) == 0) {
4402 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4403 XMLNode &before = _session->locations()->get_state();
4404 _session->locations()->add (loc, true);
4405 _session->set_auto_loop_location (loc);
4406 XMLNode &after = _session->locations()->get_state();
4407 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4409 XMLNode &before = tll->get_state();
4410 tll->set_hidden (false, this);
4411 tll->set (start, end);
4412 XMLNode &after = tll->get_state();
4413 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4416 commit_reversible_command ();
4420 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4422 if (!_session) return;
4424 begin_reversible_command (cmd);
4428 if ((tpl = transport_punch_location()) == 0) {
4429 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4430 XMLNode &before = _session->locations()->get_state();
4431 _session->locations()->add (loc, true);
4432 _session->set_auto_punch_location (loc);
4433 XMLNode &after = _session->locations()->get_state();
4434 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4437 XMLNode &before = tpl->get_state();
4438 tpl->set_hidden (false, this);
4439 tpl->set (start, end);
4440 XMLNode &after = tpl->get_state();
4441 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4444 commit_reversible_command ();
4447 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4448 * @param rs List to which found regions are added.
4449 * @param where Time to look at.
4450 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4453 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4455 const TrackViewList* tracks;
4458 tracks = &track_views;
4463 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4465 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4468 boost::shared_ptr<Track> tr;
4469 boost::shared_ptr<Playlist> pl;
4471 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4473 boost::shared_ptr<RegionList> regions = pl->regions_at (
4474 (framepos_t) floor ( (double) where * tr->speed()));
4476 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4477 RegionView* rv = rtv->view()->find_view (*i);
4488 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4490 const TrackViewList* tracks;
4493 tracks = &track_views;
4498 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4499 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4501 boost::shared_ptr<Track> tr;
4502 boost::shared_ptr<Playlist> pl;
4504 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4506 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4507 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4509 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4511 RegionView* rv = rtv->view()->find_view (*i);
4522 /** Get regions using the following method:
4524 * Make a region list using:
4525 * (a) any selected regions
4526 * (b) the intersection of any selected tracks and the edit point(*)
4527 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4529 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4531 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4535 Editor::get_regions_from_selection_and_edit_point ()
4537 RegionSelection regions;
4539 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4540 regions.add (entered_regionview);
4542 regions = selection->regions;
4545 if ( regions.empty() ) {
4546 TrackViewList tracks = selection->tracks;
4548 if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
4549 /* tracks is empty (no track selected), and 'No Selection = All Tracks'
4550 * is enabled, so consider all tracks
4552 tracks = track_views;
4555 if (!tracks.empty()) {
4556 /* no region selected or entered, but some selected tracks:
4557 * act on all regions on the selected tracks at the edit point
4559 framepos_t const where = get_preferred_edit_position ();
4560 get_regions_at(regions, where, tracks);
4567 /** Start with regions that are selected, or the entered regionview if none are selected.
4568 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4569 * of the regions that we started with.
4573 Editor::get_regions_from_selection_and_entered ()
4575 RegionSelection regions = selection->regions;
4577 if (regions.empty() && entered_regionview) {
4578 regions.add (entered_regionview);
4585 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4587 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4589 RouteTimeAxisView* tatv;
4591 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4593 boost::shared_ptr<Playlist> pl;
4594 vector<boost::shared_ptr<Region> > results;
4596 boost::shared_ptr<Track> tr;
4598 if ((tr = tatv->track()) == 0) {
4603 if ((pl = (tr->playlist())) != 0) {
4604 if (src_comparison) {
4605 pl->get_source_equivalent_regions (region, results);
4607 pl->get_region_list_equivalent_regions (region, results);
4611 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4612 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4613 regions.push_back (marv);
4622 Editor::show_rhythm_ferret ()
4624 if (rhythm_ferret == 0) {
4625 rhythm_ferret = new RhythmFerret(*this);
4628 rhythm_ferret->set_session (_session);
4629 rhythm_ferret->show ();
4630 rhythm_ferret->present ();
4634 Editor::first_idle ()
4636 MessageDialog* dialog = 0;
4638 if (track_views.size() > 1) {
4639 dialog = new MessageDialog (
4641 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4645 ARDOUR_UI::instance()->flush_pending ();
4648 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4652 // first idle adds route children (automation tracks), so we need to redisplay here
4653 _routes->redisplay ();
4660 Editor::_idle_resize (gpointer arg)
4662 return ((Editor*)arg)->idle_resize ();
4666 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4668 if (resize_idle_id < 0) {
4669 resize_idle_id = g_idle_add (_idle_resize, this);
4670 _pending_resize_amount = 0;
4673 /* make a note of the smallest resulting height, so that we can clamp the
4674 lower limit at TimeAxisView::hSmall */
4676 int32_t min_resulting = INT32_MAX;
4678 _pending_resize_amount += h;
4679 _pending_resize_view = view;
4681 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4683 if (selection->tracks.contains (_pending_resize_view)) {
4684 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4685 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4689 if (min_resulting < 0) {
4694 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4695 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4699 /** Handle pending resizing of tracks */
4701 Editor::idle_resize ()
4703 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4705 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4706 selection->tracks.contains (_pending_resize_view)) {
4708 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4709 if (*i != _pending_resize_view) {
4710 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4715 _pending_resize_amount = 0;
4716 _group_tabs->set_dirty ();
4717 resize_idle_id = -1;
4725 ENSURE_GUI_THREAD (*this, &Editor::located);
4728 playhead_cursor->set_position (_session->audible_frame ());
4729 if (_follow_playhead && !_pending_initial_locate) {
4730 reset_x_origin_to_follow_playhead ();
4734 _pending_locate_request = false;
4735 _pending_initial_locate = false;
4739 Editor::region_view_added (RegionView *)
4741 _summary->set_background_dirty ();
4745 Editor::region_view_removed ()
4747 _summary->set_background_dirty ();
4751 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4753 TrackViewList::const_iterator j = track_views.begin ();
4754 while (j != track_views.end()) {
4755 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4756 if (rtv && rtv->route() == r) {
4767 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4771 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4772 TimeAxisView* tv = axis_view_from_route (*i);
4782 Editor::suspend_route_redisplay ()
4785 _routes->suspend_redisplay();
4790 Editor::resume_route_redisplay ()
4793 _routes->resume_redisplay();
4798 Editor::add_routes (RouteList& routes)
4800 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4802 RouteTimeAxisView *rtv;
4803 list<RouteTimeAxisView*> new_views;
4805 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4806 boost::shared_ptr<Route> route = (*x);
4808 if (route->is_auditioner() || route->is_monitor()) {
4812 DataType dt = route->input()->default_type();
4814 if (dt == ARDOUR::DataType::AUDIO) {
4815 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4816 rtv->set_route (route);
4817 } else if (dt == ARDOUR::DataType::MIDI) {
4818 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
4819 rtv->set_route (route);
4821 throw unknown_type();
4824 new_views.push_back (rtv);
4825 track_views.push_back (rtv);
4827 rtv->effective_gain_display ();
4829 if (internal_editing()) {
4830 rtv->enter_internal_edit_mode ();
4832 rtv->leave_internal_edit_mode ();
4835 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4836 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4839 if (new_views.size() > 0) {
4840 _routes->routes_added (new_views);
4841 _summary->routes_added (new_views);
4844 if (show_editor_mixer_when_tracks_arrive) {
4845 show_editor_mixer (true);
4848 editor_list_button.set_sensitive (true);
4852 Editor::timeaxisview_deleted (TimeAxisView *tv)
4854 if (tv == entered_track) {
4858 if (_session && _session->deletion_in_progress()) {
4859 /* the situation is under control */
4863 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
4865 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
4867 _routes->route_removed (tv);
4869 TimeAxisView::Children c = tv->get_child_list ();
4870 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
4871 if (entered_track == i->get()) {
4876 /* remove it from the list of track views */
4878 TrackViewList::iterator i;
4880 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
4881 i = track_views.erase (i);
4884 /* update whatever the current mixer strip is displaying, if revelant */
4886 boost::shared_ptr<Route> route;
4889 route = rtav->route ();
4892 if (current_mixer_strip && current_mixer_strip->route() == route) {
4894 TimeAxisView* next_tv;
4896 if (track_views.empty()) {
4898 } else if (i == track_views.end()) {
4899 next_tv = track_views.front();
4906 set_selected_mixer_strip (*next_tv);
4908 /* make the editor mixer strip go away setting the
4909 * button to inactive (which also unticks the menu option)
4912 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
4918 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
4920 if (apply_to_selection) {
4921 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
4923 TrackSelection::iterator j = i;
4926 hide_track_in_display (*i, false);
4931 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
4933 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
4934 // this will hide the mixer strip
4935 set_selected_mixer_strip (*tv);
4938 _routes->hide_track_in_display (*tv);
4943 Editor::sync_track_view_list_and_routes ()
4945 track_views = TrackViewList (_routes->views ());
4947 _summary->set_dirty ();
4948 _group_tabs->set_dirty ();
4950 return false; // do not call again (until needed)
4954 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
4956 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4961 /** Find a RouteTimeAxisView by the ID of its route */
4963 Editor::get_route_view_by_route_id (const PBD::ID& id) const
4965 RouteTimeAxisView* v;
4967 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4968 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
4969 if(v->route()->id() == id) {
4979 Editor::fit_route_group (RouteGroup *g)
4981 TrackViewList ts = axis_views_from_routes (g->route_list ());
4986 Editor::consider_auditioning (boost::shared_ptr<Region> region)
4988 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
4991 _session->cancel_audition ();
4995 if (_session->is_auditioning()) {
4996 _session->cancel_audition ();
4997 if (r == last_audition_region) {
5002 _session->audition_region (r);
5003 last_audition_region = r;
5008 Editor::hide_a_region (boost::shared_ptr<Region> r)
5010 r->set_hidden (true);
5014 Editor::show_a_region (boost::shared_ptr<Region> r)
5016 r->set_hidden (false);
5020 Editor::audition_region_from_region_list ()
5022 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5026 Editor::hide_region_from_region_list ()
5028 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5032 Editor::show_region_in_region_list ()
5034 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5038 Editor::step_edit_status_change (bool yn)
5041 start_step_editing ();
5043 stop_step_editing ();
5048 Editor::start_step_editing ()
5050 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5054 Editor::stop_step_editing ()
5056 step_edit_connection.disconnect ();
5060 Editor::check_step_edit ()
5062 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5063 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5065 mtv->check_step_edit ();
5069 return true; // do it again, till we stop
5073 Editor::scroll_press (Direction dir)
5075 ++_scroll_callbacks;
5077 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5078 /* delay the first auto-repeat */
5084 scroll_backward (1);
5092 scroll_tracks_up_line ();
5096 scroll_tracks_down_line ();
5100 /* do hacky auto-repeat */
5101 if (!_scroll_connection.connected ()) {
5103 _scroll_connection = Glib::signal_timeout().connect (
5104 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5107 _scroll_callbacks = 0;
5114 Editor::scroll_release ()
5116 _scroll_connection.disconnect ();
5119 /** Queue a change for the Editor viewport x origin to follow the playhead */
5121 Editor::reset_x_origin_to_follow_playhead ()
5123 framepos_t const frame = playhead_cursor->current_frame ();
5125 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5127 if (_session->transport_speed() < 0) {
5129 if (frame > (current_page_samples() / 2)) {
5130 center_screen (frame-(current_page_samples()/2));
5132 center_screen (current_page_samples()/2);
5139 if (frame < leftmost_frame) {
5141 if (_session->transport_rolling()) {
5142 /* rolling; end up with the playhead at the right of the page */
5143 l = frame - current_page_samples ();
5145 /* not rolling: end up with the playhead 1/4 of the way along the page */
5146 l = frame - current_page_samples() / 4;
5150 if (_session->transport_rolling()) {
5151 /* rolling: end up with the playhead on the left of the page */
5154 /* not rolling: end up with the playhead 3/4 of the way along the page */
5155 l = frame - 3 * current_page_samples() / 4;
5163 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5169 Editor::super_rapid_screen_update ()
5171 if (!_session || !_session->engine().running()) {
5175 /* METERING / MIXER STRIPS */
5177 /* update track meters, if required */
5178 if (is_mapped() && meters_running) {
5179 RouteTimeAxisView* rtv;
5180 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5181 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5182 rtv->fast_update ();
5187 /* and any current mixer strip */
5188 if (current_mixer_strip) {
5189 current_mixer_strip->fast_update ();
5192 /* PLAYHEAD AND VIEWPORT */
5194 framepos_t const frame = _session->audible_frame();
5196 /* There are a few reasons why we might not update the playhead / viewport stuff:
5198 * 1. we don't update things when there's a pending locate request, otherwise
5199 * when the editor requests a locate there is a chance that this method
5200 * will move the playhead before the locate request is processed, causing
5202 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5203 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5206 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5208 last_update_frame = frame;
5210 if (!_dragging_playhead) {
5211 playhead_cursor->set_position (frame);
5214 if (!_stationary_playhead) {
5216 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5217 /* We only do this if we aren't already
5218 handling a visual change (ie if
5219 pending_visual_change.being_handled is
5220 false) so that these requests don't stack
5221 up there are too many of them to handle in
5224 reset_x_origin_to_follow_playhead ();
5229 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5233 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5234 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5235 if (target <= 0.0) {
5238 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5239 target = (target * 0.15) + (current * 0.85);
5245 set_horizontal_position (current);
5254 Editor::session_going_away ()
5256 _have_idled = false;
5258 _session_connections.drop_connections ();
5260 super_rapid_screen_update_connection.disconnect ();
5262 selection->clear ();
5263 cut_buffer->clear ();
5265 clicked_regionview = 0;
5266 clicked_axisview = 0;
5267 clicked_routeview = 0;
5268 entered_regionview = 0;
5270 last_update_frame = 0;
5273 playhead_cursor->hide ();
5275 /* rip everything out of the list displays */
5279 _route_groups->clear ();
5281 /* do this first so that deleting a track doesn't reset cms to null
5282 and thus cause a leak.
5285 if (current_mixer_strip) {
5286 if (current_mixer_strip->get_parent() != 0) {
5287 global_hpacker.remove (*current_mixer_strip);
5289 delete current_mixer_strip;
5290 current_mixer_strip = 0;
5293 /* delete all trackviews */
5295 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5298 track_views.clear ();
5300 nudge_clock->set_session (0);
5302 editor_list_button.set_active(false);
5303 editor_list_button.set_sensitive(false);
5305 /* clear tempo/meter rulers */
5306 remove_metric_marks ();
5308 clear_marker_display ();
5310 stop_step_editing ();
5312 /* get rid of any existing editor mixer strip */
5314 WindowTitle title(Glib::get_application_name());
5315 title += _("Editor");
5317 set_title (title.get_string());
5319 SessionHandlePtr::session_going_away ();
5324 Editor::show_editor_list (bool yn)
5327 _the_notebook.show ();
5329 _the_notebook.hide ();
5334 Editor::change_region_layering_order (bool from_context_menu)
5336 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5338 if (!clicked_routeview) {
5339 if (layering_order_editor) {
5340 layering_order_editor->hide ();
5345 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5351 boost::shared_ptr<Playlist> pl = track->playlist();
5357 if (layering_order_editor == 0) {
5358 layering_order_editor = new RegionLayeringOrderEditor (*this);
5361 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5362 layering_order_editor->maybe_present ();
5366 Editor::update_region_layering_order_editor ()
5368 if (layering_order_editor && layering_order_editor->is_visible ()) {
5369 change_region_layering_order (true);
5374 Editor::setup_fade_images ()
5376 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5377 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5378 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5379 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5380 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5382 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5383 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5384 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5385 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5386 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5388 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5389 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5390 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5391 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5392 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5394 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5395 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5396 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5397 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5398 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5402 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5404 Editor::action_menu_item (std::string const & name)
5406 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5409 return *manage (a->create_menu_item ());
5413 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5415 EventBox* b = manage (new EventBox);
5416 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5417 Label* l = manage (new Label (name));
5421 _the_notebook.append_page (widget, *b);
5425 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5427 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5428 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5431 if (ev->type == GDK_2BUTTON_PRESS) {
5433 /* double-click on a notebook tab shrinks or expands the notebook */
5435 if (_notebook_shrunk) {
5436 if (pre_notebook_shrink_pane_width) {
5437 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5439 _notebook_shrunk = false;
5441 pre_notebook_shrink_pane_width = edit_pane.get_position();
5443 /* this expands the LHS of the edit pane to cover the notebook
5444 PAGE but leaves the tabs visible.
5446 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5447 _notebook_shrunk = true;
5455 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5457 using namespace Menu_Helpers;
5459 MenuList& items = _control_point_context_menu.items ();
5462 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5463 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5464 if (!can_remove_control_point (item)) {
5465 items.back().set_sensitive (false);
5468 _control_point_context_menu.popup (event->button.button, event->button.time);
5472 Editor::zoom_vertical_modifier_released()
5474 _stepping_axis_view = 0;
5478 Editor::ui_parameter_changed (string parameter)
5480 if (parameter == "icon-set") {
5481 while (!_cursor_stack.empty()) {
5482 _cursor_stack.pop();
5484 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
5485 } else if (parameter == "draggable-playhead") {
5486 if (_verbose_cursor) {
5487 playhead_cursor->set_sensitive (ARDOUR_UI::config()->get_draggable_playhead());