2 Copyright (C) 2000-2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* Note: public Editor methods are documented in public_editor.h */
30 #include "ardour_ui.h"
32 * ardour_ui.h include was moved to the top of the list
33 * due to a conflicting definition of 'Style' between
34 * Apple's MacTypes.h and BarController.
37 #include <boost/none.hpp>
39 #include <sigc++/bind.h>
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
49 #include <glibmm/miscutils.h>
50 #include <glibmm/uriutils.h>
51 #include <gtkmm/image.h>
52 #include <gdkmm/color.h>
53 #include <gdkmm/bitmap.h>
55 #include <gtkmm/menu.h>
56 #include <gtkmm/menuitem.h>
58 #include "gtkmm2ext/bindings.h"
59 #include "gtkmm2ext/grouped_buttons.h"
60 #include "gtkmm2ext/gtk_ui.h"
61 #include "gtkmm2ext/tearoff.h"
62 #include "gtkmm2ext/utils.h"
63 #include "gtkmm2ext/window_title.h"
64 #include "gtkmm2ext/choice.h"
65 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
67 #include "ardour/audio_track.h"
68 #include "ardour/audioengine.h"
69 #include "ardour/audioregion.h"
70 #include "ardour/location.h"
71 #include "ardour/profile.h"
72 #include "ardour/route_group.h"
73 #include "ardour/session_playlists.h"
74 #include "ardour/tempo.h"
75 #include "ardour/utils.h"
77 #include "canvas/debug.h"
78 #include "canvas/text.h"
80 #include "control_protocol/control_protocol.h"
84 #include "analysis_window.h"
85 #include "audio_clock.h"
86 #include "audio_region_view.h"
87 #include "audio_streamview.h"
88 #include "audio_time_axis.h"
89 #include "automation_time_axis.h"
90 #include "bundle_manager.h"
91 #include "crossfade_edit.h"
95 #include "editor_cursors.h"
96 #include "editor_drag.h"
97 #include "editor_group_tabs.h"
98 #include "editor_locations.h"
99 #include "editor_regions.h"
100 #include "editor_route_groups.h"
101 #include "editor_routes.h"
102 #include "editor_snapshots.h"
103 #include "editor_summary.h"
104 #include "global_port_matrix.h"
105 #include "gui_object.h"
106 #include "gui_thread.h"
107 #include "keyboard.h"
109 #include "midi_time_axis.h"
110 #include "mixer_strip.h"
111 #include "mixer_ui.h"
112 #include "mouse_cursors.h"
113 #include "playlist_selector.h"
114 #include "public_editor.h"
115 #include "region_layering_order_editor.h"
116 #include "rgb_macros.h"
117 #include "rhythm_ferret.h"
118 #include "selection.h"
120 #include "tempo_lines.h"
121 #include "time_axis_view.h"
127 using namespace ARDOUR;
130 using namespace Glib;
131 using namespace Gtkmm2ext;
132 using namespace Editing;
134 using PBD::internationalize;
136 using Gtkmm2ext::Keyboard;
138 const double Editor::timebar_height = 15.0;
140 static const gchar *_snap_type_strings[] = {
142 N_("Timecode Frames"),
143 N_("Timecode Seconds"),
144 N_("Timecode Minutes"),
174 static const gchar *_snap_mode_strings[] = {
181 static const gchar *_edit_point_strings[] = {
188 static const gchar *_zoom_focus_strings[] = {
198 #ifdef USE_RUBBERBAND
199 static const gchar *_rb_opt_strings[] = {
202 N_("Balanced multitimbral mixture"),
203 N_("Unpitched percussion with stable notes"),
204 N_("Crisp monophonic instrumental"),
205 N_("Unpitched solo percussion"),
206 N_("Resample without preserving pitch"),
212 pane_size_watcher (Paned* pane)
214 /* if the handle of a pane vanishes into (at least) the tabs of a notebook,
218 Quartz: impossible to access
220 so stop that by preventing it from ever getting too narrow. 35
221 pixels is basically a rough guess at the tab width.
226 int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
228 gint pos = pane->get_position ();
230 if (pos > max_width_of_lhs) {
231 pane->set_position (max_width_of_lhs);
236 : _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
238 /* time display buttons */
239 , minsec_label (_("Mins:Secs"))
240 , bbt_label (_("Bars:Beats"))
241 , timecode_label (_("Timecode"))
242 , samples_label (_("Samples"))
243 , tempo_label (_("Tempo"))
244 , meter_label (_("Meter"))
245 , mark_label (_("Location Markers"))
246 , range_mark_label (_("Range Markers"))
247 , transport_mark_label (_("Loop/Punch Ranges"))
248 , cd_mark_label (_("CD Markers"))
249 , videotl_label (_("Video Timeline"))
250 , edit_packer (4, 4, true)
252 /* the values here don't matter: layout widgets
253 reset them as needed.
256 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
257 , horizontal_adjustment (0.0, 0.0, 1e16)
258 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
260 , controls_layout (unused_adjustment, vertical_adjustment)
262 /* tool bar related */
264 , zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
265 , toolbar_selection_clock_table (2,3)
266 , _mouse_mode_tearoff (0)
267 , automation_mode_button (_("mode"))
271 , _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
275 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
276 , meters_running(false)
277 , _pending_locate_request (false)
278 , _pending_initial_locate (false)
279 , _last_cut_copy_source_track (0)
281 , _region_selection_change_updates_region_list (true)
282 , _following_mixer_selection (false)
283 , _control_point_toggled_on_press (false)
284 , _stepping_axis_view (0)
288 /* we are a singleton */
290 PublicEditor::_instance = this;
294 selection = new Selection (this);
295 cut_buffer = new Selection (this);
297 clicked_regionview = 0;
298 clicked_axisview = 0;
299 clicked_routeview = 0;
300 clicked_control_point = 0;
301 last_update_frame = 0;
302 pre_press_cursor = 0;
303 _drags = new DragManager (this);
304 current_mixer_strip = 0;
307 snap_type_strings = I18N (_snap_type_strings);
308 snap_mode_strings = I18N (_snap_mode_strings);
309 zoom_focus_strings = I18N (_zoom_focus_strings);
310 edit_point_strings = I18N (_edit_point_strings);
311 #ifdef USE_RUBBERBAND
312 rb_opt_strings = I18N (_rb_opt_strings);
316 build_edit_mode_menu();
317 build_zoom_focus_menu();
318 build_track_count_menu();
319 build_snap_mode_menu();
320 build_snap_type_menu();
321 build_edit_point_menu();
323 snap_threshold = 5.0;
324 bbt_beat_subdivision = 4;
325 _visible_canvas_width = 0;
326 _visible_canvas_height = 0;
327 autoscroll_horizontal_allowed = false;
328 autoscroll_vertical_allowed = false;
333 current_interthread_info = 0;
334 _show_measures = true;
336 show_gain_after_trim = false;
338 have_pending_keyboard_selection = false;
339 _follow_playhead = true;
340 _stationary_playhead = false;
341 editor_ruler_menu = 0;
342 no_ruler_shown_update = false;
344 range_marker_menu = 0;
345 marker_menu_item = 0;
346 tempo_or_meter_marker_menu = 0;
347 transport_marker_menu = 0;
348 new_transport_marker_menu = 0;
349 editor_mixer_strip_width = Wide;
350 show_editor_mixer_when_tracks_arrive = false;
351 region_edit_menu_split_multichannel_item = 0;
352 region_edit_menu_split_item = 0;
355 current_stepping_trackview = 0;
357 entered_regionview = 0;
359 clear_entered_track = false;
362 button_release_can_deselect = true;
363 _dragging_playhead = false;
364 _dragging_edit_point = false;
365 select_new_marker = false;
367 layering_order_editor = 0;
368 no_save_visual = false;
370 within_track_canvas = false;
372 scrubbing_direction = 0;
376 location_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationMarker();
377 location_range_color = ARDOUR_UI::config()->get_canvasvar_LocationRange();
378 location_cd_marker_color = ARDOUR_UI::config()->get_canvasvar_LocationCDMarker();
379 location_loop_color = ARDOUR_UI::config()->get_canvasvar_LocationLoop();
380 location_punch_color = ARDOUR_UI::config()->get_canvasvar_LocationPunch();
382 zoom_focus = ZoomFocusLeft;
383 _edit_point = EditAtMouse;
384 _internal_editing = false;
385 current_canvas_cursor = 0;
386 _visible_track_count = 16;
388 samples_per_pixel = 2048; /* too early to use reset_zoom () */
390 _scroll_callbacks = 0;
392 zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
394 bbt_label.set_name ("EditorRulerLabel");
395 bbt_label.set_size_request (-1, (int)timebar_height);
396 bbt_label.set_alignment (1.0, 0.5);
397 bbt_label.set_padding (5,0);
399 bbt_label.set_no_show_all();
400 minsec_label.set_name ("EditorRulerLabel");
401 minsec_label.set_size_request (-1, (int)timebar_height);
402 minsec_label.set_alignment (1.0, 0.5);
403 minsec_label.set_padding (5,0);
404 minsec_label.hide ();
405 minsec_label.set_no_show_all();
406 timecode_label.set_name ("EditorRulerLabel");
407 timecode_label.set_size_request (-1, (int)timebar_height);
408 timecode_label.set_alignment (1.0, 0.5);
409 timecode_label.set_padding (5,0);
410 timecode_label.hide ();
411 timecode_label.set_no_show_all();
412 samples_label.set_name ("EditorRulerLabel");
413 samples_label.set_size_request (-1, (int)timebar_height);
414 samples_label.set_alignment (1.0, 0.5);
415 samples_label.set_padding (5,0);
416 samples_label.hide ();
417 samples_label.set_no_show_all();
419 tempo_label.set_name ("EditorRulerLabel");
420 tempo_label.set_size_request (-1, (int)timebar_height);
421 tempo_label.set_alignment (1.0, 0.5);
422 tempo_label.set_padding (5,0);
424 tempo_label.set_no_show_all();
426 meter_label.set_name ("EditorRulerLabel");
427 meter_label.set_size_request (-1, (int)timebar_height);
428 meter_label.set_alignment (1.0, 0.5);
429 meter_label.set_padding (5,0);
431 meter_label.set_no_show_all();
433 if (Profile->get_trx()) {
434 mark_label.set_text (_("Markers"));
436 mark_label.set_name ("EditorRulerLabel");
437 mark_label.set_size_request (-1, (int)timebar_height);
438 mark_label.set_alignment (1.0, 0.5);
439 mark_label.set_padding (5,0);
441 mark_label.set_no_show_all();
443 cd_mark_label.set_name ("EditorRulerLabel");
444 cd_mark_label.set_size_request (-1, (int)timebar_height);
445 cd_mark_label.set_alignment (1.0, 0.5);
446 cd_mark_label.set_padding (5,0);
447 cd_mark_label.hide();
448 cd_mark_label.set_no_show_all();
450 videotl_bar_height = 4;
451 videotl_label.set_name ("EditorRulerLabel");
452 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
453 videotl_label.set_alignment (1.0, 0.5);
454 videotl_label.set_padding (5,0);
455 videotl_label.hide();
456 videotl_label.set_no_show_all();
458 range_mark_label.set_name ("EditorRulerLabel");
459 range_mark_label.set_size_request (-1, (int)timebar_height);
460 range_mark_label.set_alignment (1.0, 0.5);
461 range_mark_label.set_padding (5,0);
462 range_mark_label.hide();
463 range_mark_label.set_no_show_all();
465 transport_mark_label.set_name ("EditorRulerLabel");
466 transport_mark_label.set_size_request (-1, (int)timebar_height);
467 transport_mark_label.set_alignment (1.0, 0.5);
468 transport_mark_label.set_padding (5,0);
469 transport_mark_label.hide();
470 transport_mark_label.set_no_show_all();
472 initialize_canvas ();
474 _summary = new EditorSummary (this);
476 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
477 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
479 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
481 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
482 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
484 edit_controls_vbox.set_spacing (0);
485 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
486 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
488 HBox* h = manage (new HBox);
489 _group_tabs = new EditorGroupTabs (this);
490 if (!ARDOUR::Profile->get_trx()) {
491 h->pack_start (*_group_tabs, PACK_SHRINK);
493 h->pack_start (edit_controls_vbox);
494 controls_layout.add (*h);
496 controls_layout.set_name ("EditControlsBase");
497 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
498 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
499 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
501 _cursors = new MouseCursors;
502 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());
503 cerr << "Set cursor set to " << ARDOUR_UI::config()->get_icon_set() << endl;
505 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
507 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
508 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
509 pad_line_1->set_outline_color (0xFF0000FF);
515 edit_packer.set_col_spacings (0);
516 edit_packer.set_row_spacings (0);
517 edit_packer.set_homogeneous (false);
518 edit_packer.set_border_width (0);
519 edit_packer.set_name ("EditorWindow");
521 time_bars_event_box.add (time_bars_vbox);
522 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
523 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
525 /* labels for the time bars */
526 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
528 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
530 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
532 bottom_hbox.set_border_width (2);
533 bottom_hbox.set_spacing (3);
535 _route_groups = new EditorRouteGroups (this);
536 _routes = new EditorRoutes (this);
537 _regions = new EditorRegions (this);
538 _snapshots = new EditorSnapshots (this);
539 _locations = new EditorLocations (this);
541 add_notebook_page (_("Regions"), _regions->widget ());
542 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
543 add_notebook_page (_("Snapshots"), _snapshots->widget ());
544 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
545 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
547 _the_notebook.set_show_tabs (true);
548 _the_notebook.set_scrollable (true);
549 _the_notebook.popup_disable ();
550 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
551 _the_notebook.show_all ();
553 _notebook_shrunk = false;
555 editor_summary_pane.pack1(edit_packer);
557 Button* summary_arrows_left_left = manage (new Button);
558 summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
559 summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
560 summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
562 Button* summary_arrows_left_right = manage (new Button);
563 summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
564 summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
565 summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
567 VBox* summary_arrows_left = manage (new VBox);
568 summary_arrows_left->pack_start (*summary_arrows_left_left);
569 summary_arrows_left->pack_start (*summary_arrows_left_right);
571 Button* summary_arrows_right_up = manage (new Button);
572 summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
573 summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
574 summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
576 Button* summary_arrows_right_down = manage (new Button);
577 summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
578 summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
579 summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
581 VBox* summary_arrows_right = manage (new VBox);
582 summary_arrows_right->pack_start (*summary_arrows_right_up);
583 summary_arrows_right->pack_start (*summary_arrows_right_down);
585 Frame* summary_frame = manage (new Frame);
586 summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
588 summary_frame->add (*_summary);
589 summary_frame->show ();
591 _summary_hbox.pack_start (*summary_arrows_left, false, false);
592 _summary_hbox.pack_start (*summary_frame, true, true);
593 _summary_hbox.pack_start (*summary_arrows_right, false, false);
595 if (!ARDOUR::Profile->get_trx()) {
596 editor_summary_pane.pack2 (_summary_hbox);
599 edit_pane.pack1 (editor_summary_pane, true, true);
600 if (!ARDOUR::Profile->get_trx()) {
601 edit_pane.pack2 (_the_notebook, false, true);
604 editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
606 /* XXX: editor_summary_pane might need similar to the edit_pane */
608 edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
610 Glib::PropertyProxy<int> proxy = edit_pane.property_position();
611 proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
613 top_hbox.pack_start (toolbar_frame);
615 HBox *hbox = manage (new HBox);
616 hbox->pack_start (edit_pane, true, true);
618 global_vpacker.pack_start (top_hbox, false, false);
619 global_vpacker.pack_start (*hbox, true, true);
621 global_hpacker.pack_start (global_vpacker, true, true);
623 set_name ("EditorWindow");
624 add_accel_group (ActionManager::ui_manager->get_accel_group());
626 status_bar_hpacker.show ();
628 vpacker.pack_end (status_bar_hpacker, false, false);
629 vpacker.pack_end (global_hpacker, true, true);
631 /* register actions now so that set_state() can find them and set toggles/checks etc */
634 /* when we start using our own keybinding system for the editor, this
635 * will be uncommented
641 set_zoom_focus (zoom_focus);
642 set_visible_track_count (_visible_track_count);
643 _snap_type = SnapToBeat;
644 set_snap_to (_snap_type);
645 _snap_mode = SnapOff;
646 set_snap_mode (_snap_mode);
647 set_mouse_mode (MouseObject, true);
648 pre_internal_mouse_mode = MouseObject;
649 pre_internal_snap_type = _snap_type;
650 pre_internal_snap_mode = _snap_mode;
651 internal_snap_type = _snap_type;
652 internal_snap_mode = _snap_mode;
653 set_edit_point_preference (EditAtMouse, true);
655 _playlist_selector = new PlaylistSelector();
656 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
658 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
662 nudge_forward_button.set_name ("nudge button");
663 // nudge_forward_button.add_elements (ArdourButton::Inset);
664 nudge_forward_button.set_image(::get_icon("nudge_right"));
666 nudge_backward_button.set_name ("nudge button");
667 // nudge_backward_button.add_elements (ArdourButton::Inset);
668 nudge_backward_button.set_image(::get_icon("nudge_left"));
670 fade_context_menu.set_name ("ArdourContextMenu");
672 /* icons, titles, WM stuff */
674 list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
675 Glib::RefPtr<Gdk::Pixbuf> icon;
677 if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
678 window_icons.push_back (icon);
680 if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
681 window_icons.push_back (icon);
683 if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
684 window_icons.push_back (icon);
686 if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
687 window_icons.push_back (icon);
689 if (!window_icons.empty()) {
690 // set_icon_list (window_icons);
691 set_default_icon_list (window_icons);
694 WindowTitle title(Glib::get_application_name());
695 title += _("Editor");
696 set_title (title.get_string());
697 set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
700 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
702 signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
703 signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
705 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
707 /* allow external control surfaces/protocols to do various things */
709 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
710 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
711 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
712 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
713 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
714 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
715 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
716 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
717 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
718 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
719 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
720 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
721 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
722 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
724 ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
725 ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
726 ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
727 ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
728 ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
730 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
732 /* problematic: has to return a value and thus cannot be x-thread */
734 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
736 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
737 ARDOUR_UI::config()->ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
739 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
741 _ignore_region_action = false;
742 _last_region_menu_was_main = false;
743 _popup_region_menu_item = 0;
745 _show_marker_lines = false;
747 /* Button bindings */
749 button_bindings = new Bindings;
751 XMLNode* node = button_settings();
753 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
754 button_bindings->load (**i);
761 setup_fade_images ();
766 delete button_bindings;
768 delete _route_groups;
769 delete _track_canvas_viewport;
774 Editor::button_settings () const
776 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
777 XMLNode* node = find_named_node (*settings, X_("Buttons"));
780 node = new XMLNode (X_("Buttons"));
787 Editor::add_toplevel_controls (Container& cont)
789 vpacker.pack_start (cont, false, false);
794 Editor::get_smart_mode () const
796 return ((current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active());
800 Editor::catch_vanishing_regionview (RegionView *rv)
802 /* note: the selection will take care of the vanishing
803 audioregionview by itself.
806 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
810 if (clicked_regionview == rv) {
811 clicked_regionview = 0;
814 if (entered_regionview == rv) {
815 set_entered_regionview (0);
818 if (!_all_region_actions_sensitized) {
819 sensitize_all_region_actions (true);
824 Editor::set_entered_regionview (RegionView* rv)
826 if (rv == entered_regionview) {
830 if (entered_regionview) {
831 entered_regionview->exited ();
834 entered_regionview = rv;
836 if (entered_regionview != 0) {
837 entered_regionview->entered (internal_editing ());
840 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
841 /* This RegionView entry might have changed what region actions
842 are allowed, so sensitize them all in case a key is pressed.
844 sensitize_all_region_actions (true);
849 Editor::set_entered_track (TimeAxisView* tav)
852 entered_track->exited ();
858 entered_track->entered ();
863 Editor::show_window ()
865 if (!is_visible ()) {
868 /* XXX: this is a bit unfortunate; it would probably
869 be nicer if we could just call show () above rather
870 than needing the show_all ()
873 /* re-hide stuff if necessary */
874 editor_list_button_toggled ();
875 parameter_changed ("show-summary");
876 parameter_changed ("show-group-tabs");
877 parameter_changed ("show-zoom-tools");
879 /* now reset all audio_time_axis heights, because widgets might need
885 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
886 tv = (static_cast<TimeAxisView*>(*i));
890 if (current_mixer_strip) {
891 current_mixer_strip->hide_things ();
892 current_mixer_strip->parameter_changed ("mixer-strip-visibility");
900 Editor::instant_save ()
902 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
907 _session->add_instant_xml(get_state());
909 Config->add_instant_xml(get_state());
914 Editor::zoom_adjustment_changed ()
920 framecnt_t fpu = llrintf (zoom_range_clock->current_duration() / _visible_canvas_width);
921 bool clamped = clamp_samples_per_pixel (fpu);
924 zoom_range_clock->set ((framepos_t) floor (fpu * _visible_canvas_width));
931 Editor::control_vertical_zoom_in_all ()
933 tav_zoom_smooth (false, true);
937 Editor::control_vertical_zoom_out_all ()
939 tav_zoom_smooth (true, true);
943 Editor::control_vertical_zoom_in_selected ()
945 tav_zoom_smooth (false, false);
949 Editor::control_vertical_zoom_out_selected ()
951 tav_zoom_smooth (true, false);
955 Editor::control_view (uint32_t view)
957 goto_visual_state (view);
961 Editor::control_unselect ()
963 selection->clear_tracks ();
967 Editor::control_select (uint32_t rid, Selection::Operation op)
969 /* handles the (static) signal from the ControlProtocol class that
970 * requests setting the selected track to a given RID
977 boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
983 TimeAxisView* tav = axis_view_from_route (r);
988 selection->add (tav);
990 case Selection::Toggle:
991 selection->toggle (tav);
993 case Selection::Extend:
996 selection->set (tav);
1000 selection->clear_tracks ();
1005 Editor::control_step_tracks_up ()
1007 scroll_tracks_up_line ();
1011 Editor::control_step_tracks_down ()
1013 scroll_tracks_down_line ();
1017 Editor::control_scroll (float fraction)
1019 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1025 double step = fraction * current_page_samples();
1028 _control_scroll_target is an optional<T>
1030 it acts like a pointer to an framepos_t, with
1031 a operator conversion to boolean to check
1032 that it has a value could possibly use
1033 playhead_cursor->current_frame to store the
1034 value and a boolean in the class to know
1035 when it's out of date
1038 if (!_control_scroll_target) {
1039 _control_scroll_target = _session->transport_frame();
1040 _dragging_playhead = true;
1043 if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
1044 *_control_scroll_target = 0;
1045 } else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1046 *_control_scroll_target = max_framepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1048 *_control_scroll_target += (framepos_t) floor (step);
1051 /* move visuals, we'll catch up with it later */
1053 playhead_cursor->set_position (*_control_scroll_target);
1054 UpdateAllTransportClocks (*_control_scroll_target);
1056 if (*_control_scroll_target > (current_page_samples() / 2)) {
1057 /* try to center PH in window */
1058 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1064 Now we do a timeout to actually bring the session to the right place
1065 according to the playhead. This is to avoid reading disk buffers on every
1066 call to control_scroll, which is driven by ScrollTimeline and therefore
1067 probably by a control surface wheel which can generate lots of events.
1069 /* cancel the existing timeout */
1071 control_scroll_connection.disconnect ();
1073 /* add the next timeout */
1075 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1079 Editor::deferred_control_scroll (framepos_t /*target*/)
1081 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1082 // reset for next stream
1083 _control_scroll_target = boost::none;
1084 _dragging_playhead = false;
1089 Editor::access_action (std::string action_group, std::string action_item)
1095 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1098 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1106 Editor::on_realize ()
1108 Window::on_realize ();
1113 Editor::map_position_change (framepos_t frame)
1115 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1117 if (_session == 0) {
1121 if (_follow_playhead) {
1122 center_screen (frame);
1125 playhead_cursor->set_position (frame);
1129 Editor::center_screen (framepos_t frame)
1131 framecnt_t const page = _visible_canvas_width * samples_per_pixel;
1133 /* if we're off the page, then scroll.
1136 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1137 center_screen_internal (frame, page);
1142 Editor::center_screen_internal (framepos_t frame, float page)
1147 frame -= (framepos_t) page;
1152 reset_x_origin (frame);
1157 Editor::update_title ()
1159 ENSURE_GUI_THREAD (*this, &Editor::update_title)
1162 bool dirty = _session->dirty();
1164 string session_name;
1166 if (_session->snap_name() != _session->name()) {
1167 session_name = _session->snap_name();
1169 session_name = _session->name();
1173 session_name = "*" + session_name;
1176 WindowTitle title(session_name);
1177 title += Glib::get_application_name();
1178 set_title (title.get_string());
1180 /* ::session_going_away() will have taken care of it */
1185 Editor::set_session (Session *t)
1187 SessionHandlePtr::set_session (t);
1193 zoom_range_clock->set_session (_session);
1194 _playlist_selector->set_session (_session);
1195 nudge_clock->set_session (_session);
1196 _summary->set_session (_session);
1197 _group_tabs->set_session (_session);
1198 _route_groups->set_session (_session);
1199 _regions->set_session (_session);
1200 _snapshots->set_session (_session);
1201 _routes->set_session (_session);
1202 _locations->set_session (_session);
1204 if (rhythm_ferret) {
1205 rhythm_ferret->set_session (_session);
1208 if (analysis_window) {
1209 analysis_window->set_session (_session);
1213 sfbrowser->set_session (_session);
1216 compute_fixed_ruler_scale ();
1218 /* Make sure we have auto loop and auto punch ranges */
1220 Location* loc = _session->locations()->auto_loop_location();
1222 loc->set_name (_("Loop"));
1225 loc = _session->locations()->auto_punch_location();
1228 loc->set_name (_("Punch"));
1231 refresh_location_display ();
1233 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1234 the selected Marker; this needs the LocationMarker list to be available.
1236 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1237 set_state (*node, Stateful::loading_state_version);
1239 /* catch up with the playhead */
1241 _session->request_locate (playhead_cursor->current_frame ());
1242 _pending_initial_locate = true;
1246 /* These signals can all be emitted by a non-GUI thread. Therefore the
1247 handlers for them must not attempt to directly interact with the GUI,
1248 but use PBD::Signal<T>::connect() which accepts an event loop
1249 ("context") where the handler will be asked to run.
1252 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1253 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1254 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1255 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1256 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1257 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1258 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1259 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1260 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1261 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1262 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1263 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1264 _session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1265 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1267 playhead_cursor->show ();
1269 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1270 Config->map_parameters (pc);
1271 _session->config.map_parameters (pc);
1273 restore_ruler_visibility ();
1274 //tempo_map_changed (PropertyChange (0));
1275 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1277 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1278 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1281 super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1282 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1285 switch (_snap_type) {
1286 case SnapToRegionStart:
1287 case SnapToRegionEnd:
1288 case SnapToRegionSync:
1289 case SnapToRegionBoundary:
1290 build_region_boundary_cache ();
1297 /* register for undo history */
1298 _session->register_with_memento_command_factory(id(), this);
1300 ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1302 start_updating_meters ();
1306 Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1308 if (a->get_name() == "RegionMenu") {
1309 /* When the main menu's region menu is opened, we setup the actions so that they look right
1310 in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1311 so we resensitize all region actions when the entered regionview or the region selection
1312 changes. HOWEVER we can't always resensitize on entered_regionview change because that
1313 happens after the region context menu is opened. So we set a flag here, too.
1317 sensitize_the_right_region_actions ();
1318 _last_region_menu_was_main = true;
1323 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1325 using namespace Menu_Helpers;
1327 void (Editor::*emf)(FadeShape);
1328 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1331 images = &_xfade_in_images;
1332 emf = &Editor::set_fade_in_shape;
1334 images = &_xfade_out_images;
1335 emf = &Editor::set_fade_out_shape;
1340 _("Linear (for highly correlated material)"),
1341 *(*images)[FadeLinear],
1342 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1346 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1350 _("Constant power"),
1351 *(*images)[FadeConstantPower],
1352 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1355 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1360 *(*images)[FadeSymmetric],
1361 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1365 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1370 *(*images)[FadeSlow],
1371 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1374 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1379 *(*images)[FadeFast],
1380 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1383 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1386 /** Pop up a context menu for when the user clicks on a start crossfade */
1388 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1390 using namespace Menu_Helpers;
1391 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1394 MenuList& items (xfade_in_context_menu.items());
1397 if (arv->audio_region()->fade_in_active()) {
1398 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1400 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1403 items.push_back (SeparatorElem());
1404 fill_xfade_menu (items, true);
1406 xfade_in_context_menu.popup (button, time);
1409 /** Pop up a context menu for when the user clicks on an end crossfade */
1411 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1413 using namespace Menu_Helpers;
1414 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1417 MenuList& items (xfade_out_context_menu.items());
1420 if (arv->audio_region()->fade_out_active()) {
1421 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1423 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1426 items.push_back (SeparatorElem());
1427 fill_xfade_menu (items, false);
1429 xfade_out_context_menu.popup (button, time);
1433 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1435 using namespace Menu_Helpers;
1436 Menu* (Editor::*build_menu_function)();
1439 switch (item_type) {
1441 case RegionViewName:
1442 case RegionViewNameHighlight:
1443 case LeftFrameHandle:
1444 case RightFrameHandle:
1445 if (with_selection) {
1446 build_menu_function = &Editor::build_track_selection_context_menu;
1448 build_menu_function = &Editor::build_track_region_context_menu;
1453 if (with_selection) {
1454 build_menu_function = &Editor::build_track_selection_context_menu;
1456 build_menu_function = &Editor::build_track_context_menu;
1461 if (clicked_routeview->track()) {
1462 build_menu_function = &Editor::build_track_context_menu;
1464 build_menu_function = &Editor::build_track_bus_context_menu;
1469 /* probably shouldn't happen but if it does, we don't care */
1473 menu = (this->*build_menu_function)();
1474 menu->set_name ("ArdourContextMenu");
1476 /* now handle specific situations */
1478 switch (item_type) {
1480 case RegionViewName:
1481 case RegionViewNameHighlight:
1482 case LeftFrameHandle:
1483 case RightFrameHandle:
1484 if (!with_selection) {
1485 if (region_edit_menu_split_item) {
1486 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1487 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1489 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1492 if (region_edit_menu_split_multichannel_item) {
1493 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1494 region_edit_menu_split_multichannel_item->set_sensitive (true);
1496 region_edit_menu_split_multichannel_item->set_sensitive (false);
1509 /* probably shouldn't happen but if it does, we don't care */
1513 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1515 /* Bounce to disk */
1517 using namespace Menu_Helpers;
1518 MenuList& edit_items = menu->items();
1520 edit_items.push_back (SeparatorElem());
1522 switch (clicked_routeview->audio_track()->freeze_state()) {
1523 case AudioTrack::NoFreeze:
1524 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1527 case AudioTrack::Frozen:
1528 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1531 case AudioTrack::UnFrozen:
1532 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1538 if (item_type == StreamItem && clicked_routeview) {
1539 clicked_routeview->build_underlay_menu(menu);
1542 /* When the region menu is opened, we setup the actions so that they look right
1545 sensitize_the_right_region_actions ();
1546 _last_region_menu_was_main = false;
1548 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1549 menu->popup (button, time);
1553 Editor::build_track_context_menu ()
1555 using namespace Menu_Helpers;
1557 MenuList& edit_items = track_context_menu.items();
1560 add_dstream_context_items (edit_items);
1561 return &track_context_menu;
1565 Editor::build_track_bus_context_menu ()
1567 using namespace Menu_Helpers;
1569 MenuList& edit_items = track_context_menu.items();
1572 add_bus_context_items (edit_items);
1573 return &track_context_menu;
1577 Editor::build_track_region_context_menu ()
1579 using namespace Menu_Helpers;
1580 MenuList& edit_items = track_region_context_menu.items();
1583 /* we've just cleared the track region context menu, so the menu that these
1584 two items were on will have disappeared; stop them dangling.
1586 region_edit_menu_split_item = 0;
1587 region_edit_menu_split_multichannel_item = 0;
1589 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1592 boost::shared_ptr<Track> tr;
1593 boost::shared_ptr<Playlist> pl;
1595 if ((tr = rtv->track())) {
1596 add_region_context_items (edit_items, tr);
1600 add_dstream_context_items (edit_items);
1602 return &track_region_context_menu;
1606 Editor::analyze_region_selection ()
1608 if (analysis_window == 0) {
1609 analysis_window = new AnalysisWindow();
1612 analysis_window->set_session(_session);
1614 analysis_window->show_all();
1617 analysis_window->set_regionmode();
1618 analysis_window->analyze();
1620 analysis_window->present();
1624 Editor::analyze_range_selection()
1626 if (analysis_window == 0) {
1627 analysis_window = new AnalysisWindow();
1630 analysis_window->set_session(_session);
1632 analysis_window->show_all();
1635 analysis_window->set_rangemode();
1636 analysis_window->analyze();
1638 analysis_window->present();
1642 Editor::build_track_selection_context_menu ()
1644 using namespace Menu_Helpers;
1645 MenuList& edit_items = track_selection_context_menu.items();
1646 edit_items.clear ();
1648 add_selection_context_items (edit_items);
1649 // edit_items.push_back (SeparatorElem());
1650 // add_dstream_context_items (edit_items);
1652 return &track_selection_context_menu;
1656 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1658 using namespace Menu_Helpers;
1660 /* OK, stick the region submenu at the top of the list, and then add
1664 RegionSelection rs = get_regions_from_selection_and_entered ();
1666 string::size_type pos = 0;
1667 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1669 /* we have to hack up the region name because "_" has a special
1670 meaning for menu titles.
1673 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1674 menu_item_name.replace (pos, 1, "__");
1678 if (_popup_region_menu_item == 0) {
1679 _popup_region_menu_item = new MenuItem (menu_item_name);
1680 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1681 _popup_region_menu_item->show ();
1683 _popup_region_menu_item->set_label (menu_item_name);
1686 const framepos_t position = get_preferred_edit_position (false, true);
1688 edit_items.push_back (*_popup_region_menu_item);
1689 if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1690 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1692 edit_items.push_back (SeparatorElem());
1695 /** Add context menu items relevant to selection ranges.
1696 * @param edit_items List to add the items to.
1699 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1701 using namespace Menu_Helpers;
1703 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1704 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1706 edit_items.push_back (SeparatorElem());
1707 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1709 edit_items.push_back (SeparatorElem());
1711 edit_items.push_back (
1713 _("Move Range Start to Previous Region Boundary"),
1714 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1718 edit_items.push_back (
1720 _("Move Range Start to Next Region Boundary"),
1721 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1725 edit_items.push_back (
1727 _("Move Range End to Previous Region Boundary"),
1728 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1732 edit_items.push_back (
1734 _("Move Range End to Next Region Boundary"),
1735 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1739 edit_items.push_back (SeparatorElem());
1740 edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1741 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1743 edit_items.push_back (SeparatorElem());
1744 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1746 edit_items.push_back (SeparatorElem());
1747 edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1748 edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1750 edit_items.push_back (SeparatorElem());
1751 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1753 edit_items.push_back (SeparatorElem());
1754 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1755 edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1756 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1758 edit_items.push_back (SeparatorElem());
1759 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1760 edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1761 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1762 edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1763 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1764 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1765 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*this, &Editor::export_video), true)));
1771 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1773 using namespace Menu_Helpers;
1777 Menu *play_menu = manage (new Menu);
1778 MenuList& play_items = play_menu->items();
1779 play_menu->set_name ("ArdourContextMenu");
1781 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1782 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1783 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1784 play_items.push_back (SeparatorElem());
1785 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1787 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1791 Menu *select_menu = manage (new Menu);
1792 MenuList& select_items = select_menu->items();
1793 select_menu->set_name ("ArdourContextMenu");
1795 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1796 select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
1797 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1798 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1799 select_items.push_back (SeparatorElem());
1800 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1801 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1802 select_items.push_back (SeparatorElem());
1803 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1804 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1805 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1806 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1807 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1808 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1809 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1811 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1815 Menu *cutnpaste_menu = manage (new Menu);
1816 MenuList& cutnpaste_items = cutnpaste_menu->items();
1817 cutnpaste_menu->set_name ("ArdourContextMenu");
1819 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1820 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1821 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1823 cutnpaste_items.push_back (SeparatorElem());
1825 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1826 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1828 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1830 /* Adding new material */
1832 edit_items.push_back (SeparatorElem());
1833 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1834 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1838 Menu *nudge_menu = manage (new Menu());
1839 MenuList& nudge_items = nudge_menu->items();
1840 nudge_menu->set_name ("ArdourContextMenu");
1842 edit_items.push_back (SeparatorElem());
1843 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1844 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1845 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1846 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1848 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1852 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1854 using namespace Menu_Helpers;
1858 Menu *play_menu = manage (new Menu);
1859 MenuList& play_items = play_menu->items();
1860 play_menu->set_name ("ArdourContextMenu");
1862 play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1863 play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1864 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1868 Menu *select_menu = manage (new Menu);
1869 MenuList& select_items = select_menu->items();
1870 select_menu->set_name ("ArdourContextMenu");
1872 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1873 select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
1874 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1875 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1876 select_items.push_back (SeparatorElem());
1877 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1878 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1879 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1880 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1882 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1886 Menu *cutnpaste_menu = manage (new Menu);
1887 MenuList& cutnpaste_items = cutnpaste_menu->items();
1888 cutnpaste_menu->set_name ("ArdourContextMenu");
1890 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1891 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1892 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1894 Menu *nudge_menu = manage (new Menu());
1895 MenuList& nudge_items = nudge_menu->items();
1896 nudge_menu->set_name ("ArdourContextMenu");
1898 edit_items.push_back (SeparatorElem());
1899 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1900 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1901 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1902 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1904 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1908 Editor::snap_type() const
1914 Editor::snap_mode() const
1920 Editor::set_snap_to (SnapType st)
1922 unsigned int snap_ind = (unsigned int)st;
1926 if (snap_ind > snap_type_strings.size() - 1) {
1928 _snap_type = (SnapType)snap_ind;
1931 string str = snap_type_strings[snap_ind];
1933 if (str != snap_type_selector.get_text()) {
1934 snap_type_selector.set_text (str);
1939 switch (_snap_type) {
1940 case SnapToBeatDiv128:
1941 case SnapToBeatDiv64:
1942 case SnapToBeatDiv32:
1943 case SnapToBeatDiv28:
1944 case SnapToBeatDiv24:
1945 case SnapToBeatDiv20:
1946 case SnapToBeatDiv16:
1947 case SnapToBeatDiv14:
1948 case SnapToBeatDiv12:
1949 case SnapToBeatDiv10:
1950 case SnapToBeatDiv8:
1951 case SnapToBeatDiv7:
1952 case SnapToBeatDiv6:
1953 case SnapToBeatDiv5:
1954 case SnapToBeatDiv4:
1955 case SnapToBeatDiv3:
1956 case SnapToBeatDiv2: {
1957 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
1958 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
1960 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(),
1961 current_bbt_points_begin, current_bbt_points_end);
1962 compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_samples(),
1963 current_bbt_points_begin, current_bbt_points_end);
1964 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
1968 case SnapToRegionStart:
1969 case SnapToRegionEnd:
1970 case SnapToRegionSync:
1971 case SnapToRegionBoundary:
1972 build_region_boundary_cache ();
1980 SnapChanged (); /* EMIT SIGNAL */
1984 Editor::set_snap_mode (SnapMode mode)
1986 string str = snap_mode_strings[(int)mode];
1988 if (_internal_editing) {
1989 internal_snap_mode = mode;
1991 pre_internal_snap_mode = mode;
1996 if (str != snap_mode_selector.get_text ()) {
1997 snap_mode_selector.set_text (str);
2003 Editor::set_edit_point_preference (EditPoint ep, bool force)
2005 bool changed = (_edit_point != ep);
2008 string str = edit_point_strings[(int)ep];
2010 if (str != edit_point_selector.get_text ()) {
2011 edit_point_selector.set_text (str);
2014 reset_canvas_cursor ();
2016 if (!force && !changed) {
2020 const char* action=NULL;
2022 switch (_edit_point) {
2023 case EditAtPlayhead:
2024 action = "edit-at-playhead";
2026 case EditAtSelectedMarker:
2027 action = "edit-at-marker";
2030 action = "edit-at-mouse";
2034 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2036 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2040 bool in_track_canvas;
2042 if (!mouse_frame (foo, in_track_canvas)) {
2043 in_track_canvas = false;
2046 reset_canvas_action_sensitivity (in_track_canvas);
2052 Editor::set_state (const XMLNode& node, int /*version*/)
2054 const XMLProperty* prop;
2061 g.base_width = default_width;
2062 g.base_height = default_height;
2066 if ((geometry = find_named_node (node, "geometry")) != 0) {
2070 if ((prop = geometry->property("x_size")) == 0) {
2071 prop = geometry->property ("x-size");
2074 g.base_width = atoi(prop->value());
2076 if ((prop = geometry->property("y_size")) == 0) {
2077 prop = geometry->property ("y-size");
2080 g.base_height = atoi(prop->value());
2083 if ((prop = geometry->property ("x_pos")) == 0) {
2084 prop = geometry->property ("x-pos");
2087 x = atoi (prop->value());
2090 if ((prop = geometry->property ("y_pos")) == 0) {
2091 prop = geometry->property ("y-pos");
2094 y = atoi (prop->value());
2098 set_default_size (g.base_width, g.base_height);
2101 if (_session && (prop = node.property ("playhead"))) {
2103 sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2104 playhead_cursor->set_position (pos);
2106 playhead_cursor->set_position (0);
2109 if ((prop = node.property ("mixer-width"))) {
2110 editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2113 if ((prop = node.property ("zoom-focus"))) {
2114 zoom_focus_selection_done ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2117 if ((prop = node.property ("zoom"))) {
2118 /* older versions of ardour used floating point samples_per_pixel */
2119 double f = PBD::atof (prop->value());
2120 reset_zoom (llrintf (f));
2122 reset_zoom (samples_per_pixel);
2125 if ((prop = node.property ("visible-track-count"))) {
2126 set_visible_track_count (PBD::atoi (prop->value()));
2129 if ((prop = node.property ("snap-to"))) {
2130 snap_type_selection_done ((SnapType) string_2_enum (prop->value(), _snap_type));
2133 if ((prop = node.property ("snap-mode"))) {
2134 snap_mode_selection_done((SnapMode) string_2_enum (prop->value(), _snap_mode));
2137 if ((prop = node.property ("internal-snap-to"))) {
2138 internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2141 if ((prop = node.property ("internal-snap-mode"))) {
2142 internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2145 if ((prop = node.property ("pre-internal-snap-to"))) {
2146 pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2150 if ((prop = node.property ("pre-internal-snap-mode"))) {
2151 pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2154 if ((prop = node.property ("mouse-mode"))) {
2155 MouseMode m = str2mousemode(prop->value());
2156 set_mouse_mode (m, true);
2158 set_mouse_mode (MouseObject, true);
2161 if ((prop = node.property ("left-frame")) != 0) {
2163 if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2167 reset_x_origin (pos);
2171 if ((prop = node.property ("y-origin")) != 0) {
2172 reset_y_origin (atof (prop->value ()));
2175 if ((prop = node.property ("internal-edit"))) {
2176 bool yn = string_is_affirmative (prop->value());
2177 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2179 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2180 tact->set_active (!yn);
2181 tact->set_active (yn);
2185 if ((prop = node.property ("join-object-range"))) {
2186 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2187 bool yn = string_is_affirmative (prop->value());
2189 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2190 tact->set_active (!yn);
2191 tact->set_active (yn);
2193 set_mouse_mode(mouse_mode, true);
2196 if ((prop = node.property ("edit-point"))) {
2197 set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2200 if ((prop = node.property ("show-measures"))) {
2201 bool yn = string_is_affirmative (prop->value());
2202 _show_measures = yn;
2203 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2205 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2206 /* do it twice to force the change */
2207 tact->set_active (!yn);
2208 tact->set_active (yn);
2212 if ((prop = node.property ("follow-playhead"))) {
2213 bool yn = string_is_affirmative (prop->value());
2214 set_follow_playhead (yn);
2215 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2217 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2218 if (tact->get_active() != yn) {
2219 tact->set_active (yn);
2224 if ((prop = node.property ("stationary-playhead"))) {
2225 bool yn = string_is_affirmative (prop->value());
2226 set_stationary_playhead (yn);
2227 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2229 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2230 if (tact->get_active() != yn) {
2231 tact->set_active (yn);
2236 if ((prop = node.property ("region-list-sort-type"))) {
2237 RegionListSortType st;
2238 _regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2241 if ((prop = node.property ("show-editor-mixer"))) {
2243 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2246 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2247 bool yn = string_is_affirmative (prop->value());
2249 /* do it twice to force the change */
2251 tact->set_active (!yn);
2252 tact->set_active (yn);
2255 if ((prop = node.property ("show-editor-list"))) {
2257 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2260 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2261 bool yn = string_is_affirmative (prop->value());
2263 /* do it twice to force the change */
2265 tact->set_active (!yn);
2266 tact->set_active (yn);
2269 if ((prop = node.property (X_("editor-list-page")))) {
2270 _the_notebook.set_current_page (atoi (prop->value ()));
2273 if ((prop = node.property (X_("show-marker-lines")))) {
2274 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2276 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2277 bool yn = string_is_affirmative (prop->value ());
2279 tact->set_active (!yn);
2280 tact->set_active (yn);
2283 XMLNodeList children = node.children ();
2284 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2285 selection->set_state (**i, Stateful::current_state_version);
2286 _regions->set_state (**i);
2289 if ((prop = node.property ("maximised"))) {
2290 bool yn = string_is_affirmative (prop->value());
2291 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2293 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2294 bool fs = tact && tact->get_active();
2296 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2300 if ((prop = node.property ("nudge-clock-value"))) {
2302 sscanf (prop->value().c_str(), "%" PRId64, &f);
2303 nudge_clock->set (f);
2305 nudge_clock->set_mode (AudioClock::Timecode);
2306 nudge_clock->set (_session->frame_rate() * 5, true);
2313 Editor::get_state ()
2315 XMLNode* node = new XMLNode ("Editor");
2318 id().print (buf, sizeof (buf));
2319 node->add_property ("id", buf);
2321 if (is_realized()) {
2322 Glib::RefPtr<Gdk::Window> win = get_window();
2324 int x, y, width, height;
2325 win->get_root_origin(x, y);
2326 win->get_size(width, height);
2328 XMLNode* geometry = new XMLNode ("geometry");
2330 snprintf(buf, sizeof(buf), "%d", width);
2331 geometry->add_property("x-size", string(buf));
2332 snprintf(buf, sizeof(buf), "%d", height);
2333 geometry->add_property("y-size", string(buf));
2334 snprintf(buf, sizeof(buf), "%d", x);
2335 geometry->add_property("x-pos", string(buf));
2336 snprintf(buf, sizeof(buf), "%d", y);
2337 geometry->add_property("y-pos", string(buf));
2338 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2339 geometry->add_property("edit-horizontal-pane-pos", string(buf));
2340 geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2341 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2342 geometry->add_property("edit-vertical-pane-pos", string(buf));
2344 node->add_child_nocopy (*geometry);
2347 maybe_add_mixer_strip_width (*node);
2349 node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2351 snprintf (buf, sizeof(buf), "%" PRId64, samples_per_pixel);
2352 node->add_property ("zoom", buf);
2353 node->add_property ("snap-to", enum_2_string (_snap_type));
2354 node->add_property ("snap-mode", enum_2_string (_snap_mode));
2355 node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2356 node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2357 node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2358 node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2359 node->add_property ("edit-point", enum_2_string (_edit_point));
2360 snprintf (buf, sizeof(buf), "%d", _visible_track_count);
2361 node->add_property ("visible-track-count", buf);
2363 snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame ());
2364 node->add_property ("playhead", buf);
2365 snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2366 node->add_property ("left-frame", buf);
2367 snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2368 node->add_property ("y-origin", buf);
2370 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2371 node->add_property ("maximised", _maximised ? "yes" : "no");
2372 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2373 node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2374 node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2375 node->add_property ("mouse-mode", enum2str(mouse_mode));
2376 node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2377 node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2379 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2381 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2382 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2385 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2387 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2388 node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2391 snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2392 node->add_property (X_("editor-list-page"), buf);
2394 if (button_bindings) {
2395 XMLNode* bb = new XMLNode (X_("Buttons"));
2396 button_bindings->save (*bb);
2397 node->add_child_nocopy (*bb);
2400 node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2402 node->add_child_nocopy (selection->get_state ());
2403 node->add_child_nocopy (_regions->get_state ());
2405 snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2406 node->add_property ("nudge-clock-value", buf);
2411 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2412 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2414 * @return pair: TimeAxisView that y is over, layer index.
2416 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2417 * in stacked or expanded region display mode, otherwise 0.
2419 std::pair<TimeAxisView *, double>
2420 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2422 if (!trackview_relative_offset) {
2423 y -= _trackview_group->canvas_origin().y;
2427 return std::make_pair ( (TimeAxisView *) 0, 0);
2430 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2432 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2439 return std::make_pair ( (TimeAxisView *) 0, 0);
2442 /** Snap a position to the grid, if appropriate, taking into account current
2443 * grid settings and also the state of any snap modifier keys that may be pressed.
2444 * @param start Position to snap.
2445 * @param event Event to get current key modifier information from, or 0.
2448 Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2450 if (!_session || !event) {
2454 if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2455 if (_snap_mode == SnapOff) {
2456 snap_to_internal (start, direction, for_mark);
2459 if (_snap_mode != SnapOff) {
2460 snap_to_internal (start, direction, for_mark);
2466 Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2468 if (!_session || _snap_mode == SnapOff) {
2472 snap_to_internal (start, direction, for_mark);
2476 Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2478 const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2479 framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2481 switch (_snap_type) {
2482 case SnapToTimecodeFrame:
2483 if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2484 start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2486 start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2490 case SnapToTimecodeSeconds:
2491 if (_session->config.get_timecode_offset_negative()) {
2492 start += _session->config.get_timecode_offset ();
2494 start -= _session->config.get_timecode_offset ();
2496 if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2497 start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2499 start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2502 if (_session->config.get_timecode_offset_negative()) {
2503 start -= _session->config.get_timecode_offset ();
2505 start += _session->config.get_timecode_offset ();
2509 case SnapToTimecodeMinutes:
2510 if (_session->config.get_timecode_offset_negative()) {
2511 start += _session->config.get_timecode_offset ();
2513 start -= _session->config.get_timecode_offset ();
2515 if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2516 start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2518 start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2520 if (_session->config.get_timecode_offset_negative()) {
2521 start -= _session->config.get_timecode_offset ();
2523 start += _session->config.get_timecode_offset ();
2527 fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2533 Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2535 const framepos_t one_second = _session->frame_rate();
2536 const framepos_t one_minute = _session->frame_rate() * 60;
2537 framepos_t presnap = start;
2541 switch (_snap_type) {
2542 case SnapToTimecodeFrame:
2543 case SnapToTimecodeSeconds:
2544 case SnapToTimecodeMinutes:
2545 return timecode_snap_to_internal (start, direction, for_mark);
2548 if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2549 start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2551 start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2556 if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2557 start = (framepos_t) ceil ((double) start / one_second) * one_second;
2559 start = (framepos_t) floor ((double) start / one_second) * one_second;
2564 if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2565 start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2567 start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2572 start = _session->tempo_map().round_to_bar (start, direction);
2576 start = _session->tempo_map().round_to_beat (start, direction);
2579 case SnapToBeatDiv128:
2580 start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2582 case SnapToBeatDiv64:
2583 start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2585 case SnapToBeatDiv32:
2586 start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2588 case SnapToBeatDiv28:
2589 start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2591 case SnapToBeatDiv24:
2592 start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2594 case SnapToBeatDiv20:
2595 start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2597 case SnapToBeatDiv16:
2598 start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2600 case SnapToBeatDiv14:
2601 start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2603 case SnapToBeatDiv12:
2604 start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2606 case SnapToBeatDiv10:
2607 start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2609 case SnapToBeatDiv8:
2610 start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2612 case SnapToBeatDiv7:
2613 start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2615 case SnapToBeatDiv6:
2616 start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2618 case SnapToBeatDiv5:
2619 start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2621 case SnapToBeatDiv4:
2622 start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2624 case SnapToBeatDiv3:
2625 start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2627 case SnapToBeatDiv2:
2628 start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2636 _session->locations()->marks_either_side (start, before, after);
2638 if (before == max_framepos && after == max_framepos) {
2639 /* No marks to snap to, so just don't snap */
2641 } else if (before == max_framepos) {
2643 } else if (after == max_framepos) {
2645 } else if (before != max_framepos && after != max_framepos) {
2646 /* have before and after */
2647 if ((start - before) < (after - start)) {
2656 case SnapToRegionStart:
2657 case SnapToRegionEnd:
2658 case SnapToRegionSync:
2659 case SnapToRegionBoundary:
2660 if (!region_boundary_cache.empty()) {
2662 vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2663 vector<framepos_t>::iterator next = region_boundary_cache.end ();
2665 if (direction > 0) {
2666 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2668 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2671 if (next != region_boundary_cache.begin ()) {
2676 framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2677 framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2679 if (start > (p + n) / 2) {
2688 switch (_snap_mode) {
2694 if (presnap > start) {
2695 if (presnap > (start + pixel_to_sample(snap_threshold))) {
2699 } else if (presnap < start) {
2700 if (presnap < (start - pixel_to_sample(snap_threshold))) {
2706 /* handled at entry */
2714 Editor::setup_toolbar ()
2716 HBox* mode_box = manage(new HBox);
2717 mode_box->set_border_width (2);
2718 mode_box->set_spacing(4);
2720 HBox* mouse_mode_box = manage (new HBox);
2721 HBox* mouse_mode_hbox = manage (new HBox);
2722 VBox* mouse_mode_vbox = manage (new VBox);
2723 Alignment* mouse_mode_align = manage (new Alignment);
2725 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
2726 // mouse_mode_size_group->add_widget (smart_mode_button);
2727 mouse_mode_size_group->add_widget (mouse_move_button);
2728 mouse_mode_size_group->add_widget (mouse_select_button);
2729 mouse_mode_size_group->add_widget (mouse_zoom_button);
2730 mouse_mode_size_group->add_widget (mouse_gain_button);
2731 mouse_mode_size_group->add_widget (mouse_timefx_button);
2732 mouse_mode_size_group->add_widget (mouse_audition_button);
2733 mouse_mode_size_group->add_widget (mouse_draw_button);
2734 mouse_mode_size_group->add_widget (internal_edit_button);
2736 /* make them just a bit bigger */
2737 mouse_move_button.set_size_request (-1, 30);
2739 mouse_mode_hbox->set_spacing (2);
2741 if (!ARDOUR::Profile->get_trx()) {
2742 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2745 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2746 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2747 mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2749 if (!ARDOUR::Profile->get_trx()) {
2750 mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2751 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2752 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2753 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2754 mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
2757 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2759 mouse_mode_align->add (*mouse_mode_vbox);
2760 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2762 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2764 edit_mode_strings.push_back (edit_mode_to_string (Slide));
2765 if (!Profile->get_sae()) {
2766 edit_mode_strings.push_back (edit_mode_to_string (Splice));
2768 edit_mode_strings.push_back (edit_mode_to_string (Lock));
2770 edit_mode_selector.set_name ("mouse mode button");
2771 edit_mode_selector.set_size_request (65, -1);
2772 edit_mode_selector.add_elements (ArdourButton::Inset);
2774 if (!ARDOUR::Profile->get_trx()) {
2775 mode_box->pack_start (edit_mode_selector, false, false);
2777 mode_box->pack_start (*mouse_mode_box, false, false);
2779 _mouse_mode_tearoff = manage (new TearOff (*mode_box));
2780 _mouse_mode_tearoff->set_name ("MouseModeBase");
2781 _mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2783 if (Profile->get_sae()) {
2784 _mouse_mode_tearoff->set_can_be_torn_off (false);
2787 _mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2788 &_mouse_mode_tearoff->tearoff_window()));
2789 _mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2790 &_mouse_mode_tearoff->tearoff_window(), 1));
2791 _mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2792 &_mouse_mode_tearoff->tearoff_window()));
2793 _mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2794 &_mouse_mode_tearoff->tearoff_window(), 1));
2798 _zoom_box.set_spacing (2);
2799 _zoom_box.set_border_width (2);
2803 zoom_in_button.set_name ("zoom button");
2804 // zoom_in_button.add_elements ( ArdourButton::Inset );
2805 zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2806 zoom_in_button.set_image(::get_icon ("zoom_in"));
2807 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2808 zoom_in_button.set_related_action (act);
2810 zoom_out_button.set_name ("zoom button");
2811 // zoom_out_button.add_elements ( ArdourButton::Inset );
2812 zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2813 zoom_out_button.set_image(::get_icon ("zoom_out"));
2814 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2815 zoom_out_button.set_related_action (act);
2817 zoom_out_full_button.set_name ("zoom button");
2818 // zoom_out_full_button.add_elements ( ArdourButton::Inset );
2819 zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2820 zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2821 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2822 zoom_out_full_button.set_related_action (act);
2824 zoom_focus_selector.set_name ("zoom button");
2825 zoom_focus_selector.set_size_request (80, -1);
2826 // zoom_focus_selector.add_elements (ArdourButton::Inset);
2828 if (!ARDOUR::Profile->get_trx()) {
2829 _zoom_box.pack_start (zoom_out_button, false, false);
2830 _zoom_box.pack_start (zoom_in_button, false, false);
2831 _zoom_box.pack_start (zoom_out_full_button, false, false);
2832 _zoom_box.pack_start (zoom_focus_selector, false, false);
2834 mode_box->pack_start (zoom_out_button, false, false);
2835 mode_box->pack_start (zoom_in_button, false, false);
2838 /* Track zoom buttons */
2839 visible_tracks_selector.set_name ("zoom button");
2840 // visible_tracks_selector.add_elements ( ArdourButton::Inset );
2841 set_size_request_to_display_given_text (visible_tracks_selector, _("all"), 40, 2);
2843 tav_expand_button.set_name ("zoom button");
2844 // tav_expand_button.add_elements ( ArdourButton::FlatFace );
2845 tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2846 tav_expand_button.set_size_request (-1, 20);
2847 tav_expand_button.set_image(::get_icon ("tav_exp"));
2848 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2849 tav_expand_button.set_related_action (act);
2851 tav_shrink_button.set_name ("zoom button");
2852 // tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2853 tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2854 tav_shrink_button.set_size_request (-1, 20);
2855 tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2856 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2857 tav_shrink_button.set_related_action (act);
2859 if (!ARDOUR::Profile->get_trx()) {
2860 _zoom_box.pack_start (visible_tracks_selector);
2862 _zoom_box.pack_start (tav_shrink_button);
2863 _zoom_box.pack_start (tav_expand_button);
2865 if (!ARDOUR::Profile->get_trx()) {
2866 _zoom_tearoff = manage (new TearOff (_zoom_box));
2868 _zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2869 &_zoom_tearoff->tearoff_window()));
2870 _zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2871 &_zoom_tearoff->tearoff_window(), 0));
2872 _zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2873 &_zoom_tearoff->tearoff_window()));
2874 _zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2875 &_zoom_tearoff->tearoff_window(), 0));
2878 snap_box.set_spacing (2);
2879 snap_box.set_border_width (2);
2881 snap_type_selector.set_name ("mouse mode button");
2882 snap_type_selector.set_size_request (140, -1);
2883 snap_type_selector.add_elements (ArdourButton::Inset);
2885 snap_mode_selector.set_name ("mouse mode button");
2886 snap_mode_selector.set_size_request (85, -1);
2887 snap_mode_selector.add_elements (ArdourButton::Inset);
2889 edit_point_selector.set_name ("mouse mode button");
2890 edit_point_selector.set_size_request (85, -1);
2891 edit_point_selector.add_elements (ArdourButton::Inset);
2893 snap_box.pack_start (snap_mode_selector, false, false);
2894 snap_box.pack_start (snap_type_selector, false, false);
2895 snap_box.pack_start (edit_point_selector, false, false);
2899 HBox *nudge_box = manage (new HBox);
2900 nudge_box->set_spacing (2);
2901 nudge_box->set_border_width (2);
2903 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
2904 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
2906 nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2907 nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2909 nudge_box->pack_start (nudge_backward_button, false, false);
2910 nudge_box->pack_start (nudge_forward_button, false, false);
2911 nudge_box->pack_start (*nudge_clock, false, false);
2914 /* Pack everything in... */
2916 HBox* hbox = manage (new HBox);
2917 hbox->set_spacing(10);
2919 _tools_tearoff = manage (new TearOff (*hbox));
2920 _tools_tearoff->set_name ("MouseModeBase");
2921 _tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
2923 if (Profile->get_sae()) {
2924 _tools_tearoff->set_can_be_torn_off (false);
2927 _tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2928 &_tools_tearoff->tearoff_window()));
2929 _tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2930 &_tools_tearoff->tearoff_window(), 0));
2931 _tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2932 &_tools_tearoff->tearoff_window()));
2933 _tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2934 &_tools_tearoff->tearoff_window(), 0));
2936 toolbar_hbox.set_spacing (10);
2937 toolbar_hbox.set_border_width (1);
2939 toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
2940 if (!ARDOUR::Profile->get_trx()) {
2941 toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
2942 toolbar_hbox.pack_start (*_tools_tearoff, false, false);
2945 if (!ARDOUR::Profile->get_trx()) {
2946 hbox->pack_start (snap_box, false, false);
2947 if (!Profile->get_small_screen()) {
2948 hbox->pack_start (*nudge_box, false, false);
2950 ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
2953 hbox->pack_start (panic_box, false, false);
2957 toolbar_base.set_name ("ToolBarBase");
2958 toolbar_base.add (toolbar_hbox);
2960 _toolbar_viewport.add (toolbar_base);
2961 /* stick to the required height but allow width to vary if there's not enough room */
2962 _toolbar_viewport.set_size_request (1, -1);
2964 toolbar_frame.set_shadow_type (SHADOW_OUT);
2965 toolbar_frame.set_name ("BaseFrame");
2966 toolbar_frame.add (_toolbar_viewport);
2970 Editor::build_edit_point_menu ()
2972 using namespace Menu_Helpers;
2974 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
2975 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
2976 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
2980 Editor::build_edit_mode_menu ()
2982 using namespace Menu_Helpers;
2984 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Slide), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
2985 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Splice), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
2986 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_to_string(Lock), sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
2990 Editor::build_snap_mode_menu ()
2992 using namespace Menu_Helpers;
2994 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapOff], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapOff)));
2995 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapNormal], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapNormal)));
2996 snap_mode_selector.AddMenuElem (MenuElem ( snap_mode_strings[(int)SnapMagnetic], sigc::bind (sigc::mem_fun(*this, &Editor::snap_mode_selection_done), (SnapMode) SnapMagnetic)));
3000 Editor::build_snap_type_menu ()
3002 using namespace Menu_Helpers;
3004 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToCDFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToCDFrame)));
3005 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeFrame], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeFrame)));
3006 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeSeconds)));
3007 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToTimecodeMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToTimecodeMinutes)));
3008 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToSeconds], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToSeconds)));
3009 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMinutes], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMinutes)));
3010 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv128], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv128)));
3011 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv64], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv64)));
3012 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv32)));
3013 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv28)));
3014 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv24)));
3015 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv20)));
3016 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv16)));
3017 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv14)));
3018 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv12)));
3019 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv10)));
3020 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv8)));
3021 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv7)));
3022 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv6)));
3023 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv5)));
3024 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv4)));
3025 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv3)));
3026 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeatDiv2)));
3027 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBeat], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBeat)));
3028 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToBar], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToBar)));
3029 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToMark], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToMark)));
3030 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionStart], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionStart)));
3031 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionEnd], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionEnd)));
3032 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionSync], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionSync)));
3033 snap_type_selector.AddMenuElem (MenuElem ( snap_type_strings[(int)SnapToRegionBoundary], sigc::bind (sigc::mem_fun(*this, &Editor::snap_type_selection_done), (SnapType) SnapToRegionBoundary)));
3037 Editor::setup_tooltips ()
3039 ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3040 ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3041 ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3042 ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3043 ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3044 ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3045 ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3046 ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3047 ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3048 ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3049 ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3050 ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3051 ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3052 ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3053 ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3054 ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3055 ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3056 ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3057 ARDOUR_UI::instance()->set_tip (visible_tracks_selector, _("Number of visible tracks"));
3058 ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3059 ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3060 ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3061 ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3062 ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3066 Editor::convert_drop_to_paths (
3067 vector<string>& paths,
3068 const RefPtr<Gdk::DragContext>& /*context*/,
3071 const SelectionData& data,
3075 if (_session == 0) {
3079 vector<string> uris = data.get_uris();
3083 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3084 are actually URI lists. So do it by hand.
3087 if (data.get_target() != "text/plain") {
3091 /* Parse the "uri-list" format that Nautilus provides,
3092 where each pathname is delimited by \r\n.
3094 THERE MAY BE NO NULL TERMINATING CHAR!!!
3097 string txt = data.get_text();
3101 p = (char *) malloc (txt.length() + 1);
3102 txt.copy (p, txt.length(), 0);
3103 p[txt.length()] = '\0';
3109 while (g_ascii_isspace (*p))
3113 while (*q && (*q != '\n') && (*q != '\r')) {
3120 while (q > p && g_ascii_isspace (*q))
3125 uris.push_back (string (p, q - p + 1));
3129 p = strchr (p, '\n');
3141 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3142 if ((*i).substr (0,7) == "file://") {
3143 paths.push_back (Glib::filename_from_uri (*i));
3151 Editor::new_tempo_section ()
3156 Editor::map_transport_state ()
3158 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3160 if (_session && _session->transport_stopped()) {
3161 have_pending_keyboard_selection = false;
3164 update_loop_range_view ();
3170 Editor::begin_reversible_command (string name)
3173 _session->begin_reversible_command (name);
3178 Editor::begin_reversible_command (GQuark q)
3181 _session->begin_reversible_command (q);
3186 Editor::commit_reversible_command ()
3189 _session->commit_reversible_command ();
3194 Editor::history_changed ()
3198 if (undo_action && _session) {
3199 if (_session->undo_depth() == 0) {
3200 label = S_("Command|Undo");
3202 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3204 undo_action->property_label() = label;
3207 if (redo_action && _session) {
3208 if (_session->redo_depth() == 0) {
3211 label = string_compose(_("Redo (%1)"), _session->next_redo());
3213 redo_action->property_label() = label;
3218 Editor::duplicate_range (bool with_dialog)
3222 RegionSelection rs = get_regions_from_selection_and_entered ();
3224 if ( selection->time.length() == 0 && rs.empty()) {
3230 ArdourDialog win (_("Duplicate"));
3231 Label label (_("Number of duplications:"));
3232 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3233 SpinButton spinner (adjustment, 0.0, 1);
3236 win.get_vbox()->set_spacing (12);
3237 win.get_vbox()->pack_start (hbox);
3238 hbox.set_border_width (6);
3239 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3241 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3242 place, visually. so do this by hand.
3245 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3246 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3247 spinner.grab_focus();
3253 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3254 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3255 win.set_default_response (RESPONSE_ACCEPT);
3257 spinner.grab_focus ();
3259 switch (win.run ()) {
3260 case RESPONSE_ACCEPT:
3266 times = adjustment.get_value();
3269 if ((current_mouse_mode() == Editing::MouseRange)) {
3270 if (selection->time.length()) {
3271 duplicate_selection (times);
3273 } else if (get_smart_mode()) {
3274 if (selection->time.length()) {
3275 duplicate_selection (times);
3277 duplicate_some_regions (rs, times);
3279 duplicate_some_regions (rs, times);
3284 Editor::set_edit_mode (EditMode m)
3286 Config->set_edit_mode (m);
3290 Editor::cycle_edit_mode ()
3292 switch (Config->get_edit_mode()) {
3294 if (Profile->get_sae()) {
3295 Config->set_edit_mode (Lock);
3297 Config->set_edit_mode (Splice);
3301 Config->set_edit_mode (Lock);
3304 Config->set_edit_mode (Slide);
3310 Editor::edit_mode_selection_done ( EditMode m )
3312 Config->set_edit_mode ( m );
3316 Editor::snap_type_selection_done (SnapType snaptype)
3318 RefPtr<RadioAction> ract = snap_type_action (snaptype);
3320 ract->set_active ();
3325 Editor::snap_mode_selection_done (SnapMode mode)
3327 RefPtr<RadioAction> ract = snap_mode_action (mode);
3330 ract->set_active (true);
3335 Editor::cycle_edit_point (bool with_marker)
3337 switch (_edit_point) {
3339 set_edit_point_preference (EditAtPlayhead);
3341 case EditAtPlayhead:
3343 set_edit_point_preference (EditAtSelectedMarker);
3345 set_edit_point_preference (EditAtMouse);
3348 case EditAtSelectedMarker:
3349 set_edit_point_preference (EditAtMouse);
3355 Editor::edit_point_selection_done (EditPoint ep)
3357 set_edit_point_preference ( ep );
3361 Editor::build_zoom_focus_menu ()
3363 using namespace Menu_Helpers;
3365 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3366 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3367 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3368 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3369 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3370 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3374 Editor::zoom_focus_selection_done ( ZoomFocus f )
3376 RefPtr<RadioAction> ract = zoom_focus_action (f);
3378 ract->set_active ();
3383 Editor::build_track_count_menu ()
3385 using namespace Menu_Helpers;
3387 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3388 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3389 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3390 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3391 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3392 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3393 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3394 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3395 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3396 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3397 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3398 visible_tracks_selector.AddMenuElem (MenuElem (_("all"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3402 Editor::set_visible_track_count (int32_t n)
3404 _visible_track_count = n;
3406 /* if the canvas hasn't really been allocated any size yet, just
3407 record the desired number of visible tracks and return. when canvas
3408 allocation happens, we will get called again and then we can do the
3412 if (_visible_canvas_height <= 1) {
3419 if (_visible_track_count > 0) {
3420 h = _visible_canvas_height / _visible_track_count;
3421 std::ostringstream s;
3422 s << _visible_track_count;
3424 } else if (_visible_track_count == 0) {
3425 h = _visible_canvas_height / track_views.size();
3428 /* negative value means that the visible track count has
3429 been overridden by explicit track height changes.
3431 visible_tracks_selector.set_text (X_("*"));
3435 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3436 (*i)->set_height (h);
3439 if (str != visible_tracks_selector.get_text()) {
3440 visible_tracks_selector.set_text (str);
3445 Editor::override_visible_track_count ()
3447 _visible_track_count = -_visible_track_count;
3451 Editor::edit_controls_button_release (GdkEventButton* ev)
3453 if (Keyboard::is_context_menu_event (ev)) {
3454 ARDOUR_UI::instance()->add_route (this);
3455 } else if (ev->button == 1) {
3456 selection->clear_tracks ();
3463 Editor::mouse_select_button_release (GdkEventButton* ev)
3465 /* this handles just right-clicks */
3467 if (ev->button != 3) {
3475 Editor::set_zoom_focus (ZoomFocus f)
3477 string str = zoom_focus_strings[(int)f];
3479 if (str != zoom_focus_selector.get_text()) {
3480 zoom_focus_selector.set_text (str);
3483 if (zoom_focus != f) {
3490 Editor::cycle_zoom_focus ()
3492 switch (zoom_focus) {
3494 set_zoom_focus (ZoomFocusRight);
3496 case ZoomFocusRight:
3497 set_zoom_focus (ZoomFocusCenter);
3499 case ZoomFocusCenter:
3500 set_zoom_focus (ZoomFocusPlayhead);
3502 case ZoomFocusPlayhead:
3503 set_zoom_focus (ZoomFocusMouse);
3505 case ZoomFocusMouse:
3506 set_zoom_focus (ZoomFocusEdit);
3509 set_zoom_focus (ZoomFocusLeft);
3515 Editor::ensure_float (Window& win)
3517 win.set_transient_for (*this);
3521 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3523 /* recover or initialize pane positions. do this here rather than earlier because
3524 we don't want the positions to change the child allocations, which they seem to do.
3530 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3539 XMLNode* geometry = find_named_node (*node, "geometry");
3541 if (which == static_cast<Paned*> (&edit_pane)) {
3543 if (done & Horizontal) {
3547 if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3548 _notebook_shrunk = string_is_affirmative (prop->value ());
3551 if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3552 /* initial allocation is 90% to canvas, 10% to notebook */
3553 pos = (int) floor (alloc.get_width() * 0.90f);
3554 snprintf (buf, sizeof(buf), "%d", pos);
3556 pos = atoi (prop->value());
3559 if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3560 edit_pane.set_position (pos);
3563 done = (Pane) (done | Horizontal);
3565 } else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3567 if (done & Vertical) {
3571 if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3572 /* initial allocation is 90% to canvas, 10% to summary */
3573 pos = (int) floor (alloc.get_height() * 0.90f);
3574 snprintf (buf, sizeof(buf), "%d", pos);
3577 pos = atoi (prop->value());
3580 if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3581 editor_summary_pane.set_position (pos);
3584 done = (Pane) (done | Vertical);
3589 Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3591 if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3592 (_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3593 (_zoom_tearoff && (_zoom_tearoff->torn_off() || !_zoom_tearoff->visible()))) {
3594 top_hbox.remove (toolbar_frame);
3599 Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3601 if (toolbar_frame.get_parent() == 0) {
3602 top_hbox.pack_end (toolbar_frame);
3607 Editor::set_show_measures (bool yn)
3609 if (_show_measures != yn) {
3612 if ((_show_measures = yn) == true) {
3614 tempo_lines->show();
3617 ARDOUR::TempoMap::BBTPointList::const_iterator begin;
3618 ARDOUR::TempoMap::BBTPointList::const_iterator end;
3620 compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_samples(), begin, end);
3621 draw_measures (begin, end);
3629 Editor::toggle_follow_playhead ()
3631 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3633 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3634 set_follow_playhead (tact->get_active());
3638 /** @param yn true to follow playhead, otherwise false.
3639 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3642 Editor::set_follow_playhead (bool yn, bool catch_up)
3644 if (_follow_playhead != yn) {
3645 if ((_follow_playhead = yn) == true && catch_up) {
3647 reset_x_origin_to_follow_playhead ();
3654 Editor::toggle_stationary_playhead ()
3656 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3658 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3659 set_stationary_playhead (tact->get_active());
3664 Editor::set_stationary_playhead (bool yn)
3666 if (_stationary_playhead != yn) {
3667 if ((_stationary_playhead = yn) == true) {
3669 // FIXME need a 3.0 equivalent of this 2.X call
3670 // update_current_screen ();
3677 Editor::playlist_selector () const
3679 return *_playlist_selector;
3683 Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3687 switch (_snap_type) {
3692 case SnapToBeatDiv128:
3695 case SnapToBeatDiv64:
3698 case SnapToBeatDiv32:
3701 case SnapToBeatDiv28:
3704 case SnapToBeatDiv24:
3707 case SnapToBeatDiv20:
3710 case SnapToBeatDiv16:
3713 case SnapToBeatDiv14:
3716 case SnapToBeatDiv12:
3719 case SnapToBeatDiv10:
3722 case SnapToBeatDiv8:
3725 case SnapToBeatDiv7:
3728 case SnapToBeatDiv6:
3731 case SnapToBeatDiv5:
3734 case SnapToBeatDiv4:
3737 case SnapToBeatDiv3:
3740 case SnapToBeatDiv2:
3746 return _session->tempo_map().meter_at (position).divisions_per_bar();
3751 case SnapToTimecodeFrame:
3752 case SnapToTimecodeSeconds:
3753 case SnapToTimecodeMinutes:
3756 case SnapToRegionStart:
3757 case SnapToRegionEnd:
3758 case SnapToRegionSync:
3759 case SnapToRegionBoundary:
3769 Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3773 ret = nudge_clock->current_duration (pos);
3774 next = ret + 1; /* XXXX fix me */
3780 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3782 ArdourDialog dialog (_("Playlist Deletion"));
3783 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3784 "If it is kept, its audio files will not be cleaned.\n"
3785 "If it is deleted, audio files used by it alone will be cleaned."),
3788 dialog.set_position (WIN_POS_CENTER);
3789 dialog.get_vbox()->pack_start (label);
3793 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3794 dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3795 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3797 switch (dialog.run ()) {
3798 case RESPONSE_ACCEPT:
3799 /* delete the playlist */
3803 case RESPONSE_REJECT:
3804 /* keep the playlist */
3816 Editor::audio_region_selection_covers (framepos_t where)
3818 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3819 if ((*a)->region()->covers (where)) {
3828 Editor::prepare_for_cleanup ()
3830 cut_buffer->clear_regions ();
3831 cut_buffer->clear_playlists ();
3833 selection->clear_regions ();
3834 selection->clear_playlists ();
3836 _regions->suspend_redisplay ();
3840 Editor::finish_cleanup ()
3842 _regions->resume_redisplay ();
3846 Editor::transport_loop_location()
3849 return _session->locations()->auto_loop_location();
3856 Editor::transport_punch_location()
3859 return _session->locations()->auto_punch_location();
3866 Editor::control_layout_scroll (GdkEventScroll* ev)
3868 /* Just forward to the normal canvas scroll method. The coordinate
3869 systems are different but since the canvas is always larger than the
3870 track headers, and aligned with the trackview area, this will work.
3872 In the not too distant future this layout is going away anyway and
3873 headers will be on the canvas.
3875 return canvas_scroll_event (ev, false);
3879 Editor::session_state_saved (string)
3882 _snapshots->redisplay ();
3886 Editor::update_tearoff_visibility()
3888 bool visible = Config->get_keep_tearoffs();
3889 _mouse_mode_tearoff->set_visible (visible);
3890 _tools_tearoff->set_visible (visible);
3891 if (_zoom_tearoff) {
3892 _zoom_tearoff->set_visible (visible);
3897 Editor::maximise_editing_space ()
3909 Editor::restore_editing_space ()
3921 * Make new playlists for a given track and also any others that belong
3922 * to the same active route group with the `select' property.
3927 Editor::new_playlists (TimeAxisView* v)
3929 begin_reversible_command (_("new playlists"));
3930 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3931 _session->playlists->get (playlists);
3932 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
3933 commit_reversible_command ();
3937 * Use a copy of the current playlist for a given track and also any others that belong
3938 * to the same active route group with the `select' property.
3943 Editor::copy_playlists (TimeAxisView* v)
3945 begin_reversible_command (_("copy playlists"));
3946 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3947 _session->playlists->get (playlists);
3948 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
3949 commit_reversible_command ();
3952 /** Clear the current playlist for a given track and also any others that belong
3953 * to the same active route group with the `select' property.
3958 Editor::clear_playlists (TimeAxisView* v)
3960 begin_reversible_command (_("clear playlists"));
3961 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
3962 _session->playlists->get (playlists);
3963 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
3964 commit_reversible_command ();
3968 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
3970 atv.use_new_playlist (sz > 1 ? false : true, playlists);
3974 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
3976 atv.use_copy_playlist (sz > 1 ? false : true, playlists);
3980 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
3982 atv.clear_playlist ();
3986 Editor::on_key_press_event (GdkEventKey* ev)
3988 return key_press_focus_accelerator_handler (*this, ev);
3992 Editor::on_key_release_event (GdkEventKey* ev)
3994 return Gtk::Window::on_key_release_event (ev);
3995 // return key_press_focus_accelerator_handler (*this, ev);
3998 /** Queue up a change to the viewport x origin.
3999 * @param frame New x origin.
4002 Editor::reset_x_origin (framepos_t frame)
4004 pending_visual_change.add (VisualChange::TimeOrigin);
4005 pending_visual_change.time_origin = frame;
4006 ensure_visual_change_idle_handler ();
4010 Editor::reset_y_origin (double y)
4012 pending_visual_change.add (VisualChange::YOrigin);
4013 pending_visual_change.y_origin = y;
4014 ensure_visual_change_idle_handler ();
4018 Editor::reset_zoom (framecnt_t spp)
4020 clamp_samples_per_pixel (spp);
4022 if (spp == samples_per_pixel) {
4026 pending_visual_change.add (VisualChange::ZoomLevel);
4027 pending_visual_change.samples_per_pixel = spp;
4028 ensure_visual_change_idle_handler ();
4032 Editor::reposition_and_zoom (framepos_t frame, double fpu)
4034 reset_x_origin (frame);
4037 if (!no_save_visual) {
4038 undo_visual_stack.push_back (current_visual_state(false));
4042 Editor::VisualState::VisualState (bool with_tracks)
4043 : gui_state (with_tracks ? new GUIObjectState : 0)
4047 Editor::VisualState::~VisualState ()
4052 Editor::VisualState*
4053 Editor::current_visual_state (bool with_tracks)
4055 VisualState* vs = new VisualState (with_tracks);
4056 vs->y_position = vertical_adjustment.get_value();
4057 vs->samples_per_pixel = samples_per_pixel;
4058 vs->leftmost_frame = leftmost_frame;
4059 vs->zoom_focus = zoom_focus;
4062 *vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4069 Editor::undo_visual_state ()
4071 if (undo_visual_stack.empty()) {
4075 VisualState* vs = undo_visual_stack.back();
4076 undo_visual_stack.pop_back();
4079 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4081 use_visual_state (*vs);
4085 Editor::redo_visual_state ()
4087 if (redo_visual_stack.empty()) {
4091 VisualState* vs = redo_visual_stack.back();
4092 redo_visual_stack.pop_back();
4094 undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4096 use_visual_state (*vs);
4100 Editor::swap_visual_state ()
4102 if (undo_visual_stack.empty()) {
4103 redo_visual_state ();
4105 undo_visual_state ();
4110 Editor::use_visual_state (VisualState& vs)
4112 PBD::Unwinder<bool> nsv (no_save_visual, true);
4114 _routes->suspend_redisplay ();
4116 vertical_adjustment.set_value (vs.y_position);
4118 set_zoom_focus (vs.zoom_focus);
4119 reposition_and_zoom (vs.leftmost_frame, vs.samples_per_pixel);
4122 *ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4124 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4125 (*i)->reset_visual_state ();
4129 _routes->update_visibility ();
4130 _routes->resume_redisplay ();
4133 /** This is the core function that controls the zoom level of the canvas. It is called
4134 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4135 * @param fpu New frames per unit; should already have been clamped so that it is sensible.
4138 Editor::set_samples_per_pixel (framecnt_t spp)
4140 clamp_samples_per_pixel (spp);
4141 samples_per_pixel = spp;
4144 tempo_lines->tempo_map_changed();
4147 /* convert fpu to frame count */
4149 framepos_t frames = samples_per_pixel * _visible_canvas_width;
4151 if (samples_per_pixel != zoom_range_clock->current_duration()) {
4152 zoom_range_clock->set (frames);
4155 bool const showing_time_selection = selection->time.length() > 0;
4157 if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4158 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4159 (*i)->reshow_selection (selection->time);
4163 ZoomChanged (); /* EMIT_SIGNAL */
4165 ArdourCanvas::GtkCanvasViewport* c;
4167 c = get_track_canvas();
4169 c->canvas()->zoomed ();
4172 if (playhead_cursor) {
4173 playhead_cursor->set_position (playhead_cursor->current_frame ());
4176 refresh_location_display();
4177 _summary->set_overlays_dirty ();
4179 update_marker_labels ();
4185 Editor::queue_visual_videotimeline_update ()
4188 * pending_visual_change.add (VisualChange::VideoTimeline);
4189 * or maybe even more specific: which videotimeline-image
4190 * currently it calls update_video_timeline() to update
4191 * _all outdated_ images on the video-timeline.
4192 * see 'exposeimg()' in video_image_frame.cc
4194 ensure_visual_change_idle_handler ();
4198 Editor::ensure_visual_change_idle_handler ()
4200 if (pending_visual_change.idle_handler_id < 0) {
4201 pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4202 pending_visual_change.being_handled = false;
4207 Editor::_idle_visual_changer (void* arg)
4209 return static_cast<Editor*>(arg)->idle_visual_changer ();
4213 Editor::idle_visual_changer ()
4215 /* set_horizontal_position() below (and maybe other calls) call
4216 gtk_main_iteration(), so it's possible that a signal will be handled
4217 half-way through this method. If this signal wants an
4218 idle_visual_changer we must schedule another one after this one, so
4219 mark the idle_handler_id as -1 here to allow that. Also make a note
4220 that we are doing the visual change, so that changes in response to
4221 super-rapid-screen-update can be dropped if we are still processing
4225 pending_visual_change.idle_handler_id = -1;
4226 pending_visual_change.being_handled = true;
4228 VisualChange vc = pending_visual_change;
4230 pending_visual_change.pending = (VisualChange::Type) 0;
4232 visual_changer (vc);
4234 pending_visual_change.being_handled = false;
4236 return 0; /* this is always a one-shot call */
4240 Editor::visual_changer (const VisualChange& vc)
4242 double const last_time_origin = horizontal_position ();
4244 if (vc.pending & VisualChange::ZoomLevel) {
4245 set_samples_per_pixel (vc.samples_per_pixel);
4247 compute_fixed_ruler_scale ();
4249 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4250 ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4252 compute_current_bbt_points (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4253 current_bbt_points_begin, current_bbt_points_end);
4254 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples(),
4255 current_bbt_points_begin, current_bbt_points_end);
4256 update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4258 update_video_timeline();
4261 if (vc.pending & VisualChange::TimeOrigin) {
4262 set_horizontal_position (vc.time_origin / samples_per_pixel);
4265 if (vc.pending & VisualChange::YOrigin) {
4266 vertical_adjustment.set_value (vc.y_origin);
4269 if (last_time_origin == horizontal_position ()) {
4270 /* changed signal not emitted */
4271 update_fixed_rulers ();
4272 redisplay_tempo (true);
4275 if (!(vc.pending & VisualChange::ZoomLevel)) {
4276 update_video_timeline();
4279 _summary->set_overlays_dirty ();
4282 struct EditorOrderTimeAxisSorter {
4283 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4284 return a->order () < b->order ();
4289 Editor::sort_track_selection (TrackViewList& sel)
4291 EditorOrderTimeAxisSorter cmp;
4296 Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4299 framepos_t where = 0;
4300 EditPoint ep = _edit_point;
4302 if (from_context_menu && (ep == EditAtMouse)) {
4303 return canvas_event_sample (&context_click_event, 0, 0);
4306 if (entered_marker) {
4307 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4308 return entered_marker->position();
4311 if (ignore_playhead && ep == EditAtPlayhead) {
4312 ep = EditAtSelectedMarker;
4316 case EditAtPlayhead:
4317 where = _session->audible_frame();
4318 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4321 case EditAtSelectedMarker:
4322 if (!selection->markers.empty()) {
4324 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4327 where = loc->start();
4331 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4339 if (!mouse_frame (where, ignored)) {
4340 /* XXX not right but what can we do ? */
4344 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4352 Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4354 if (!_session) return;
4356 begin_reversible_command (cmd);
4360 if ((tll = transport_loop_location()) == 0) {
4361 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4362 XMLNode &before = _session->locations()->get_state();
4363 _session->locations()->add (loc, true);
4364 _session->set_auto_loop_location (loc);
4365 XMLNode &after = _session->locations()->get_state();
4366 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4368 XMLNode &before = tll->get_state();
4369 tll->set_hidden (false, this);
4370 tll->set (start, end);
4371 XMLNode &after = tll->get_state();
4372 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4375 commit_reversible_command ();
4379 Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4381 if (!_session) return;
4383 begin_reversible_command (cmd);
4387 if ((tpl = transport_punch_location()) == 0) {
4388 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4389 XMLNode &before = _session->locations()->get_state();
4390 _session->locations()->add (loc, true);
4391 _session->set_auto_punch_location (loc);
4392 XMLNode &after = _session->locations()->get_state();
4393 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4396 XMLNode &before = tpl->get_state();
4397 tpl->set_hidden (false, this);
4398 tpl->set (start, end);
4399 XMLNode &after = tpl->get_state();
4400 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4403 commit_reversible_command ();
4406 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4407 * @param rs List to which found regions are added.
4408 * @param where Time to look at.
4409 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4412 Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4414 const TrackViewList* tracks;
4417 tracks = &track_views;
4422 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4424 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4427 boost::shared_ptr<Track> tr;
4428 boost::shared_ptr<Playlist> pl;
4430 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4432 boost::shared_ptr<RegionList> regions = pl->regions_at (
4433 (framepos_t) floor ( (double) where * tr->speed()));
4435 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4436 RegionView* rv = rtv->view()->find_view (*i);
4447 Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4449 const TrackViewList* tracks;
4452 tracks = &track_views;
4457 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4458 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4460 boost::shared_ptr<Track> tr;
4461 boost::shared_ptr<Playlist> pl;
4463 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4465 boost::shared_ptr<RegionList> regions = pl->regions_touched (
4466 (framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4468 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4470 RegionView* rv = rtv->view()->find_view (*i);
4481 /** Get regions using the following method:
4483 * Make a region list using the selected regions, unless
4484 * the edit point is `mouse' and the mouse is over an unselected
4485 * region. In this case, use just that region.
4487 * If the edit point is not 'mouse', and there are no regions selected,
4488 * search the list of selected tracks and return regions that are under
4489 * the edit point on these tracks. If there are no selected tracks and
4490 * 'No Selection = All Tracks' is active, search all tracks,
4492 * The rationale here is that the mouse edit point is special in that
4493 * its position describes both a time and a track; the other edit
4494 * modes only describe a time. Hence if the edit point is `mouse' we
4495 * ignore selected tracks, as we assume the user means something by
4496 * pointing at a particular track. Also in this case we take note of
4497 * the region directly under the edit point, as there is always just one
4498 * (rather than possibly several with non-mouse edit points).
4502 Editor::get_regions_from_selection_and_edit_point ()
4504 RegionSelection regions;
4506 if (_edit_point == EditAtMouse && entered_regionview && !selection->regions.contains (entered_regionview)) {
4507 regions.add (entered_regionview);
4509 regions = selection->regions;
4513 if (regions.empty() && _edit_point != EditAtMouse) {
4514 TrackViewList tracks = selection->tracks;
4516 if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
4517 /* tracks is empty (no track selected), and 'No Selection = All Tracks'
4518 * is enabled, so consider all tracks
4520 tracks = track_views;
4523 if (!tracks.empty()) {
4524 /* no region selected or entered, but some selected tracks:
4525 * act on all regions on the selected tracks at the edit point
4527 framepos_t const where = get_preferred_edit_position ();
4528 get_regions_at(regions, where, tracks);
4534 /** Start with regions that are selected, or the entered regionview if none are selected.
4535 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4536 * of the regions that we started with.
4540 Editor::get_regions_from_selection_and_entered ()
4542 RegionSelection regions = selection->regions;
4544 if (regions.empty() && entered_regionview) {
4545 regions.add (entered_regionview);
4552 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4554 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4556 RouteTimeAxisView* tatv;
4558 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4560 boost::shared_ptr<Playlist> pl;
4561 vector<boost::shared_ptr<Region> > results;
4563 boost::shared_ptr<Track> tr;
4565 if ((tr = tatv->track()) == 0) {
4570 if ((pl = (tr->playlist())) != 0) {
4571 if (src_comparison) {
4572 pl->get_source_equivalent_regions (region, results);
4574 pl->get_region_list_equivalent_regions (region, results);
4578 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4579 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4580 regions.push_back (marv);
4589 Editor::show_rhythm_ferret ()
4591 if (rhythm_ferret == 0) {
4592 rhythm_ferret = new RhythmFerret(*this);
4595 rhythm_ferret->set_session (_session);
4596 rhythm_ferret->show ();
4597 rhythm_ferret->present ();
4601 Editor::first_idle ()
4603 MessageDialog* dialog = 0;
4605 if (track_views.size() > 1) {
4606 dialog = new MessageDialog (
4608 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4612 ARDOUR_UI::instance()->flush_pending ();
4615 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4619 // first idle adds route children (automation tracks), so we need to redisplay here
4620 _routes->redisplay ();
4627 Editor::_idle_resize (gpointer arg)
4629 return ((Editor*)arg)->idle_resize ();
4633 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4635 if (resize_idle_id < 0) {
4636 resize_idle_id = g_idle_add (_idle_resize, this);
4637 _pending_resize_amount = 0;
4640 /* make a note of the smallest resulting height, so that we can clamp the
4641 lower limit at TimeAxisView::hSmall */
4643 int32_t min_resulting = INT32_MAX;
4645 _pending_resize_amount += h;
4646 _pending_resize_view = view;
4648 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4650 if (selection->tracks.contains (_pending_resize_view)) {
4651 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4652 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4656 if (min_resulting < 0) {
4661 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4662 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4666 /** Handle pending resizing of tracks */
4668 Editor::idle_resize ()
4670 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4672 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4673 selection->tracks.contains (_pending_resize_view)) {
4675 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4676 if (*i != _pending_resize_view) {
4677 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4682 _pending_resize_amount = 0;
4683 _group_tabs->set_dirty ();
4684 resize_idle_id = -1;
4692 ENSURE_GUI_THREAD (*this, &Editor::located);
4695 playhead_cursor->set_position (_session->audible_frame ());
4696 if (_follow_playhead && !_pending_initial_locate) {
4697 reset_x_origin_to_follow_playhead ();
4701 _pending_locate_request = false;
4702 _pending_initial_locate = false;
4706 Editor::region_view_added (RegionView *)
4708 _summary->set_background_dirty ();
4712 Editor::region_view_removed ()
4714 _summary->set_background_dirty ();
4718 Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4720 TrackViewList::const_iterator j = track_views.begin ();
4721 while (j != track_views.end()) {
4722 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4723 if (rtv && rtv->route() == r) {
4734 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4738 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4739 TimeAxisView* tv = axis_view_from_route (*i);
4749 Editor::add_routes (RouteList& routes)
4751 ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4753 RouteTimeAxisView *rtv;
4754 list<RouteTimeAxisView*> new_views;
4756 for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4757 boost::shared_ptr<Route> route = (*x);
4759 if (route->is_auditioner() || route->is_monitor()) {
4763 DataType dt = route->input()->default_type();
4765 if (dt == ARDOUR::DataType::AUDIO) {
4766 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
4767 rtv->set_route (route);
4768 } else if (dt == ARDOUR::DataType::MIDI) {
4769 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
4770 rtv->set_route (route);
4772 throw unknown_type();
4775 new_views.push_back (rtv);
4776 track_views.push_back (rtv);
4778 rtv->effective_gain_display ();
4780 if (internal_editing()) {
4781 rtv->enter_internal_edit_mode ();
4783 rtv->leave_internal_edit_mode ();
4786 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4787 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4790 if (new_views.size() > 0) {
4791 _routes->routes_added (new_views);
4792 _summary->routes_added (new_views);
4795 if (show_editor_mixer_when_tracks_arrive) {
4796 show_editor_mixer (true);
4799 editor_list_button.set_sensitive (true);
4803 Editor::timeaxisview_deleted (TimeAxisView *tv)
4805 if (_session && _session->deletion_in_progress()) {
4806 /* the situation is under control */
4810 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
4812 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
4814 _routes->route_removed (tv);
4816 if (tv == entered_track) {
4820 TimeAxisView::Children c = tv->get_child_list ();
4821 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
4822 if (entered_track == i->get()) {
4827 /* remove it from the list of track views */
4829 TrackViewList::iterator i;
4831 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
4832 i = track_views.erase (i);
4835 /* update whatever the current mixer strip is displaying, if revelant */
4837 boost::shared_ptr<Route> route;
4840 route = rtav->route ();
4843 if (current_mixer_strip && current_mixer_strip->route() == route) {
4845 TimeAxisView* next_tv;
4847 if (track_views.empty()) {
4849 } else if (i == track_views.end()) {
4850 next_tv = track_views.front();
4857 set_selected_mixer_strip (*next_tv);
4859 /* make the editor mixer strip go away setting the
4860 * button to inactive (which also unticks the menu option)
4863 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
4869 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
4871 if (apply_to_selection) {
4872 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
4874 TrackSelection::iterator j = i;
4877 hide_track_in_display (*i, false);
4882 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
4884 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
4885 // this will hide the mixer strip
4886 set_selected_mixer_strip (*tv);
4889 _routes->hide_track_in_display (*tv);
4894 Editor::sync_track_view_list_and_routes ()
4896 track_views = TrackViewList (_routes->views ());
4898 _summary->set_dirty ();
4899 _group_tabs->set_dirty ();
4901 return false; // do not call again (until needed)
4905 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
4907 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4912 /** Find a RouteTimeAxisView by the ID of its route */
4914 Editor::get_route_view_by_route_id (const PBD::ID& id) const
4916 RouteTimeAxisView* v;
4918 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4919 if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
4920 if(v->route()->id() == id) {
4930 Editor::fit_route_group (RouteGroup *g)
4932 TrackViewList ts = axis_views_from_routes (g->route_list ());
4937 Editor::consider_auditioning (boost::shared_ptr<Region> region)
4939 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
4942 _session->cancel_audition ();
4946 if (_session->is_auditioning()) {
4947 _session->cancel_audition ();
4948 if (r == last_audition_region) {
4953 _session->audition_region (r);
4954 last_audition_region = r;
4959 Editor::hide_a_region (boost::shared_ptr<Region> r)
4961 r->set_hidden (true);
4965 Editor::show_a_region (boost::shared_ptr<Region> r)
4967 r->set_hidden (false);
4971 Editor::audition_region_from_region_list ()
4973 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
4977 Editor::hide_region_from_region_list ()
4979 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
4983 Editor::show_region_in_region_list ()
4985 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
4989 Editor::step_edit_status_change (bool yn)
4992 start_step_editing ();
4994 stop_step_editing ();
4999 Editor::start_step_editing ()
5001 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5005 Editor::stop_step_editing ()
5007 step_edit_connection.disconnect ();
5011 Editor::check_step_edit ()
5013 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5014 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5016 mtv->check_step_edit ();
5020 return true; // do it again, till we stop
5024 Editor::scroll_press (Direction dir)
5026 ++_scroll_callbacks;
5028 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5029 /* delay the first auto-repeat */
5035 scroll_backward (1);
5043 scroll_tracks_up_line ();
5047 scroll_tracks_down_line ();
5051 /* do hacky auto-repeat */
5052 if (!_scroll_connection.connected ()) {
5054 _scroll_connection = Glib::signal_timeout().connect (
5055 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5058 _scroll_callbacks = 0;
5065 Editor::scroll_release ()
5067 _scroll_connection.disconnect ();
5070 /** Queue a change for the Editor viewport x origin to follow the playhead */
5072 Editor::reset_x_origin_to_follow_playhead ()
5074 framepos_t const frame = playhead_cursor->current_frame ();
5076 if (frame < leftmost_frame || frame > leftmost_frame + current_page_samples()) {
5078 if (_session->transport_speed() < 0) {
5080 if (frame > (current_page_samples() / 2)) {
5081 center_screen (frame-(current_page_samples()/2));
5083 center_screen (current_page_samples()/2);
5090 if (frame < leftmost_frame) {
5092 if (_session->transport_rolling()) {
5093 /* rolling; end up with the playhead at the right of the page */
5094 l = frame - current_page_samples ();
5096 /* not rolling: end up with the playhead 1/4 of the way along the page */
5097 l = frame - current_page_samples() / 4;
5101 if (_session->transport_rolling()) {
5102 /* rolling: end up with the playhead on the left of the page */
5105 /* not rolling: end up with the playhead 3/4 of the way along the page */
5106 l = frame - 3 * current_page_samples() / 4;
5114 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5120 Editor::super_rapid_screen_update ()
5122 if (!_session || !_session->engine().running()) {
5126 /* METERING / MIXER STRIPS */
5128 /* update track meters, if required */
5129 if (is_mapped() && meters_running) {
5130 RouteTimeAxisView* rtv;
5131 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5132 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5133 rtv->fast_update ();
5138 /* and any current mixer strip */
5139 if (current_mixer_strip) {
5140 current_mixer_strip->fast_update ();
5143 /* PLAYHEAD AND VIEWPORT */
5145 framepos_t const frame = _session->audible_frame();
5147 /* There are a few reasons why we might not update the playhead / viewport stuff:
5149 * 1. we don't update things when there's a pending locate request, otherwise
5150 * when the editor requests a locate there is a chance that this method
5151 * will move the playhead before the locate request is processed, causing
5153 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5154 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5157 if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5159 last_update_frame = frame;
5161 if (!_dragging_playhead) {
5162 playhead_cursor->set_position (frame);
5165 if (!_stationary_playhead) {
5167 if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5168 /* We only do this if we aren't already
5169 handling a visual change (ie if
5170 pending_visual_change.being_handled is
5171 false) so that these requests don't stack
5172 up there are too many of them to handle in
5175 reset_x_origin_to_follow_playhead ();
5180 /* don't do continuous scroll till the new position is in the rightmost quarter of the
5184 // FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5185 double target = ((double)frame - (double)current_page_samples()/2.0) / samples_per_pixel;
5186 if (target <= 0.0) {
5189 if (fabs(target - current) < current_page_samples() / samples_per_pixel) {
5190 target = (target * 0.15) + (current * 0.85);
5196 set_horizontal_position (current);
5205 Editor::session_going_away ()
5207 _have_idled = false;
5209 _session_connections.drop_connections ();
5211 super_rapid_screen_update_connection.disconnect ();
5213 selection->clear ();
5214 cut_buffer->clear ();
5216 clicked_regionview = 0;
5217 clicked_axisview = 0;
5218 clicked_routeview = 0;
5219 entered_regionview = 0;
5221 last_update_frame = 0;
5224 playhead_cursor->hide ();
5226 /* rip everything out of the list displays */
5230 _route_groups->clear ();
5232 /* do this first so that deleting a track doesn't reset cms to null
5233 and thus cause a leak.
5236 if (current_mixer_strip) {
5237 if (current_mixer_strip->get_parent() != 0) {
5238 global_hpacker.remove (*current_mixer_strip);
5240 delete current_mixer_strip;
5241 current_mixer_strip = 0;
5244 /* delete all trackviews */
5246 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5249 track_views.clear ();
5251 zoom_range_clock->set_session (0);
5252 nudge_clock->set_session (0);
5254 editor_list_button.set_active(false);
5255 editor_list_button.set_sensitive(false);
5257 /* clear tempo/meter rulers */
5258 remove_metric_marks ();
5260 clear_marker_display ();
5262 stop_step_editing ();
5264 /* get rid of any existing editor mixer strip */
5266 WindowTitle title(Glib::get_application_name());
5267 title += _("Editor");
5269 set_title (title.get_string());
5271 SessionHandlePtr::session_going_away ();
5276 Editor::show_editor_list (bool yn)
5279 _the_notebook.show ();
5281 _the_notebook.hide ();
5286 Editor::change_region_layering_order (bool from_context_menu)
5288 const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5290 if (!clicked_routeview) {
5291 if (layering_order_editor) {
5292 layering_order_editor->hide ();
5297 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5303 boost::shared_ptr<Playlist> pl = track->playlist();
5309 if (layering_order_editor == 0) {
5310 layering_order_editor = new RegionLayeringOrderEditor (*this);
5313 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5314 layering_order_editor->maybe_present ();
5318 Editor::update_region_layering_order_editor ()
5320 if (layering_order_editor && layering_order_editor->is_visible ()) {
5321 change_region_layering_order (true);
5326 Editor::setup_fade_images ()
5328 _fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5329 _fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5330 _fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5331 _fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5332 _fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5334 _fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5335 _fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5336 _fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5337 _fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5338 _fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5340 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5341 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5342 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5343 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5344 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5346 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5347 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5348 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5349 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5350 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5354 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5356 Editor::action_menu_item (std::string const & name)
5358 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5361 return *manage (a->create_menu_item ());
5365 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5367 EventBox* b = manage (new EventBox);
5368 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5369 Label* l = manage (new Label (name));
5373 _the_notebook.append_page (widget, *b);
5377 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5379 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5380 _the_notebook.set_current_page (_the_notebook.page_num (*page));
5383 if (ev->type == GDK_2BUTTON_PRESS) {
5385 /* double-click on a notebook tab shrinks or expands the notebook */
5387 if (_notebook_shrunk) {
5388 if (pre_notebook_shrink_pane_width) {
5389 edit_pane.set_position (*pre_notebook_shrink_pane_width);
5391 _notebook_shrunk = false;
5393 pre_notebook_shrink_pane_width = edit_pane.get_position();
5395 /* this expands the LHS of the edit pane to cover the notebook
5396 PAGE but leaves the tabs visible.
5398 edit_pane.set_position (edit_pane.get_position() + page->get_width());
5399 _notebook_shrunk = true;
5407 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5409 using namespace Menu_Helpers;
5411 MenuList& items = _control_point_context_menu.items ();
5414 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5415 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5416 if (!can_remove_control_point (item)) {
5417 items.back().set_sensitive (false);
5420 _control_point_context_menu.popup (event->button.button, event->button.time);
5424 Editor::zoom_vertical_modifier_released()
5426 _stepping_axis_view = 0;
5430 Editor::ui_parameter_changed (string parameter)
5432 if (parameter == "icon-set") {
5433 while (!_cursor_stack.empty()) {
5434 _cursor_stack.pop();
5436 _cursors->set_cursor_set (ARDOUR_UI::config()->get_icon_set());