2 Copyright (C) 2000-2009 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 /* Note: public Editor methods are documented in public_editor.h */
30 #include "ardour_ui.h"
32 * ardour_ui.h include was moved to the top of the list
33 * due to a conflicting definition of 'Style' between
34 * Apple's MacTypes.h and BarController.
37 #include <boost/none.hpp>
39 #include <sigc++/bind.h>
41 #include "pbd/convert.h"
42 #include "pbd/error.h"
43 #include "pbd/enumwriter.h"
44 #include "pbd/memento_command.h"
45 #include "pbd/unknown_type.h"
46 #include "pbd/unwind.h"
47 #include "pbd/stacktrace.h"
48 #include "pbd/timersub.h"
50 #include <glibmm/miscutils.h>
51 #include <glibmm/uriutils.h>
52 #include <gtkmm/image.h>
53 #include <gdkmm/color.h>
54 #include <gdkmm/bitmap.h>
56 #include <gtkmm/menu.h>
57 #include <gtkmm/menuitem.h>
59 #include "gtkmm2ext/bindings.h"
60 #include "gtkmm2ext/gtk_ui.h"
61 #include "gtkmm2ext/keyboard.h"
62 #include "gtkmm2ext/utils.h"
63 #include "gtkmm2ext/window_title.h"
64 #include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
66 #include "ardour/analysis_graph.h"
67 #include "ardour/audio_track.h"
68 #include "ardour/audioengine.h"
69 #include "ardour/audioregion.h"
70 #include "ardour/lmath.h"
71 #include "ardour/location.h"
72 #include "ardour/profile.h"
73 #include "ardour/route.h"
74 #include "ardour/route_group.h"
75 #include "ardour/session_playlists.h"
76 #include "ardour/tempo.h"
77 #include "ardour/utils.h"
78 #include "ardour/vca_manager.h"
79 #include "ardour/vca.h"
81 #include "canvas/debug.h"
82 #include "canvas/text.h"
84 #include "widgets/ardour_spacer.h"
85 #include "widgets/eventboxext.h"
86 #include "widgets/tooltips.h"
88 #include "control_protocol/control_protocol.h"
91 #include "analysis_window.h"
92 #include "audio_clock.h"
93 #include "audio_region_view.h"
94 #include "audio_streamview.h"
95 #include "audio_time_axis.h"
96 #include "automation_time_axis.h"
97 #include "bundle_manager.h"
98 #include "crossfade_edit.h"
101 #include "editing_convert.h"
103 #include "editor_cursors.h"
104 #include "editor_drag.h"
105 #include "editor_group_tabs.h"
106 #include "editor_locations.h"
107 #include "editor_regions.h"
108 #include "editor_route_groups.h"
109 #include "editor_routes.h"
110 #include "editor_snapshots.h"
111 #include "editor_summary.h"
112 #include "enums_convert.h"
113 #include "export_report.h"
114 #include "global_port_matrix.h"
115 #include "gui_object.h"
116 #include "gui_thread.h"
117 #include "keyboard.h"
118 #include "luainstance.h"
120 #include "midi_region_view.h"
121 #include "midi_time_axis.h"
122 #include "mixer_strip.h"
123 #include "mixer_ui.h"
124 #include "mouse_cursors.h"
125 #include "note_base.h"
126 #include "playlist_selector.h"
127 #include "public_editor.h"
128 #include "quantize_dialog.h"
129 #include "region_layering_order_editor.h"
130 #include "rgb_macros.h"
131 #include "rhythm_ferret.h"
132 #include "route_sorter.h"
133 #include "selection.h"
134 #include "simple_progress_dialog.h"
136 #include "grid_lines.h"
137 #include "time_axis_view.h"
138 #include "time_info_box.h"
140 #include "ui_config.h"
142 #include "vca_time_axis.h"
143 #include "verbose_cursor.h"
145 #include "pbd/i18n.h"
148 using namespace ARDOUR;
149 using namespace ArdourWidgets;
150 using namespace ARDOUR_UI_UTILS;
153 using namespace Glib;
154 using namespace Gtkmm2ext;
155 using namespace Editing;
157 using PBD::internationalize;
159 using Gtkmm2ext::Keyboard;
161 double Editor::timebar_height = 15.0;
163 static const gchar *_grid_type_strings[] = {
172 N_("1/3 (8th triplet)"), // or "1/12" ?
173 N_("1/6 (16th triplet)"),
174 N_("1/12 (32nd triplet)"),
175 N_("1/24 (64th triplet)"),
176 N_("1/5 (8th quintuplet)"),
177 N_("1/10 (16th quintuplet)"),
178 N_("1/20 (32nd quintuplet)"),
179 N_("1/7 (8th septuplet)"),
180 N_("1/14 (16th septuplet)"),
181 N_("1/28 (32nd septuplet)"),
188 static const gchar *_edit_point_strings[] = {
195 static const gchar *_edit_mode_strings[] = {
203 static const gchar *_zoom_focus_strings[] = {
213 #ifdef USE_RUBBERBAND
214 static const gchar *_rb_opt_strings[] = {
217 N_("Balanced multitimbral mixture"),
218 N_("Unpitched percussion with stable notes"),
219 N_("Crisp monophonic instrumental"),
220 N_("Unpitched solo percussion"),
221 N_("Resample without preserving pitch"),
226 #define COMBO_TRIANGLE_WIDTH 25 // ArdourButton _diameter (11) + 2 * arrow-padding (2*2) + 2 * text-padding (2*5)
229 : PublicEditor (global_hpacker)
230 , editor_mixer_strip_width (Wide)
231 , constructed (false)
232 , _playlist_selector (0)
234 , no_save_visual (false)
235 , _leftmost_sample (0)
236 , samples_per_pixel (2048)
237 , zoom_focus (ZoomFocusPlayhead)
238 , mouse_mode (MouseObject)
239 , pre_internal_grid_type (GridTypeBeat)
240 , pre_internal_snap_mode (SnapOff)
241 , internal_grid_type (GridTypeBeat)
242 , internal_snap_mode (SnapOff)
243 , _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
244 , _notebook_shrunk (false)
245 , location_marker_color (0)
246 , location_range_color (0)
247 , location_loop_color (0)
248 , location_punch_color (0)
249 , location_cd_marker_color (0)
251 , _show_marker_lines (false)
252 , clicked_axisview (0)
253 , clicked_routeview (0)
254 , clicked_regionview (0)
255 , clicked_selection (0)
256 , clicked_control_point (0)
257 , button_release_can_deselect (true)
258 , _mouse_changed_selection (false)
259 , region_edit_menu_split_item (0)
260 , region_edit_menu_split_multichannel_item (0)
261 , track_region_edit_playlist_menu (0)
262 , track_edit_playlist_submenu (0)
263 , track_selection_edit_playlist_submenu (0)
264 , _popup_region_menu_item (0)
266 , _track_canvas_viewport (0)
267 , within_track_canvas (false)
268 , _verbose_cursor (0)
272 , range_marker_group (0)
273 , transport_marker_group (0)
274 , cd_marker_group (0)
275 , _time_markers_group (0)
276 , hv_scroll_group (0)
278 , cursor_scroll_group (0)
279 , no_scroll_group (0)
280 , _trackview_group (0)
281 , _drag_motion_group (0)
282 , _canvas_drop_zone (0)
283 , no_ruler_shown_update (false)
284 , ruler_grabbed_widget (0)
286 , minsec_mark_interval (0)
287 , minsec_mark_modulo (0)
289 , timecode_ruler_scale (timecode_show_many_hours)
290 , timecode_mark_modulo (0)
291 , timecode_nmarks (0)
292 , _samples_ruler_interval (0)
293 , bbt_ruler_scale (bbt_show_many)
296 , bbt_bar_helper_on (0)
297 , bbt_accent_modulo (0)
302 , visible_timebars (0)
303 , editor_ruler_menu (0)
307 , range_marker_bar (0)
308 , transport_marker_bar (0)
310 , minsec_label (_("Mins:Secs"))
311 , bbt_label (_("Bars:Beats"))
312 , timecode_label (_("Timecode"))
313 , samples_label (_("Samples"))
314 , tempo_label (_("Tempo"))
315 , meter_label (_("Meter"))
316 , mark_label (_("Location Markers"))
317 , range_mark_label (_("Range Markers"))
318 , transport_mark_label (_("Loop/Punch Ranges"))
319 , cd_mark_label (_("CD Markers"))
320 , videotl_label (_("Video Timeline"))
323 , playhead_cursor (0)
324 , _region_boundary_cache_dirty (true)
325 , edit_packer (4, 4, true)
326 , vertical_adjustment (0.0, 0.0, 10.0, 400.0)
327 , horizontal_adjustment (0.0, 0.0, 1e16)
328 , unused_adjustment (0.0, 0.0, 10.0, 400.0)
329 , controls_layout (unused_adjustment, vertical_adjustment)
330 , _scroll_callbacks (0)
331 , _visible_canvas_width (0)
332 , _visible_canvas_height (0)
333 , _full_canvas_height (0)
334 , edit_controls_left_menu (0)
335 , edit_controls_right_menu (0)
336 , visual_change_queued(false)
337 , _last_update_time (0)
338 , _err_screen_engine (0)
339 , cut_buffer_start (0)
340 , cut_buffer_length (0)
341 , button_bindings (0)
342 , last_paste_pos (-1)
345 , current_interthread_info (0)
346 , analysis_window (0)
347 , select_new_marker (false)
349 , scrubbing_direction (0)
350 , scrub_reversals (0)
351 , scrub_reverse_distance (0)
352 , have_pending_keyboard_selection (false)
353 , pending_keyboard_selection_start (0)
354 , _grid_type (GridTypeBeat)
355 , _snap_mode (SnapOff)
356 , ignore_gui_changes (false)
357 , _drags (new DragManager (this))
359 /* , last_event_time { 0, 0 } */ /* this initialization style requires C++11 */
360 , _dragging_playhead (false)
361 , _dragging_edit_point (false)
362 , _follow_playhead (true)
363 , _stationary_playhead (false)
366 , global_rect_group (0)
367 , time_line_group (0)
368 , tempo_marker_menu (0)
369 , meter_marker_menu (0)
371 , range_marker_menu (0)
372 , transport_marker_menu (0)
373 , new_transport_marker_menu (0)
375 , marker_menu_item (0)
376 , bbt_beat_subdivision (4)
377 , _visible_track_count (-1)
378 , toolbar_selection_clock_table (2,3)
379 , automation_mode_button (_("mode"))
380 , selection (new Selection (this, true))
381 , cut_buffer (new Selection (this, false))
382 , _selection_memento (new SelectionMemento())
383 , _all_region_actions_sensitized (false)
384 , _ignore_region_action (false)
385 , _last_region_menu_was_main (false)
386 , _track_selection_change_without_scroll (false)
387 , _editor_track_selection_change_without_scroll (false)
388 , cd_marker_bar_drag_rect (0)
389 , range_bar_drag_rect (0)
390 , transport_bar_drag_rect (0)
391 , transport_bar_range_rect (0)
392 , transport_bar_preroll_rect (0)
393 , transport_bar_postroll_rect (0)
394 , transport_loop_range_rect (0)
395 , transport_punch_range_rect (0)
396 , transport_punchin_line (0)
397 , transport_punchout_line (0)
398 , transport_preroll_rect (0)
399 , transport_postroll_rect (0)
401 , rubberband_rect (0)
407 , autoscroll_horizontal_allowed (false)
408 , autoscroll_vertical_allowed (false)
410 , autoscroll_widget (0)
411 , show_gain_after_trim (false)
412 , selection_op_cmd_depth (0)
413 , selection_op_history_it (0)
414 , no_save_instant (false)
416 , current_mixer_strip (0)
417 , show_editor_mixer_when_tracks_arrive (false)
418 , nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
419 , current_stepping_trackview (0)
420 , last_track_height_step_timestamp (0)
422 , entered_regionview (0)
423 , clear_entered_track (false)
424 , _edit_point (EditAtMouse)
425 , meters_running (false)
427 , _have_idled (false)
428 , resize_idle_id (-1)
429 , _pending_resize_amount (0)
430 , _pending_resize_view (0)
431 , _pending_locate_request (false)
432 , _pending_initial_locate (false)
436 , layering_order_editor (0)
437 , _last_cut_copy_source_track (0)
438 , _region_selection_change_updates_region_list (true)
440 , _following_mixer_selection (false)
441 , _control_point_toggled_on_press (false)
442 , _stepping_axis_view (0)
443 , quantize_dialog (0)
444 , _main_menu_disabler (0)
445 , myactions (X_("editor"))
447 /* we are a singleton */
449 PublicEditor::_instance = this;
453 last_event_time.tv_sec = 0;
454 last_event_time.tv_usec = 0;
456 selection_op_history.clear();
459 grid_type_strings = I18N (_grid_type_strings);
460 zoom_focus_strings = I18N (_zoom_focus_strings);
461 edit_mode_strings = I18N (_edit_mode_strings);
462 edit_point_strings = I18N (_edit_point_strings);
463 #ifdef USE_RUBBERBAND
464 rb_opt_strings = I18N (_rb_opt_strings);
468 build_edit_mode_menu();
469 build_zoom_focus_menu();
470 build_track_count_menu();
471 build_grid_type_menu();
472 build_edit_point_menu();
474 location_marker_color = UIConfiguration::instance().color ("location marker");
475 location_range_color = UIConfiguration::instance().color ("location range");
476 location_cd_marker_color = UIConfiguration::instance().color ("location cd marker");
477 location_loop_color = UIConfiguration::instance().color ("location loop");
478 location_punch_color = UIConfiguration::instance().color ("location punch");
480 timebar_height = std::max (12., ceil (15. * UIConfiguration::instance().get_ui_scale()));
482 TimeAxisView::setup_sizes ();
483 ArdourMarker::setup_sizes (timebar_height);
484 TempoCurve::setup_sizes (timebar_height);
486 bbt_label.set_name ("EditorRulerLabel");
487 bbt_label.set_size_request (-1, (int)timebar_height);
488 bbt_label.set_alignment (1.0, 0.5);
489 bbt_label.set_padding (5,0);
491 bbt_label.set_no_show_all();
492 minsec_label.set_name ("EditorRulerLabel");
493 minsec_label.set_size_request (-1, (int)timebar_height);
494 minsec_label.set_alignment (1.0, 0.5);
495 minsec_label.set_padding (5,0);
496 minsec_label.hide ();
497 minsec_label.set_no_show_all();
498 timecode_label.set_name ("EditorRulerLabel");
499 timecode_label.set_size_request (-1, (int)timebar_height);
500 timecode_label.set_alignment (1.0, 0.5);
501 timecode_label.set_padding (5,0);
502 timecode_label.hide ();
503 timecode_label.set_no_show_all();
504 samples_label.set_name ("EditorRulerLabel");
505 samples_label.set_size_request (-1, (int)timebar_height);
506 samples_label.set_alignment (1.0, 0.5);
507 samples_label.set_padding (5,0);
508 samples_label.hide ();
509 samples_label.set_no_show_all();
511 tempo_label.set_name ("EditorRulerLabel");
512 tempo_label.set_size_request (-1, (int)timebar_height);
513 tempo_label.set_alignment (1.0, 0.5);
514 tempo_label.set_padding (5,0);
516 tempo_label.set_no_show_all();
518 meter_label.set_name ("EditorRulerLabel");
519 meter_label.set_size_request (-1, (int)timebar_height);
520 meter_label.set_alignment (1.0, 0.5);
521 meter_label.set_padding (5,0);
523 meter_label.set_no_show_all();
525 if (Profile->get_trx()) {
526 mark_label.set_text (_("Markers"));
528 mark_label.set_name ("EditorRulerLabel");
529 mark_label.set_size_request (-1, (int)timebar_height);
530 mark_label.set_alignment (1.0, 0.5);
531 mark_label.set_padding (5,0);
533 mark_label.set_no_show_all();
535 cd_mark_label.set_name ("EditorRulerLabel");
536 cd_mark_label.set_size_request (-1, (int)timebar_height);
537 cd_mark_label.set_alignment (1.0, 0.5);
538 cd_mark_label.set_padding (5,0);
539 cd_mark_label.hide();
540 cd_mark_label.set_no_show_all();
542 videotl_bar_height = 4;
543 videotl_label.set_name ("EditorRulerLabel");
544 videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
545 videotl_label.set_alignment (1.0, 0.5);
546 videotl_label.set_padding (5,0);
547 videotl_label.hide();
548 videotl_label.set_no_show_all();
550 range_mark_label.set_name ("EditorRulerLabel");
551 range_mark_label.set_size_request (-1, (int)timebar_height);
552 range_mark_label.set_alignment (1.0, 0.5);
553 range_mark_label.set_padding (5,0);
554 range_mark_label.hide();
555 range_mark_label.set_no_show_all();
557 transport_mark_label.set_name ("EditorRulerLabel");
558 transport_mark_label.set_size_request (-1, (int)timebar_height);
559 transport_mark_label.set_alignment (1.0, 0.5);
560 transport_mark_label.set_padding (5,0);
561 transport_mark_label.hide();
562 transport_mark_label.set_no_show_all();
564 initialize_canvas ();
566 CairoWidget::set_focus_handler (sigc::mem_fun (ARDOUR_UI::instance(), &ARDOUR_UI::reset_focus));
568 _summary = new EditorSummary (this);
570 selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
572 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
574 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
575 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
577 edit_controls_vbox.set_spacing (0);
578 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
579 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
581 HBox* h = manage (new HBox);
582 _group_tabs = new EditorGroupTabs (this);
583 if (!ARDOUR::Profile->get_trx()) {
584 h->pack_start (*_group_tabs, PACK_SHRINK);
586 h->pack_start (edit_controls_vbox);
587 controls_layout.add (*h);
589 controls_layout.set_name ("EditControlsBase");
590 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
591 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
592 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
594 _cursors = new MouseCursors;
595 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
596 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
598 /* Push default cursor to ever-present bottom of cursor stack. */
599 push_canvas_cursor(_cursors->grabber);
601 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
603 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
604 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
605 pad_line_1->set_outline_color (0xFF0000FF);
611 edit_packer.set_col_spacings (0);
612 edit_packer.set_row_spacings (0);
613 edit_packer.set_homogeneous (false);
614 edit_packer.set_border_width (0);
615 edit_packer.set_name ("EditorWindow");
617 time_bars_event_box.add (time_bars_vbox);
618 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
619 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
621 /* labels for the time bars */
622 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
624 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
626 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
628 bottom_hbox.set_border_width (2);
629 bottom_hbox.set_spacing (3);
631 PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&Editor::presentation_info_changed, this, _1), gui_context());
633 _route_groups = new EditorRouteGroups (this);
634 _routes = new EditorRoutes (this);
635 _regions = new EditorRegions (this);
636 _snapshots = new EditorSnapshots (this);
637 _locations = new EditorLocations (this);
638 _time_info_box = new TimeInfoBox ("EditorTimeInfo", true);
640 /* these are static location signals */
642 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
643 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
644 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
646 add_notebook_page (_("Regions"), _regions->widget ());
647 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
648 add_notebook_page (_("Snapshots"), _snapshots->widget ());
649 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
650 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
652 _the_notebook.set_show_tabs (true);
653 _the_notebook.set_scrollable (true);
654 _the_notebook.popup_disable ();
655 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
656 _the_notebook.show_all ();
658 _notebook_shrunk = false;
661 /* Pick up some settings we need to cache, early */
663 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
666 settings->get_property ("notebook-shrunk", _notebook_shrunk);
669 editor_summary_pane.set_check_divider_position (true);
670 editor_summary_pane.add (edit_packer);
672 Button* summary_arrow_left = manage (new Button);
673 summary_arrow_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
674 summary_arrow_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
675 summary_arrow_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
677 Button* summary_arrow_right = manage (new Button);
678 summary_arrow_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
679 summary_arrow_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
680 summary_arrow_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
682 VBox* summary_arrows_left = manage (new VBox);
683 summary_arrows_left->pack_start (*summary_arrow_left);
685 VBox* summary_arrows_right = manage (new VBox);
686 summary_arrows_right->pack_start (*summary_arrow_right);
688 Frame* summary_sample = manage (new Frame);
689 summary_sample->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
691 summary_sample->add (*_summary);
692 summary_sample->show ();
694 _summary_hbox.pack_start (*summary_arrows_left, false, false);
695 _summary_hbox.pack_start (*summary_sample, true, true);
696 _summary_hbox.pack_start (*summary_arrows_right, false, false);
698 if (!ARDOUR::Profile->get_trx()) {
699 editor_summary_pane.add (_summary_hbox);
702 edit_pane.set_check_divider_position (true);
703 edit_pane.add (editor_summary_pane);
704 if (!ARDOUR::Profile->get_trx()) {
705 _editor_list_vbox.pack_start (*_time_info_box, false, false, 0);
706 _editor_list_vbox.pack_start (_the_notebook);
707 edit_pane.add (_editor_list_vbox);
708 edit_pane.set_child_minsize (_editor_list_vbox, 30); /* rough guess at width of notebook tabs */
711 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
712 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
715 if (!settings || !settings->get_property ("edit-horizontal-pane-pos", fract) || fract > 1.0) {
716 /* initial allocation is 90% to canvas, 10% to notebook */
719 edit_pane.set_divider (0, fract);
721 if (!settings || !settings->get_property ("edit-vertical-pane-pos", fract) || fract > 1.0) {
722 /* initial allocation is 90% to canvas, 10% to summary */
725 editor_summary_pane.set_divider (0, fract);
727 global_vpacker.set_spacing (2);
728 global_vpacker.set_border_width (0);
730 //the next three EventBoxes provide the ability for their child widgets to have a background color. That is all.
732 Gtk::EventBox* ebox = manage (new Gtk::EventBox); //a themeable box
733 ebox->set_name("EditorWindow");
734 ebox->add (toolbar_hbox);
736 Gtk::EventBox* epane_box = manage (new EventBoxExt); //a themeable box
737 epane_box->set_name("EditorWindow");
738 epane_box->add (edit_pane);
740 Gtk::EventBox* epane_box2 = manage (new EventBoxExt); //a themeable box
741 epane_box2->set_name("EditorWindow");
742 epane_box2->add (global_vpacker);
744 global_vpacker.pack_start (*ebox, false, false);
745 global_vpacker.pack_start (*epane_box, true, true);
746 global_hpacker.pack_start (*epane_box2, true, true);
748 /* need to show the "contents" widget so that notebook will show if tab is switched to
751 global_hpacker.show ();
753 /* register actions now so that set_state() can find them and set toggles/checks etc */
760 _playlist_selector = new PlaylistSelector();
761 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
763 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
767 nudge_forward_button.set_name ("nudge button");
768 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
770 nudge_backward_button.set_name ("nudge button");
771 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
773 fade_context_menu.set_name ("ArdourContextMenu");
775 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
777 /* allow external control surfaces/protocols to do various things */
779 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
780 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
781 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
782 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
783 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
784 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
785 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
786 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
787 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
788 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
789 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
790 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
791 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
792 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
794 ControlProtocol::AddStripableToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
795 ControlProtocol::RemoveStripableFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
796 ControlProtocol::SetStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
797 ControlProtocol::ToggleStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
798 ControlProtocol::ClearStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
800 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
804 ARDOUR_UI::instance()->Escape.connect (*this, invalidator (*this), boost::bind (&Editor::escape, this), gui_context());
806 /* problematic: has to return a value and thus cannot be x-thread */
808 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
810 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
811 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
813 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
815 _ignore_region_action = false;
816 _last_region_menu_was_main = false;
817 _popup_region_menu_item = 0;
819 _show_marker_lines = false;
821 /* Button bindings */
823 button_bindings = new Bindings ("editor-mouse");
825 XMLNode* node = button_settings();
827 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
828 button_bindings->load_operation (**i);
834 /* grab current parameter state */
835 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
836 UIConfiguration::instance().map_parameters (pc);
838 setup_fade_images ();
840 set_grid_to (GridTypeNone);
847 delete button_bindings;
849 delete _route_groups;
850 delete _track_canvas_viewport;
853 delete _verbose_cursor;
854 delete quantize_dialog;
860 delete _playlist_selector;
861 delete _time_info_box;
866 LuaInstance::destroy_instance ();
868 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
871 for (std::map<ARDOUR::FadeShape, Gtk::Image*>::const_iterator i = _xfade_in_images.begin(); i != _xfade_in_images.end (); ++i) {
874 for (std::map<ARDOUR::FadeShape, Gtk::Image*>::const_iterator i = _xfade_out_images.begin(); i != _xfade_out_images.end (); ++i) {
880 Editor::button_settings () const
882 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
883 XMLNode* node = find_named_node (*settings, X_("Buttons"));
886 node = new XMLNode (X_("Buttons"));
893 Editor::get_smart_mode () const
895 return ((current_mouse_mode() == MouseObject) && smart_mode_action->get_active());
899 Editor::catch_vanishing_regionview (RegionView *rv)
901 /* note: the selection will take care of the vanishing
902 audioregionview by itself.
905 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
909 if (clicked_regionview == rv) {
910 clicked_regionview = 0;
913 if (entered_regionview == rv) {
914 set_entered_regionview (0);
917 if (!_all_region_actions_sensitized) {
918 sensitize_all_region_actions (true);
923 Editor::set_entered_regionview (RegionView* rv)
925 if (rv == entered_regionview) {
929 if (entered_regionview) {
930 entered_regionview->exited ();
933 entered_regionview = rv;
935 if (entered_regionview != 0) {
936 entered_regionview->entered ();
939 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
940 /* This RegionView entry might have changed what region actions
941 are allowed, so sensitize them all in case a key is pressed.
943 sensitize_all_region_actions (true);
948 Editor::set_entered_track (TimeAxisView* tav)
951 entered_track->exited ();
957 entered_track->entered ();
962 Editor::instant_save ()
964 if (!constructed || !ARDOUR_UI::instance()->session_loaded || no_save_instant) {
969 _session->add_instant_xml(get_state());
971 Config->add_instant_xml(get_state());
976 Editor::control_vertical_zoom_in_all ()
978 tav_zoom_smooth (false, true);
982 Editor::control_vertical_zoom_out_all ()
984 tav_zoom_smooth (true, true);
988 Editor::control_vertical_zoom_in_selected ()
990 tav_zoom_smooth (false, false);
994 Editor::control_vertical_zoom_out_selected ()
996 tav_zoom_smooth (true, false);
1000 Editor::control_view (uint32_t view)
1002 goto_visual_state (view);
1006 Editor::control_unselect ()
1008 selection->clear_tracks ();
1012 Editor::control_select (boost::shared_ptr<Stripable> s, Selection::Operation op)
1014 TimeAxisView* tav = time_axis_view_from_stripable (s);
1018 case Selection::Add:
1019 selection->add (tav);
1021 case Selection::Toggle:
1022 selection->toggle (tav);
1024 case Selection::Extend:
1026 case Selection::Set:
1027 selection->set (tav);
1031 selection->clear_tracks ();
1036 Editor::control_step_tracks_up ()
1038 scroll_tracks_up_line ();
1042 Editor::control_step_tracks_down ()
1044 scroll_tracks_down_line ();
1048 Editor::control_scroll (float fraction)
1050 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1056 double step = fraction * current_page_samples();
1059 _control_scroll_target is an optional<T>
1061 it acts like a pointer to an samplepos_t, with
1062 a operator conversion to boolean to check
1063 that it has a value could possibly use
1064 playhead_cursor->current_sample to store the
1065 value and a boolean in the class to know
1066 when it's out of date
1069 if (!_control_scroll_target) {
1070 _control_scroll_target = _session->transport_sample();
1071 _dragging_playhead = true;
1074 if ((fraction < 0.0f) && (*_control_scroll_target <= (samplepos_t) fabs(step))) {
1075 *_control_scroll_target = 0;
1076 } else if ((fraction > 0.0f) && (max_samplepos - *_control_scroll_target < step)) {
1077 *_control_scroll_target = max_samplepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1079 *_control_scroll_target += (samplepos_t) trunc (step);
1082 /* move visuals, we'll catch up with it later */
1084 playhead_cursor->set_position (*_control_scroll_target);
1085 UpdateAllTransportClocks (*_control_scroll_target);
1087 if (*_control_scroll_target > (current_page_samples() / 2)) {
1088 /* try to center PH in window */
1089 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1095 Now we do a timeout to actually bring the session to the right place
1096 according to the playhead. This is to avoid reading disk buffers on every
1097 call to control_scroll, which is driven by ScrollTimeline and therefore
1098 probably by a control surface wheel which can generate lots of events.
1100 /* cancel the existing timeout */
1102 control_scroll_connection.disconnect ();
1104 /* add the next timeout */
1106 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1110 Editor::deferred_control_scroll (samplepos_t /*target*/)
1112 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1113 // reset for next stream
1114 _control_scroll_target = boost::none;
1115 _dragging_playhead = false;
1120 Editor::access_action (const std::string& action_group, const std::string& action_item)
1126 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1129 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1137 Editor::set_toggleaction (const std::string& action_group, const std::string& action_item, bool s)
1139 ActionManager::set_toggleaction_state (action_group.c_str(), action_item.c_str(), s);
1143 Editor::on_realize ()
1147 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1148 start_lock_event_timing ();
1153 Editor::start_lock_event_timing ()
1155 /* check if we should lock the GUI every 30 seconds */
1157 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1161 Editor::generic_event_handler (GdkEvent* ev)
1164 case GDK_BUTTON_PRESS:
1165 case GDK_BUTTON_RELEASE:
1166 case GDK_MOTION_NOTIFY:
1168 case GDK_KEY_RELEASE:
1169 if (contents().is_mapped()) {
1170 gettimeofday (&last_event_time, 0);
1174 case GDK_LEAVE_NOTIFY:
1175 switch (ev->crossing.detail) {
1176 case GDK_NOTIFY_UNKNOWN:
1177 case GDK_NOTIFY_INFERIOR:
1178 case GDK_NOTIFY_ANCESTOR:
1180 case GDK_NOTIFY_VIRTUAL:
1181 case GDK_NOTIFY_NONLINEAR:
1182 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1183 /* leaving window, so reset focus, thus ending any and
1184 all text entry operations.
1186 ARDOUR_UI::instance()->reset_focus (&contents());
1199 Editor::lock_timeout_callback ()
1201 struct timeval now, delta;
1203 gettimeofday (&now, 0);
1205 timersub (&now, &last_event_time, &delta);
1207 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1209 /* don't call again. Returning false will effectively
1210 disconnect us from the timer callback.
1212 unlock() will call start_lock_event_timing() to get things
1222 Editor::map_position_change (samplepos_t sample)
1224 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, sample)
1226 if (_session == 0) {
1230 if (_follow_playhead) {
1231 center_screen (sample);
1234 playhead_cursor->set_position (sample);
1238 Editor::center_screen (samplepos_t sample)
1240 samplecnt_t const page = _visible_canvas_width * samples_per_pixel;
1242 /* if we're off the page, then scroll.
1245 if (sample < _leftmost_sample || sample >= _leftmost_sample + page) {
1246 center_screen_internal (sample, page);
1251 Editor::center_screen_internal (samplepos_t sample, float page)
1255 if (sample > page) {
1256 sample -= (samplepos_t) page;
1261 reset_x_origin (sample);
1266 Editor::update_title ()
1268 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1270 if (!own_window()) {
1275 bool dirty = _session->dirty();
1277 string session_name;
1279 if (_session->snap_name() != _session->name()) {
1280 session_name = _session->snap_name();
1282 session_name = _session->name();
1286 session_name = "*" + session_name;
1289 WindowTitle title(session_name);
1290 title += S_("Window|Editor");
1291 title += Glib::get_application_name();
1292 own_window()->set_title (title.get_string());
1294 /* ::session_going_away() will have taken care of it */
1299 Editor::set_session (Session *t)
1301 SessionHandlePtr::set_session (t);
1307 //initialize _leftmost_sample to the extents of the session
1308 //this prevents a bogus setting of leftmost = "0" if the summary view asks for the leftmost sample before the visible state has been loaded from instant.xml
1309 _leftmost_sample = session_gui_extents().first;
1311 _playlist_selector->set_session (_session);
1312 nudge_clock->set_session (_session);
1313 _summary->set_session (_session);
1314 _group_tabs->set_session (_session);
1315 _route_groups->set_session (_session);
1316 _regions->set_session (_session);
1317 _snapshots->set_session (_session);
1318 _routes->set_session (_session);
1319 _locations->set_session (_session);
1320 _time_info_box->set_session (_session);
1322 if (rhythm_ferret) {
1323 rhythm_ferret->set_session (_session);
1326 if (analysis_window) {
1327 analysis_window->set_session (_session);
1331 sfbrowser->set_session (_session);
1334 compute_fixed_ruler_scale ();
1336 /* Make sure we have auto loop and auto punch ranges */
1338 Location* loc = _session->locations()->auto_loop_location();
1340 loc->set_name (_("Loop"));
1343 loc = _session->locations()->auto_punch_location();
1346 loc->set_name (_("Punch"));
1349 refresh_location_display ();
1351 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1352 the selected Marker; this needs the LocationMarker list to be available.
1354 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1355 set_state (*node, Stateful::loading_state_version);
1357 /* catch up on selection state, etc. */
1360 sc.add (Properties::selected);
1361 presentation_info_changed (sc);
1363 /* catch up with the playhead */
1365 _session->request_locate (playhead_cursor->current_sample ());
1366 _pending_initial_locate = true;
1370 /* These signals can all be emitted by a non-GUI thread. Therefore the
1371 handlers for them must not attempt to directly interact with the GUI,
1372 but use PBD::Signal<T>::connect() which accepts an event loop
1373 ("context") where the handler will be asked to run.
1376 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1377 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1378 _session->TransportLooped.connect (_session_connections, invalidator (*this), boost::bind (&Editor::transport_looped, this), gui_context());
1379 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1380 _session->vca_manager().VCAAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_vcas, this, _1), gui_context());
1381 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1382 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1383 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1384 _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempometric_position_changed, this, _1), gui_context());
1385 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1386 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1387 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1388 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1389 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1390 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1391 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1393 playhead_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
1394 playhead_cursor->show ();
1396 snapped_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
1397 snapped_cursor->set_color (UIConfiguration::instance().color ("edit point"));
1398 snapped_cursor->show ();
1400 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1401 Config->map_parameters (pc);
1402 _session->config.map_parameters (pc);
1404 restore_ruler_visibility ();
1405 //tempo_map_changed (PropertyChange (0));
1406 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1408 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1409 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1412 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1413 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1416 /* register for undo history */
1417 _session->register_with_memento_command_factory(id(), this);
1418 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1420 LuaInstance::instance()->set_session(_session);
1422 start_updating_meters ();
1426 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1428 using namespace Menu_Helpers;
1430 void (Editor::*emf)(FadeShape);
1431 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1434 images = &_xfade_in_images;
1435 emf = &Editor::set_fade_in_shape;
1437 images = &_xfade_out_images;
1438 emf = &Editor::set_fade_out_shape;
1443 _("Linear (for highly correlated material)"),
1444 *(*images)[FadeLinear],
1445 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1449 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1453 _("Constant power"),
1454 *(*images)[FadeConstantPower],
1455 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1458 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1463 *(*images)[FadeSymmetric],
1464 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1468 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1473 *(*images)[FadeSlow],
1474 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1477 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1482 *(*images)[FadeFast],
1483 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1486 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1489 /** Pop up a context menu for when the user clicks on a start crossfade */
1491 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1493 using namespace Menu_Helpers;
1494 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1499 MenuList& items (xfade_in_context_menu.items());
1502 if (arv->audio_region()->fade_in_active()) {
1503 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1505 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1508 items.push_back (SeparatorElem());
1509 fill_xfade_menu (items, true);
1511 xfade_in_context_menu.popup (button, time);
1514 /** Pop up a context menu for when the user clicks on an end crossfade */
1516 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1518 using namespace Menu_Helpers;
1519 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1524 MenuList& items (xfade_out_context_menu.items());
1527 if (arv->audio_region()->fade_out_active()) {
1528 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1530 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1533 items.push_back (SeparatorElem());
1534 fill_xfade_menu (items, false);
1536 xfade_out_context_menu.popup (button, time);
1540 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1542 using namespace Menu_Helpers;
1543 Menu* (Editor::*build_menu_function)();
1546 switch (item_type) {
1548 case RegionViewName:
1549 case RegionViewNameHighlight:
1550 case LeftFrameHandle:
1551 case RightFrameHandle:
1552 if (with_selection) {
1553 build_menu_function = &Editor::build_track_selection_context_menu;
1555 build_menu_function = &Editor::build_track_region_context_menu;
1560 if (with_selection) {
1561 build_menu_function = &Editor::build_track_selection_context_menu;
1563 build_menu_function = &Editor::build_track_context_menu;
1568 if (clicked_routeview->track()) {
1569 build_menu_function = &Editor::build_track_context_menu;
1571 build_menu_function = &Editor::build_track_bus_context_menu;
1576 /* probably shouldn't happen but if it does, we don't care */
1580 menu = (this->*build_menu_function)();
1581 menu->set_name ("ArdourContextMenu");
1583 /* now handle specific situations */
1585 switch (item_type) {
1587 case RegionViewName:
1588 case RegionViewNameHighlight:
1589 case LeftFrameHandle:
1590 case RightFrameHandle:
1591 if (!with_selection) {
1592 if (region_edit_menu_split_item) {
1593 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1594 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1596 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1599 if (region_edit_menu_split_multichannel_item) {
1600 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1601 region_edit_menu_split_multichannel_item->set_sensitive (true);
1603 region_edit_menu_split_multichannel_item->set_sensitive (false);
1616 /* probably shouldn't happen but if it does, we don't care */
1620 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1622 /* Bounce to disk */
1624 using namespace Menu_Helpers;
1625 MenuList& edit_items = menu->items();
1627 edit_items.push_back (SeparatorElem());
1629 switch (clicked_routeview->audio_track()->freeze_state()) {
1630 case AudioTrack::NoFreeze:
1631 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1634 case AudioTrack::Frozen:
1635 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1638 case AudioTrack::UnFrozen:
1639 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1645 if (item_type == StreamItem && clicked_routeview) {
1646 clicked_routeview->build_underlay_menu(menu);
1649 /* When the region menu is opened, we setup the actions so that they look right
1652 sensitize_the_right_region_actions (false);
1653 _last_region_menu_was_main = false;
1655 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1656 menu->popup (button, time);
1660 Editor::build_track_context_menu ()
1662 using namespace Menu_Helpers;
1664 MenuList& edit_items = track_context_menu.items();
1667 add_dstream_context_items (edit_items);
1668 return &track_context_menu;
1672 Editor::build_track_bus_context_menu ()
1674 using namespace Menu_Helpers;
1676 MenuList& edit_items = track_context_menu.items();
1679 add_bus_context_items (edit_items);
1680 return &track_context_menu;
1684 Editor::build_track_region_context_menu ()
1686 using namespace Menu_Helpers;
1687 MenuList& edit_items = track_region_context_menu.items();
1690 /* we've just cleared the track region context menu, so the menu that these
1691 two items were on will have disappeared; stop them dangling.
1693 region_edit_menu_split_item = 0;
1694 region_edit_menu_split_multichannel_item = 0;
1696 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1699 boost::shared_ptr<Track> tr;
1700 boost::shared_ptr<Playlist> pl;
1702 if ((tr = rtv->track())) {
1703 add_region_context_items (edit_items, tr);
1707 add_dstream_context_items (edit_items);
1709 return &track_region_context_menu;
1713 Editor::loudness_analyze_region_selection ()
1718 Selection& s (PublicEditor::instance ().get_selection ());
1719 RegionSelection ars = s.regions;
1720 ARDOUR::AnalysisGraph ag (_session);
1721 samplecnt_t total_work = 0;
1723 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1724 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1728 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1731 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1732 total_work += arv->region ()->length ();
1735 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1737 ag.set_total_samples (total_work);
1738 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1741 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1742 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1746 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1750 ag.analyze_region (ar);
1753 if (!ag.canceled ()) {
1754 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1760 Editor::loudness_analyze_range_selection ()
1765 Selection& s (PublicEditor::instance ().get_selection ());
1766 TimeSelection ts = s.time;
1767 ARDOUR::AnalysisGraph ag (_session);
1768 samplecnt_t total_work = 0;
1770 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1771 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1775 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1779 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1780 total_work += j->length ();
1784 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1786 ag.set_total_samples (total_work);
1787 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1790 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1791 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1795 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1799 ag.analyze_range (rui->route (), pl, ts);
1802 if (!ag.canceled ()) {
1803 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1809 Editor::spectral_analyze_region_selection ()
1811 if (analysis_window == 0) {
1812 analysis_window = new AnalysisWindow();
1815 analysis_window->set_session(_session);
1817 analysis_window->show_all();
1820 analysis_window->set_regionmode();
1821 analysis_window->analyze();
1823 analysis_window->present();
1827 Editor::spectral_analyze_range_selection()
1829 if (analysis_window == 0) {
1830 analysis_window = new AnalysisWindow();
1833 analysis_window->set_session(_session);
1835 analysis_window->show_all();
1838 analysis_window->set_rangemode();
1839 analysis_window->analyze();
1841 analysis_window->present();
1845 Editor::build_track_selection_context_menu ()
1847 using namespace Menu_Helpers;
1848 MenuList& edit_items = track_selection_context_menu.items();
1849 edit_items.clear ();
1851 add_selection_context_items (edit_items);
1852 // edit_items.push_back (SeparatorElem());
1853 // add_dstream_context_items (edit_items);
1855 return &track_selection_context_menu;
1859 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1861 using namespace Menu_Helpers;
1863 /* OK, stick the region submenu at the top of the list, and then add
1867 RegionSelection rs = get_regions_from_selection_and_entered ();
1869 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1871 if (_popup_region_menu_item == 0) {
1872 _popup_region_menu_item = new MenuItem (menu_item_name, false);
1873 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1874 _popup_region_menu_item->show ();
1876 _popup_region_menu_item->set_label (menu_item_name);
1879 /* No layering allowed in later is higher layering model */
1880 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1881 if (act && Config->get_layer_model() == LaterHigher) {
1882 act->set_sensitive (false);
1884 act->set_sensitive (true);
1887 const samplepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1889 edit_items.push_back (*_popup_region_menu_item);
1890 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1891 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1893 edit_items.push_back (SeparatorElem());
1896 /** Add context menu items relevant to selection ranges.
1897 * @param edit_items List to add the items to.
1900 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1902 using namespace Menu_Helpers;
1904 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1905 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1907 edit_items.push_back (SeparatorElem());
1908 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), Horizontal)));
1910 edit_items.push_back (SeparatorElem());
1911 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1912 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1914 edit_items.push_back (SeparatorElem());
1916 edit_items.push_back (
1918 _("Move Range Start to Previous Region Boundary"),
1919 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1923 edit_items.push_back (
1925 _("Move Range Start to Next Region Boundary"),
1926 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1930 edit_items.push_back (
1932 _("Move Range End to Previous Region Boundary"),
1933 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1937 edit_items.push_back (
1939 _("Move Range End to Next Region Boundary"),
1940 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1944 edit_items.push_back (SeparatorElem());
1945 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1946 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1948 edit_items.push_back (SeparatorElem());
1949 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1951 edit_items.push_back (SeparatorElem());
1952 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1953 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1954 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1956 edit_items.push_back (SeparatorElem());
1957 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1959 edit_items.push_back (SeparatorElem());
1960 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1961 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1963 edit_items.push_back (SeparatorElem());
1964 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1965 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1966 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1967 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1968 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1969 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1970 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1976 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1978 using namespace Menu_Helpers;
1982 Menu *play_menu = manage (new Menu);
1983 MenuList& play_items = play_menu->items();
1984 play_menu->set_name ("ArdourContextMenu");
1986 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1987 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1988 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1989 play_items.push_back (SeparatorElem());
1990 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1992 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1996 Menu *select_menu = manage (new Menu);
1997 MenuList& select_items = select_menu->items();
1998 select_menu->set_name ("ArdourContextMenu");
2000 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2001 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2002 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2003 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2004 select_items.push_back (SeparatorElem());
2005 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2006 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2007 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2008 select_items.push_back (SeparatorElem());
2009 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2010 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2011 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2012 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2013 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2014 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2015 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2017 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2021 Menu *cutnpaste_menu = manage (new Menu);
2022 MenuList& cutnpaste_items = cutnpaste_menu->items();
2023 cutnpaste_menu->set_name ("ArdourContextMenu");
2025 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2026 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2027 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2029 cutnpaste_items.push_back (SeparatorElem());
2031 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2032 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2034 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2036 /* Adding new material */
2038 edit_items.push_back (SeparatorElem());
2039 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2040 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2044 Menu *nudge_menu = manage (new Menu());
2045 MenuList& nudge_items = nudge_menu->items();
2046 nudge_menu->set_name ("ArdourContextMenu");
2048 edit_items.push_back (SeparatorElem());
2049 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2050 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2051 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2052 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2054 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2058 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2060 using namespace Menu_Helpers;
2064 Menu *play_menu = manage (new Menu);
2065 MenuList& play_items = play_menu->items();
2066 play_menu->set_name ("ArdourContextMenu");
2068 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2069 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2070 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2074 Menu *select_menu = manage (new Menu);
2075 MenuList& select_items = select_menu->items();
2076 select_menu->set_name ("ArdourContextMenu");
2078 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2079 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2080 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2081 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2082 select_items.push_back (SeparatorElem());
2083 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2084 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2085 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2086 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2088 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2092 Menu *cutnpaste_menu = manage (new Menu);
2093 MenuList& cutnpaste_items = cutnpaste_menu->items();
2094 cutnpaste_menu->set_name ("ArdourContextMenu");
2096 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2097 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2098 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2100 Menu *nudge_menu = manage (new Menu());
2101 MenuList& nudge_items = nudge_menu->items();
2102 nudge_menu->set_name ("ArdourContextMenu");
2104 edit_items.push_back (SeparatorElem());
2105 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2106 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2107 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2108 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2110 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2114 Editor::grid_type() const
2120 Editor::grid_musical() const
2122 switch (_grid_type) {
2123 case GridTypeBeatDiv32:
2124 case GridTypeBeatDiv28:
2125 case GridTypeBeatDiv24:
2126 case GridTypeBeatDiv20:
2127 case GridTypeBeatDiv16:
2128 case GridTypeBeatDiv14:
2129 case GridTypeBeatDiv12:
2130 case GridTypeBeatDiv10:
2131 case GridTypeBeatDiv8:
2132 case GridTypeBeatDiv7:
2133 case GridTypeBeatDiv6:
2134 case GridTypeBeatDiv5:
2135 case GridTypeBeatDiv4:
2136 case GridTypeBeatDiv3:
2137 case GridTypeBeatDiv2:
2143 case GridTypeMinSec:
2144 case GridTypeSamples:
2151 Editor::grid_nonmusical() const
2153 switch (_grid_type) {
2155 case GridTypeMinSec:
2156 case GridTypeSamples:
2158 case GridTypeBeatDiv32:
2159 case GridTypeBeatDiv28:
2160 case GridTypeBeatDiv24:
2161 case GridTypeBeatDiv20:
2162 case GridTypeBeatDiv16:
2163 case GridTypeBeatDiv14:
2164 case GridTypeBeatDiv12:
2165 case GridTypeBeatDiv10:
2166 case GridTypeBeatDiv8:
2167 case GridTypeBeatDiv7:
2168 case GridTypeBeatDiv6:
2169 case GridTypeBeatDiv5:
2170 case GridTypeBeatDiv4:
2171 case GridTypeBeatDiv3:
2172 case GridTypeBeatDiv2:
2181 Editor::snap_mode() const
2187 Editor::set_grid_to (GridType gt)
2189 if (_grid_type == gt) { //already set
2193 unsigned int grid_ind = (unsigned int)gt;
2195 if (internal_editing()) {
2196 internal_grid_type = gt;
2198 pre_internal_grid_type = gt;
2203 if (grid_ind > grid_type_strings.size() - 1) {
2205 _grid_type = (GridType)grid_ind;
2208 string str = grid_type_strings[grid_ind];
2210 if (str != grid_type_selector.get_text()) {
2211 grid_type_selector.set_text (str);
2214 //show appropriate rulers for this grid setting. (ToDo: perhaps make this optional)
2215 //Currently this is 'required' because the RULER calculates the grid_marks which will be used by grid_lines
2216 if ( grid_musical() ) {
2217 ruler_tempo_action->set_active(true);
2218 ruler_meter_action->set_active(true);
2220 ruler_bbt_action->set_active(true);
2221 ruler_timecode_action->set_active(false);
2222 ruler_minsec_action->set_active(false);
2223 ruler_samples_action->set_active(false);
2224 } else if (_grid_type == GridTypeSmpte ) {
2225 ruler_tempo_action->set_active(false);
2226 ruler_meter_action->set_active(false);
2228 ruler_bbt_action->set_active(false);
2229 ruler_timecode_action->set_active(true);
2230 ruler_minsec_action->set_active(false);
2231 ruler_samples_action->set_active(false);
2232 } else if (_grid_type == GridTypeMinSec ) {
2233 ruler_tempo_action->set_active(false);
2234 ruler_meter_action->set_active(false);
2236 ruler_bbt_action->set_active(false);
2237 ruler_timecode_action->set_active(false);
2238 ruler_minsec_action->set_active(true);
2239 ruler_samples_action->set_active(false);
2240 } else if (_grid_type == GridTypeSamples ) {
2241 ruler_tempo_action->set_active(false);
2242 ruler_meter_action->set_active(false);
2244 ruler_bbt_action->set_active(false);
2245 ruler_timecode_action->set_active(false);
2246 ruler_minsec_action->set_active(false);
2247 ruler_samples_action->set_active(true);
2252 if ( grid_musical() ) {
2253 compute_bbt_ruler_scale (_leftmost_sample, _leftmost_sample + current_page_samples());
2254 update_tempo_based_rulers ();
2257 mark_region_boundary_cache_dirty ();
2259 redisplay_grid (false);
2261 SnapChanged (); /* EMIT SIGNAL */
2265 Editor::set_snap_mode (SnapMode mode)
2267 if (internal_editing()) {
2268 internal_snap_mode = mode;
2270 pre_internal_snap_mode = mode;
2275 if (_snap_mode == SnapOff ) {
2276 snap_mode_button.set_active_state (Gtkmm2ext::Off);
2278 snap_mode_button.set_active_state (Gtkmm2ext::ExplicitActive);
2285 Editor::set_edit_point_preference (EditPoint ep, bool force)
2287 bool changed = (_edit_point != ep);
2290 if (Profile->get_mixbus())
2291 if (ep == EditAtSelectedMarker)
2292 ep = EditAtPlayhead;
2294 string str = edit_point_strings[(int)ep];
2295 if (str != edit_point_selector.get_text ()) {
2296 edit_point_selector.set_text (str);
2299 update_all_enter_cursors();
2301 if (!force && !changed) {
2305 const char* action=NULL;
2307 switch (_edit_point) {
2308 case EditAtPlayhead:
2309 action = "edit-at-playhead";
2311 case EditAtSelectedMarker:
2312 action = "edit-at-marker";
2315 action = "edit-at-mouse";
2319 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2321 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2325 bool in_track_canvas;
2327 if (!mouse_sample (foo, in_track_canvas)) {
2328 in_track_canvas = false;
2331 reset_canvas_action_sensitivity (in_track_canvas);
2332 sensitize_the_right_region_actions (false);
2338 Editor::set_state (const XMLNode& node, int version)
2341 PBD::Unwinder<bool> nsi (no_save_instant, true);
2344 Tabbable::set_state (node, version);
2347 if (_session && node.get_property ("playhead", ph_pos)) {
2349 playhead_cursor->set_position (ph_pos);
2351 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2352 playhead_cursor->set_position (0);
2355 playhead_cursor->set_position (0);
2358 node.get_property ("mixer-width", editor_mixer_strip_width);
2360 node.get_property ("zoom-focus", zoom_focus);
2361 zoom_focus_selection_done (zoom_focus);
2364 if (node.get_property ("zoom", z)) {
2365 /* older versions of ardour used floating point samples_per_pixel */
2366 reset_zoom (llrintf (z));
2368 reset_zoom (samples_per_pixel);
2372 if (node.get_property ("visible-track-count", cnt)) {
2373 set_visible_track_count (cnt);
2377 if (!node.get_property ("grid-type", grid_type)) {
2378 grid_type = _grid_type;
2380 set_grid_to (grid_type);
2383 if (node.get_property ("snap-mode", sm)) {
2384 snap_mode_selection_done(sm);
2385 /* set text of Dropdown. in case _snap_mode == SnapOff (default)
2386 * snap_mode_selection_done() will only mark an already active item as active
2387 * which does not trigger set_text().
2391 set_snap_mode (_snap_mode);
2394 node.get_property ("internal-grid-type", internal_grid_type);
2395 node.get_property ("internal-snap-mode", internal_snap_mode);
2396 node.get_property ("pre-internal-grid-type", pre_internal_grid_type);
2397 node.get_property ("pre-internal-snap-mode", pre_internal_snap_mode);
2400 if (node.get_property ("mouse-mode", mm_str)) {
2401 MouseMode m = str2mousemode(mm_str);
2402 set_mouse_mode (m, true);
2404 set_mouse_mode (MouseObject, true);
2408 if (node.get_property ("left-frame", lf_pos)) {
2412 reset_x_origin (lf_pos);
2416 if (node.get_property ("y-origin", y_origin)) {
2417 reset_y_origin (y_origin);
2420 if (node.get_property ("join-object-range", yn)) {
2421 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2423 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2424 tact->set_active (!yn);
2425 tact->set_active (yn);
2427 set_mouse_mode(mouse_mode, true);
2431 if (node.get_property ("edit-point", ep)) {
2432 set_edit_point_preference (ep, true);
2434 set_edit_point_preference (_edit_point);
2437 if (node.get_property ("follow-playhead", yn)) {
2438 set_follow_playhead (yn);
2441 if (node.get_property ("stationary-playhead", yn)) {
2442 set_stationary_playhead (yn);
2445 RegionListSortType sort_type;
2446 if (node.get_property ("region-list-sort-type", sort_type)) {
2447 _regions->reset_sort_type (sort_type, true);
2450 if (node.get_property ("show-editor-mixer", yn)) {
2452 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2455 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2457 /* do it twice to force the change */
2459 tact->set_active (!yn);
2460 tact->set_active (yn);
2463 if (node.get_property ("show-editor-list", yn)) {
2465 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2468 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2470 /* do it twice to force the change */
2472 tact->set_active (!yn);
2473 tact->set_active (yn);
2477 if (node.get_property (X_("editor-list-page"), el_page)) {
2478 _the_notebook.set_current_page (el_page);
2481 if (node.get_property (X_("show-marker-lines"), yn)) {
2482 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2484 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2486 tact->set_active (!yn);
2487 tact->set_active (yn);
2490 XMLNodeList children = node.children ();
2491 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2492 selection->set_state (**i, Stateful::current_state_version);
2493 _regions->set_state (**i);
2494 _locations->set_state (**i);
2497 if (node.get_property ("maximised", yn)) {
2498 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2500 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2501 bool fs = tact && tact->get_active();
2503 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2507 samplepos_t nudge_clock_value;
2508 if (node.get_property ("nudge-clock-value", nudge_clock_value)) {
2509 nudge_clock->set (nudge_clock_value);
2511 nudge_clock->set_mode (AudioClock::Timecode);
2512 nudge_clock->set (_session->sample_rate() * 5, true);
2517 * Not all properties may have been in XML, but
2518 * those that are linked to a private variable may need changing
2522 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2523 yn = _follow_playhead;
2525 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2526 if (tact->get_active() != yn) {
2527 tact->set_active (yn);
2531 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2532 yn = _stationary_playhead;
2534 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2535 if (tact->get_active() != yn) {
2536 tact->set_active (yn);
2541 return LuaInstance::instance()->set_state(node);
2545 Editor::get_state ()
2547 XMLNode* node = new XMLNode (X_("Editor"));
2549 node->set_property ("id", id().to_s ());
2551 node->add_child_nocopy (Tabbable::get_state());
2553 node->set_property("edit-horizontal-pane-pos", edit_pane.get_divider ());
2554 node->set_property("notebook-shrunk", _notebook_shrunk);
2555 node->set_property("edit-vertical-pane-pos", editor_summary_pane.get_divider());
2557 maybe_add_mixer_strip_width (*node);
2559 node->set_property ("zoom-focus", zoom_focus);
2561 node->set_property ("zoom", samples_per_pixel);
2562 node->set_property ("grid-type", _grid_type);
2563 node->set_property ("snap-mode", _snap_mode);
2564 node->set_property ("internal-grid-type", internal_grid_type);
2565 node->set_property ("internal-snap-mode", internal_snap_mode);
2566 node->set_property ("pre-internal-grid-type", pre_internal_grid_type);
2567 node->set_property ("pre-internal-snap-mode", pre_internal_snap_mode);
2568 node->set_property ("edit-point", _edit_point);
2569 node->set_property ("visible-track-count", _visible_track_count);
2571 node->set_property ("playhead", playhead_cursor->current_sample ());
2572 node->set_property ("left-frame", _leftmost_sample);
2573 node->set_property ("y-origin", vertical_adjustment.get_value ());
2575 node->set_property ("maximised", _maximised);
2576 node->set_property ("follow-playhead", _follow_playhead);
2577 node->set_property ("stationary-playhead", _stationary_playhead);
2578 node->set_property ("region-list-sort-type", _regions->sort_type ());
2579 node->set_property ("mouse-mode", mouse_mode);
2580 node->set_property ("join-object-range", smart_mode_action->get_active ());
2582 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2584 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2585 node->set_property (X_("show-editor-mixer"), tact->get_active());
2588 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2590 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2591 node->set_property (X_("show-editor-list"), tact->get_active());
2594 node->set_property (X_("editor-list-page"), _the_notebook.get_current_page ());
2596 if (button_bindings) {
2597 XMLNode* bb = new XMLNode (X_("Buttons"));
2598 button_bindings->save (*bb);
2599 node->add_child_nocopy (*bb);
2602 node->set_property (X_("show-marker-lines"), _show_marker_lines);
2604 node->add_child_nocopy (selection->get_state ());
2605 node->add_child_nocopy (_regions->get_state ());
2607 node->set_property ("nudge-clock-value", nudge_clock->current_duration());
2609 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2610 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2611 node->add_child_nocopy (_locations->get_state ());
2616 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2617 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2619 * @return pair: TimeAxisView that y is over, layer index.
2621 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2622 * in stacked or expanded region display mode, otherwise 0.
2624 std::pair<TimeAxisView *, double>
2625 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2627 if (!trackview_relative_offset) {
2628 y -= _trackview_group->canvas_origin().y;
2632 return std::make_pair ( (TimeAxisView *) 0, 0);
2635 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2637 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2644 return std::make_pair ( (TimeAxisView *) 0, 0);
2648 Editor::set_snapped_cursor_position (samplepos_t pos)
2650 if ( _edit_point == EditAtMouse ) {
2651 snapped_cursor->set_position(pos);
2656 /** Snap a position to the grid, if appropriate, taking into account current
2657 * grid settings and also the state of any snap modifier keys that may be pressed.
2658 * @param start Position to snap.
2659 * @param event Event to get current key modifier information from, or 0.
2662 Editor::snap_to_with_modifier (MusicSample& start, GdkEvent const * event, RoundMode direction, SnapPref pref, bool for_mark)
2664 if (!_session || !event) {
2668 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2669 if (_snap_mode == SnapOff) {
2670 snap_to_internal (start, direction, pref, for_mark);
2672 start.set (start.sample, 0);
2675 if (_snap_mode != SnapOff) {
2676 snap_to_internal (start, direction, pref, for_mark);
2677 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2678 /* SnapOff, but we pressed the snap_delta modifier */
2679 snap_to_internal (start, direction, pref, for_mark);
2681 start.set (start.sample, 0);
2687 Editor::snap_to (MusicSample& start, RoundMode direction, SnapPref pref, bool for_mark, bool ensure_snap)
2689 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2690 start.set (start.sample, 0);
2694 snap_to_internal (start, direction, pref, for_mark, ensure_snap);
2698 check_best_snap ( samplepos_t presnap, samplepos_t &test, samplepos_t &dist, samplepos_t &best )
2700 samplepos_t diff = abs( test - presnap );
2701 if ( diff < dist ) {
2706 test = max_samplepos; //reset this so it doesn't get accidentally reused
2710 Editor::snap_to_grid (vector<ArdourCanvas::Ruler::Mark> marks, samplepos_t presnap, RoundMode direction)
2716 before = after = max_samplepos;
2718 //get marks to either side of presnap
2719 vector<ArdourCanvas::Ruler::Mark>::const_iterator m = marks.begin();
2720 while ( m != marks.end() && (m->position < presnap) ) {
2724 if (m == marks.end ()) {
2725 /* ran out of marks */
2726 before = grid_marks.back().position;
2729 after = m->position;
2731 if (m != marks.begin ()) {
2733 before = m->position;
2736 if (before == max_samplepos && after == max_samplepos) {
2737 /* No smpte to snap to, so just don't snap */
2739 } else if (before == max_samplepos) {
2741 } else if (after == max_samplepos) {
2744 if ((direction == RoundUpMaybe || direction == RoundUpAlways))
2746 else if ((direction == RoundDownMaybe || direction == RoundDownAlways))
2748 else if (direction == 0 ) {
2749 if ((presnap - before) < (after - presnap)) {
2761 Editor::marker_snap_to_internal (samplepos_t presnap, RoundMode direction)
2767 _session->locations()->marks_either_side (presnap, before, after);
2769 if (before == max_samplepos && after == max_samplepos) {
2770 /* No marks to snap to, so just don't snap */
2772 } else if (before == max_samplepos) {
2774 } else if (after == max_samplepos) {
2777 if ((direction == RoundUpMaybe || direction == RoundUpAlways)) {
2779 } else if ((direction == RoundDownMaybe || direction == RoundDownAlways)) {
2781 } else if (direction == 0 ) {
2782 if ((presnap - before) < (after - presnap)) {
2794 Editor::snap_to_internal (MusicSample& start, RoundMode direction, SnapPref pref, bool for_mark, bool ensure_snap)
2796 const samplepos_t presnap = start.sample;
2798 samplepos_t test = max_samplepos; //for each snap, we'll use this value
2799 samplepos_t dist = max_samplepos; //this records the distance of the best snap result we've found so far
2800 samplepos_t best = max_samplepos; //this records the best snap-result we've found so far
2802 //check snap-to-marker
2803 if ( UIConfiguration::instance().get_snap_to_marks() ) {
2808 test = marker_snap_to_internal ( presnap, direction );
2809 check_best_snap(presnap, test, dist, best);
2812 //check snap-to-region-{start/end/sync}
2813 if ( UIConfiguration::instance().get_snap_to_region_start() || UIConfiguration::instance().get_snap_to_region_end() || UIConfiguration::instance().get_snap_to_region_sync() ) {
2814 if (!region_boundary_cache.empty()) {
2816 vector<samplepos_t>::iterator prev = region_boundary_cache.end ();
2817 vector<samplepos_t>::iterator next = region_boundary_cache.end ();
2819 if (direction > 0) {
2820 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap);
2822 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap);
2825 if (next != region_boundary_cache.begin ()) {
2830 samplepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2831 samplepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2833 if (presnap > (p + n) / 2) {
2840 check_best_snap(presnap, test, dist, best);
2844 if (UIConfiguration::instance().get_snap_to_grid() && (_grid_type != GridTypeNone) ) {
2846 //if SnapToGrid is selected, the user wants to prioritize the music grid
2847 //in this case we should reset the best distance, so Grid will prevail
2848 dist = max_samplepos;
2850 test = snap_to_grid (grid_marks, presnap, direction);
2851 check_best_snap(presnap, test, dist, best);
2854 //now check "magnetic" state: is the grid within reasonable on-screen distance to trigger a snap?
2855 //this also helps to avoid snapping to somewhere the user can't see. ( i.e.: I clicked on a region and it disappeared!! )
2856 //ToDo: perhaps this should only occur if EditPointMouse?
2857 int snap_threshold_s = pixel_to_sample(UIConfiguration::instance().get_snap_threshold());
2859 start.set (best, 0);
2861 } else if (presnap > best) {
2862 if (presnap > (best+ snap_threshold_s)) {
2865 } else if (presnap < best) {
2866 if (presnap < (best - snap_threshold_s)) {
2871 start.set (best, 0);
2876 Editor::setup_toolbar ()
2878 HBox* mode_box = manage(new HBox);
2879 mode_box->set_border_width (2);
2880 mode_box->set_spacing(2);
2882 HBox* mouse_mode_box = manage (new HBox);
2883 HBox* mouse_mode_hbox = manage (new HBox);
2884 VBox* mouse_mode_vbox = manage (new VBox);
2885 Alignment* mouse_mode_align = manage (new Alignment);
2887 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2888 mouse_mode_size_group->add_widget (smart_mode_button);
2889 mouse_mode_size_group->add_widget (mouse_move_button);
2890 mouse_mode_size_group->add_widget (mouse_cut_button);
2891 mouse_mode_size_group->add_widget (mouse_select_button);
2892 mouse_mode_size_group->add_widget (mouse_timefx_button);
2893 mouse_mode_size_group->add_widget (mouse_audition_button);
2894 mouse_mode_size_group->add_widget (mouse_draw_button);
2895 mouse_mode_size_group->add_widget (mouse_content_button);
2897 if (!Profile->get_mixbus()) {
2898 mouse_mode_size_group->add_widget (zoom_in_button);
2899 mouse_mode_size_group->add_widget (zoom_out_button);
2900 mouse_mode_size_group->add_widget (zoom_out_full_button);
2901 mouse_mode_size_group->add_widget (zoom_focus_selector);
2902 mouse_mode_size_group->add_widget (tav_shrink_button);
2903 mouse_mode_size_group->add_widget (tav_expand_button);
2905 mouse_mode_size_group->add_widget (zoom_preset_selector);
2906 mouse_mode_size_group->add_widget (visible_tracks_selector);
2909 mouse_mode_size_group->add_widget (grid_type_selector);
2910 mouse_mode_size_group->add_widget (snap_mode_button);
2912 mouse_mode_size_group->add_widget (edit_point_selector);
2913 mouse_mode_size_group->add_widget (edit_mode_selector);
2915 mouse_mode_size_group->add_widget (*nudge_clock);
2916 mouse_mode_size_group->add_widget (nudge_forward_button);
2917 mouse_mode_size_group->add_widget (nudge_backward_button);
2919 mouse_mode_hbox->set_spacing (2);
2921 if (!ARDOUR::Profile->get_trx()) {
2922 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2925 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2926 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2928 if (!ARDOUR::Profile->get_mixbus()) {
2929 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2932 if (!ARDOUR::Profile->get_trx()) {
2933 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2934 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2935 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2936 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2939 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2941 mouse_mode_align->add (*mouse_mode_vbox);
2942 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2944 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2946 edit_mode_selector.set_name ("mouse mode button");
2948 if (!ARDOUR::Profile->get_trx()) {
2949 mode_box->pack_start (edit_mode_selector, false, false);
2952 mode_box->pack_start (*mouse_mode_box, false, false);
2956 _zoom_box.set_spacing (2);
2957 _zoom_box.set_border_width (2);
2961 zoom_preset_selector.set_name ("zoom button");
2962 zoom_preset_selector.set_icon (ArdourIcon::ZoomExpand);
2964 zoom_in_button.set_name ("zoom button");
2965 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
2966 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2967 zoom_in_button.set_related_action (act);
2969 zoom_out_button.set_name ("zoom button");
2970 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
2971 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2972 zoom_out_button.set_related_action (act);
2974 zoom_out_full_button.set_name ("zoom button");
2975 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
2976 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2977 zoom_out_full_button.set_related_action (act);
2979 zoom_focus_selector.set_name ("zoom button");
2981 if (ARDOUR::Profile->get_mixbus()) {
2982 _zoom_box.pack_start (zoom_preset_selector, false, false);
2983 } else if (ARDOUR::Profile->get_trx()) {
2984 mode_box->pack_start (zoom_out_button, false, false);
2985 mode_box->pack_start (zoom_in_button, false, false);
2987 _zoom_box.pack_start (zoom_out_button, false, false);
2988 _zoom_box.pack_start (zoom_in_button, false, false);
2989 _zoom_box.pack_start (zoom_out_full_button, false, false);
2990 _zoom_box.pack_start (zoom_focus_selector, false, false);
2993 /* Track zoom buttons */
2994 _track_box.set_spacing (2);
2995 _track_box.set_border_width (2);
2997 visible_tracks_selector.set_name ("zoom button");
2998 if (Profile->get_mixbus()) {
2999 visible_tracks_selector.set_icon (ArdourIcon::TimeAxisExpand);
3001 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3004 tav_expand_button.set_name ("zoom button");
3005 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3006 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3007 tav_expand_button.set_related_action (act);
3009 tav_shrink_button.set_name ("zoom button");
3010 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3011 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3012 tav_shrink_button.set_related_action (act);
3014 if (ARDOUR::Profile->get_mixbus()) {
3015 _track_box.pack_start (visible_tracks_selector);
3016 } else if (ARDOUR::Profile->get_trx()) {
3017 _track_box.pack_start (tav_shrink_button);
3018 _track_box.pack_start (tav_expand_button);
3020 _track_box.pack_start (visible_tracks_selector);
3021 _track_box.pack_start (tav_shrink_button);
3022 _track_box.pack_start (tav_expand_button);
3025 snap_box.set_spacing (2);
3026 snap_box.set_border_width (2);
3028 grid_type_selector.set_name ("mouse mode button");
3030 snap_mode_button.set_name ("mouse mode button");
3032 edit_point_selector.set_name ("mouse mode button");
3034 snap_box.pack_start (snap_mode_button, false, false);
3035 snap_box.pack_start (grid_type_selector, false, false);
3038 HBox *ep_box = manage (new HBox);
3039 ep_box->set_spacing (2);
3040 ep_box->set_border_width (2);
3042 ep_box->pack_start (edit_point_selector, false, false);
3046 HBox *nudge_box = manage (new HBox);
3047 nudge_box->set_spacing (2);
3048 nudge_box->set_border_width (2);
3050 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3051 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3053 nudge_box->pack_start (nudge_backward_button, false, false);
3054 nudge_box->pack_start (nudge_forward_button, false, false);
3055 nudge_box->pack_start (*nudge_clock, false, false);
3058 /* Pack everything in... */
3060 toolbar_hbox.set_spacing (2);
3061 toolbar_hbox.set_border_width (2);
3063 toolbar_hbox.pack_start (*mode_box, false, false);
3065 if (!ARDOUR::Profile->get_trx()) {
3067 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3069 toolbar_hbox.pack_start (_zoom_box, false, false);
3071 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3073 toolbar_hbox.pack_start (_track_box, false, false);
3075 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3077 toolbar_hbox.pack_start (snap_box, false, false);
3079 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3081 toolbar_hbox.pack_start (*ep_box, false, false);
3083 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3085 toolbar_hbox.pack_start (*nudge_box, false, false);
3088 toolbar_hbox.show_all ();
3092 Editor::build_edit_point_menu ()
3094 using namespace Menu_Helpers;
3096 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3097 if(!Profile->get_mixbus())
3098 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3099 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3101 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3105 Editor::build_edit_mode_menu ()
3107 using namespace Menu_Helpers;
3109 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3110 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3111 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3112 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3114 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3118 Editor::build_grid_type_menu ()
3120 using namespace Menu_Helpers;
3122 //main grid: bars, quarter-notes, etc
3123 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeNone], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeNone)));
3124 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBar], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBar)));
3125 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeat], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeat)));
3126 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv2)));
3127 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv4)));
3128 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv8)));
3129 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv16)));
3130 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv32)));
3133 grid_type_selector.AddMenuElem(SeparatorElem());
3134 Gtk::Menu *_triplet_menu = manage (new Menu);
3135 MenuList& triplet_items (_triplet_menu->items());
3137 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv3) ));
3138 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv6) ));
3139 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv12) ));
3140 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv24) ));
3142 grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Triplets"), *_triplet_menu));
3145 Gtk::Menu *_quintuplet_menu = manage (new Menu);
3146 MenuList& quintuplet_items (_quintuplet_menu->items());
3148 quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv5) ));
3149 quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv10) ));
3150 quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv20) ));
3152 grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Quintuplets"), *_quintuplet_menu));
3155 Gtk::Menu *_septuplet_menu = manage (new Menu);
3156 MenuList& septuplet_items (_septuplet_menu->items());
3158 septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv7) ));
3159 septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv14) ));
3160 septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv28) ));
3162 grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Septuplets"), *_septuplet_menu));
3164 grid_type_selector.AddMenuElem(SeparatorElem());
3165 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeSmpte], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeSmpte)));
3166 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeMinSec], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeMinSec)));
3167 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeSamples], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeSamples)));
3169 set_size_request_to_display_given_text (grid_type_selector, "No Grid", COMBO_TRIANGLE_WIDTH, 2);
3173 Editor::setup_tooltips ()
3175 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3176 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3177 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3178 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3179 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3180 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3181 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3182 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3183 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3184 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3185 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3186 set_tooltip (zoom_in_button, _("Zoom In"));
3187 set_tooltip (zoom_out_button, _("Zoom Out"));
3188 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3189 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3190 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3191 set_tooltip (tav_expand_button, _("Expand Tracks"));
3192 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3193 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3194 set_tooltip (grid_type_selector, _("Grid Mode"));
3195 set_tooltip (snap_mode_button, _("Snap Mode\n\nRight-click to visit Snap preferences."));
3196 set_tooltip (edit_point_selector, _("Edit Point"));
3197 set_tooltip (edit_mode_selector, _("Edit Mode"));
3198 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3202 Editor::convert_drop_to_paths (
3203 vector<string>& paths,
3204 const RefPtr<Gdk::DragContext>& /*context*/,
3207 const SelectionData& data,
3211 if (_session == 0) {
3215 vector<string> uris = data.get_uris();
3219 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3220 are actually URI lists. So do it by hand.
3223 if (data.get_target() != "text/plain") {
3227 /* Parse the "uri-list" format that Nautilus provides,
3228 where each pathname is delimited by \r\n.
3230 THERE MAY BE NO NULL TERMINATING CHAR!!!
3233 string txt = data.get_text();
3237 p = (char *) malloc (txt.length() + 1);
3238 txt.copy (p, txt.length(), 0);
3239 p[txt.length()] = '\0';
3245 while (g_ascii_isspace (*p))
3249 while (*q && (*q != '\n') && (*q != '\r')) {
3256 while (q > p && g_ascii_isspace (*q))
3261 uris.push_back (string (p, q - p + 1));
3265 p = strchr (p, '\n');
3277 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3278 if ((*i).substr (0,7) == "file://") {
3279 paths.push_back (Glib::filename_from_uri (*i));
3287 Editor::new_tempo_section ()
3292 Editor::map_transport_state ()
3294 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3296 if (_session && _session->transport_stopped()) {
3297 have_pending_keyboard_selection = false;
3300 update_loop_range_view ();
3304 Editor::transport_looped ()
3306 /* reset Playhead position interpolation.
3307 * see Editor::super_rapid_screen_update
3309 _last_update_time = 0;
3315 Editor::begin_selection_op_history ()
3317 selection_op_cmd_depth = 0;
3318 selection_op_history_it = 0;
3320 while(!selection_op_history.empty()) {
3321 delete selection_op_history.front();
3322 selection_op_history.pop_front();
3325 selection_undo_action->set_sensitive (false);
3326 selection_redo_action->set_sensitive (false);
3327 selection_op_history.push_front (&_selection_memento->get_state ());
3331 Editor::begin_reversible_selection_op (string name)
3334 //cerr << name << endl;
3335 /* begin/commit pairs can be nested */
3336 selection_op_cmd_depth++;
3341 Editor::commit_reversible_selection_op ()
3344 if (selection_op_cmd_depth == 1) {
3346 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3348 The user has undone some selection ops and then made a new one,
3349 making anything earlier in the list invalid.
3352 list<XMLNode *>::iterator it = selection_op_history.begin();
3353 list<XMLNode *>::iterator e_it = it;
3354 advance (e_it, selection_op_history_it);
3356 for ( ; it != e_it; ++it) {
3359 selection_op_history.erase (selection_op_history.begin(), e_it);
3362 selection_op_history.push_front (&_selection_memento->get_state ());
3363 selection_op_history_it = 0;
3365 selection_undo_action->set_sensitive (true);
3366 selection_redo_action->set_sensitive (false);
3369 if (selection_op_cmd_depth > 0) {
3370 selection_op_cmd_depth--;
3376 Editor::undo_selection_op ()
3379 selection_op_history_it++;
3381 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3382 if (n == selection_op_history_it) {
3383 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3384 selection_redo_action->set_sensitive (true);
3388 /* is there an earlier entry? */
3389 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3390 selection_undo_action->set_sensitive (false);
3396 Editor::redo_selection_op ()
3399 if (selection_op_history_it > 0) {
3400 selection_op_history_it--;
3403 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3404 if (n == selection_op_history_it) {
3405 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3406 selection_undo_action->set_sensitive (true);
3411 if (selection_op_history_it == 0) {
3412 selection_redo_action->set_sensitive (false);
3418 Editor::begin_reversible_command (string name)
3421 before.push_back (&_selection_memento->get_state ());
3422 _session->begin_reversible_command (name);
3427 Editor::begin_reversible_command (GQuark q)
3430 before.push_back (&_selection_memento->get_state ());
3431 _session->begin_reversible_command (q);
3436 Editor::abort_reversible_command ()
3439 while(!before.empty()) {
3440 delete before.front();
3443 _session->abort_reversible_command ();
3448 Editor::commit_reversible_command ()
3451 if (before.size() == 1) {
3452 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3453 redo_action->set_sensitive(false);
3454 undo_action->set_sensitive(true);
3455 begin_selection_op_history ();
3458 if (before.empty()) {
3459 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3464 _session->commit_reversible_command ();
3469 Editor::history_changed ()
3473 if (undo_action && _session) {
3474 if (_session->undo_depth() == 0) {
3475 label = S_("Command|Undo");
3477 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3479 undo_action->property_label() = label;
3482 if (redo_action && _session) {
3483 if (_session->redo_depth() == 0) {
3485 redo_action->set_sensitive (false);
3487 label = string_compose(_("Redo (%1)"), _session->next_redo());
3488 redo_action->set_sensitive (true);
3490 redo_action->property_label() = label;
3495 Editor::duplicate_range (bool with_dialog)
3499 RegionSelection rs = get_regions_from_selection_and_entered ();
3501 if ( selection->time.length() == 0 && rs.empty()) {
3507 ArdourDialog win (_("Duplicate"));
3508 Label label (_("Number of duplications:"));
3509 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3510 SpinButton spinner (adjustment, 0.0, 1);
3513 win.get_vbox()->set_spacing (12);
3514 win.get_vbox()->pack_start (hbox);
3515 hbox.set_border_width (6);
3516 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3518 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3519 place, visually. so do this by hand.
3522 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3523 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3524 spinner.grab_focus();
3530 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3531 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3532 win.set_default_response (RESPONSE_ACCEPT);
3534 spinner.grab_focus ();
3536 switch (win.run ()) {
3537 case RESPONSE_ACCEPT:
3543 times = adjustment.get_value();
3546 if ((current_mouse_mode() == MouseRange)) {
3547 if (selection->time.length()) {
3548 duplicate_selection (times);
3550 } else if (get_smart_mode()) {
3551 if (selection->time.length()) {
3552 duplicate_selection (times);
3554 duplicate_some_regions (rs, times);
3556 duplicate_some_regions (rs, times);
3561 Editor::set_edit_mode (EditMode m)
3563 Config->set_edit_mode (m);
3567 Editor::cycle_edit_mode ()
3569 switch (Config->get_edit_mode()) {
3571 Config->set_edit_mode (Ripple);
3575 Config->set_edit_mode (Lock);
3578 Config->set_edit_mode (Slide);
3584 Editor::edit_mode_selection_done ( EditMode m )
3586 Config->set_edit_mode ( m );
3590 Editor::grid_type_selection_done (GridType gridtype)
3592 RefPtr<RadioAction> ract = grid_type_action (gridtype);
3594 ract->set_active ();
3599 Editor::snap_mode_selection_done (SnapMode mode)
3601 RefPtr<RadioAction> ract = snap_mode_action (mode);
3604 ract->set_active (true);
3609 Editor::cycle_edit_point (bool with_marker)
3611 if(Profile->get_mixbus())
3612 with_marker = false;
3614 switch (_edit_point) {
3616 set_edit_point_preference (EditAtPlayhead);
3618 case EditAtPlayhead:
3620 set_edit_point_preference (EditAtSelectedMarker);
3622 set_edit_point_preference (EditAtMouse);
3625 case EditAtSelectedMarker:
3626 set_edit_point_preference (EditAtMouse);
3632 Editor::edit_point_selection_done (EditPoint ep)
3634 set_edit_point_preference ( ep );
3638 Editor::build_zoom_focus_menu ()
3640 using namespace Menu_Helpers;
3642 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3643 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3644 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3645 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3646 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3647 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3649 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3653 Editor::zoom_focus_selection_done ( ZoomFocus f )
3655 RefPtr<RadioAction> ract = zoom_focus_action (f);
3657 ract->set_active ();
3662 Editor::build_track_count_menu ()
3664 using namespace Menu_Helpers;
3666 if (!Profile->get_mixbus()) {
3667 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3668 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3669 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3670 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3671 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3672 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3673 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3674 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3675 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3676 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3677 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3678 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3679 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3681 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3682 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3683 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3684 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3685 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3686 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3687 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3688 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3689 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3690 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3692 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3693 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3694 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3695 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3696 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3697 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3698 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3699 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3700 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3701 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3702 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Extents"), sigc::mem_fun(*this, &Editor::temporal_zoom_extents)));
3703 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), Horizontal)));
3708 Editor::set_zoom_preset (int64_t ms)
3711 temporal_zoom_session();
3715 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3716 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3720 Editor::set_visible_track_count (int32_t n)
3722 _visible_track_count = n;
3724 /* if the canvas hasn't really been allocated any size yet, just
3725 record the desired number of visible tracks and return. when canvas
3726 allocation happens, we will get called again and then we can do the
3730 if (_visible_canvas_height <= 1) {
3736 DisplaySuspender ds;
3738 if (_visible_track_count > 0) {
3739 h = trackviews_height() / _visible_track_count;
3740 std::ostringstream s;
3741 s << _visible_track_count;
3743 } else if (_visible_track_count == 0) {
3745 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
3746 if ((*i)->marked_for_display()) {
3748 TimeAxisView::Children cl ((*i)->get_child_list ());
3749 for (TimeAxisView::Children::const_iterator j = cl.begin(); j != cl.end(); ++j) {
3750 if ((*j)->marked_for_display()) {
3757 visible_tracks_selector.set_text (X_("*"));
3760 h = trackviews_height() / n;
3763 /* negative value means that the visible track count has
3764 been overridden by explicit track height changes.
3766 visible_tracks_selector.set_text (X_("*"));
3770 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3771 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3774 if (str != visible_tracks_selector.get_text()) {
3775 visible_tracks_selector.set_text (str);
3780 Editor::override_visible_track_count ()
3782 _visible_track_count = -1;
3783 visible_tracks_selector.set_text ( _("*") );
3787 Editor::edit_controls_button_release (GdkEventButton* ev)
3789 if (Keyboard::is_context_menu_event (ev)) {
3790 ARDOUR_UI::instance()->add_route ();
3791 } else if (ev->button == 1) {
3792 selection->clear_tracks ();
3799 Editor::mouse_select_button_release (GdkEventButton* ev)
3801 /* this handles just right-clicks */
3803 if (ev->button != 3) {
3811 Editor::set_zoom_focus (ZoomFocus f)
3813 string str = zoom_focus_strings[(int)f];
3815 if (str != zoom_focus_selector.get_text()) {
3816 zoom_focus_selector.set_text (str);
3819 if (zoom_focus != f) {
3826 Editor::cycle_zoom_focus ()
3828 switch (zoom_focus) {
3830 set_zoom_focus (ZoomFocusRight);
3832 case ZoomFocusRight:
3833 set_zoom_focus (ZoomFocusCenter);
3835 case ZoomFocusCenter:
3836 set_zoom_focus (ZoomFocusPlayhead);
3838 case ZoomFocusPlayhead:
3839 set_zoom_focus (ZoomFocusMouse);
3841 case ZoomFocusMouse:
3842 set_zoom_focus (ZoomFocusEdit);
3845 set_zoom_focus (ZoomFocusLeft);
3851 Editor::update_grid ()
3853 if ( grid_musical() ) {
3854 std::vector<TempoMap::BBTPoint> grid;
3855 if (bbt_ruler_scale != bbt_show_many) {
3856 compute_current_bbt_points (grid, _leftmost_sample, _leftmost_sample + current_page_samples());
3858 maybe_draw_grid_lines ();
3859 } else if ( grid_nonmusical() ) {
3860 maybe_draw_grid_lines ();
3867 Editor::toggle_follow_playhead ()
3869 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3871 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3872 set_follow_playhead (tact->get_active());
3876 /** @param yn true to follow playhead, otherwise false.
3877 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3880 Editor::set_follow_playhead (bool yn, bool catch_up)
3882 if (_follow_playhead != yn) {
3883 if ((_follow_playhead = yn) == true && catch_up) {
3885 reset_x_origin_to_follow_playhead ();
3892 Editor::toggle_stationary_playhead ()
3894 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3896 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3897 set_stationary_playhead (tact->get_active());
3902 Editor::set_stationary_playhead (bool yn)
3904 if (_stationary_playhead != yn) {
3905 if ((_stationary_playhead = yn) == true) {
3907 // FIXME need a 3.0 equivalent of this 2.X call
3908 // update_current_screen ();
3915 Editor::playlist_selector () const
3917 return *_playlist_selector;
3921 Editor::get_paste_offset (samplepos_t pos, unsigned paste_count, samplecnt_t duration)
3923 if (paste_count == 0) {
3924 /* don't bother calculating an offset that will be zero anyway */
3928 /* calculate basic unsnapped multi-paste offset */
3929 samplecnt_t offset = paste_count * duration;
3931 /* snap offset so pos + offset is aligned to the grid */
3932 MusicSample offset_pos (pos + offset, 0);
3933 snap_to(offset_pos, RoundUpMaybe);
3934 offset = offset_pos.sample - pos;
3940 Editor::get_grid_beat_divisions(samplepos_t position)
3942 switch (_grid_type) {
3943 case GridTypeBeatDiv32: return 32;
3944 case GridTypeBeatDiv28: return 28;
3945 case GridTypeBeatDiv24: return 24;
3946 case GridTypeBeatDiv20: return 20;
3947 case GridTypeBeatDiv16: return 16;
3948 case GridTypeBeatDiv14: return 14;
3949 case GridTypeBeatDiv12: return 12;
3950 case GridTypeBeatDiv10: return 10;
3951 case GridTypeBeatDiv8: return 8;
3952 case GridTypeBeatDiv7: return 7;
3953 case GridTypeBeatDiv6: return 6;
3954 case GridTypeBeatDiv5: return 5;
3955 case GridTypeBeatDiv4: return 4;
3956 case GridTypeBeatDiv3: return 3;
3957 case GridTypeBeatDiv2: return 2;
3959 case GridTypeNone: return 0;
3960 case GridTypeSmpte: return 0;
3961 case GridTypeMinSec: return 0;
3962 case GridTypeSamples: return 0;
3968 /** returns the current musical grid divisiions using the supplied modifier mask from a GtkEvent.
3969 if the grid is non-musical, returns 0.
3970 if the grid is snapped to bars, returns -1.
3971 @param event_state the current keyboard modifier mask.
3974 Editor::get_grid_music_divisions (uint32_t event_state)
3976 if (snap_mode() == SnapOff && !ArdourKeyboard::indicates_snap (event_state)) {
3980 if (snap_mode() != SnapOff && ArdourKeyboard::indicates_snap (event_state)) {
3984 switch (_grid_type) {
3985 case GridTypeBeatDiv32: return 32;
3986 case GridTypeBeatDiv28: return 28;
3987 case GridTypeBeatDiv24: return 24;
3988 case GridTypeBeatDiv20: return 20;
3989 case GridTypeBeatDiv16: return 16;
3990 case GridTypeBeatDiv14: return 14;
3991 case GridTypeBeatDiv12: return 12;
3992 case GridTypeBeatDiv10: return 10;
3993 case GridTypeBeatDiv8: return 8;
3994 case GridTypeBeatDiv7: return 7;
3995 case GridTypeBeatDiv6: return 6;
3996 case GridTypeBeatDiv5: return 5;
3997 case GridTypeBeatDiv4: return 4;
3998 case GridTypeBeatDiv3: return 3;
3999 case GridTypeBeatDiv2: return 2;
4000 case GridTypeBeat: return 1;
4001 case GridTypeBar : return -1;
4003 case GridTypeNone: return 0;
4004 case GridTypeSmpte: return 0;
4005 case GridTypeMinSec: return 0;
4006 case GridTypeSamples: return 0;
4012 Editor::get_grid_type_as_beats (bool& success, samplepos_t position)
4016 const unsigned divisions = get_grid_beat_divisions(position);
4018 return Temporal::Beats(1.0 / (double)get_grid_beat_divisions(position));
4021 switch (_grid_type) {
4023 return Temporal::Beats(4.0 / _session->tempo_map().meter_at_sample (position).note_divisor());
4026 const Meter& m = _session->tempo_map().meter_at_sample (position);
4027 return Temporal::Beats((4.0 * m.divisions_per_bar()) / m.note_divisor());
4035 return Temporal::Beats();
4039 Editor::get_nudge_distance (samplepos_t pos, samplecnt_t& next)
4043 ret = nudge_clock->current_duration (pos);
4044 next = ret + 1; /* XXXX fix me */
4050 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4052 ArdourDialog dialog (_("Playlist Deletion"));
4053 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4054 "If it is kept, its audio files will not be cleaned.\n"
4055 "If it is deleted, audio files used by it alone will be cleaned."),
4058 dialog.set_position (WIN_POS_CENTER);
4059 dialog.get_vbox()->pack_start (label);
4063 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4064 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4065 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4066 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4067 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4069 // by default gtk uses the left most button
4070 keep->grab_focus ();
4072 switch (dialog.run ()) {
4074 /* keep this and all remaining ones */
4079 /* delete this and all others */
4083 case RESPONSE_ACCEPT:
4084 /* delete the playlist */
4088 case RESPONSE_REJECT:
4089 /* keep the playlist */
4101 Editor::audio_region_selection_covers (samplepos_t where)
4103 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4104 if ((*a)->region()->covers (where)) {
4113 Editor::prepare_for_cleanup ()
4115 cut_buffer->clear_regions ();
4116 cut_buffer->clear_playlists ();
4118 selection->clear_regions ();
4119 selection->clear_playlists ();
4121 _regions->suspend_redisplay ();
4125 Editor::finish_cleanup ()
4127 _regions->resume_redisplay ();
4131 Editor::transport_loop_location()
4134 return _session->locations()->auto_loop_location();
4141 Editor::transport_punch_location()
4144 return _session->locations()->auto_punch_location();
4151 Editor::control_layout_scroll (GdkEventScroll* ev)
4153 /* Just forward to the normal canvas scroll method. The coordinate
4154 systems are different but since the canvas is always larger than the
4155 track headers, and aligned with the trackview area, this will work.
4157 In the not too distant future this layout is going away anyway and
4158 headers will be on the canvas.
4160 return canvas_scroll_event (ev, false);
4164 Editor::session_state_saved (string)
4167 _snapshots->redisplay ();
4171 Editor::maximise_editing_space ()
4177 Gtk::Window* toplevel = current_toplevel();
4180 toplevel->fullscreen ();
4186 Editor::restore_editing_space ()
4192 Gtk::Window* toplevel = current_toplevel();
4195 toplevel->unfullscreen();
4201 * Make new playlists for a given track and also any others that belong
4202 * to the same active route group with the `select' property.
4207 Editor::new_playlists (TimeAxisView* v)
4209 begin_reversible_command (_("new playlists"));
4210 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4211 _session->playlists->get (playlists);
4212 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
4213 commit_reversible_command ();
4217 * Use a copy of the current playlist for a given track and also any others that belong
4218 * to the same active route group with the `select' property.
4223 Editor::copy_playlists (TimeAxisView* v)
4225 begin_reversible_command (_("copy playlists"));
4226 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4227 _session->playlists->get (playlists);
4228 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
4229 commit_reversible_command ();
4232 /** Clear the current playlist for a given track and also any others that belong
4233 * to the same active route group with the `select' property.
4238 Editor::clear_playlists (TimeAxisView* v)
4240 begin_reversible_command (_("clear playlists"));
4241 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4242 _session->playlists->get (playlists);
4243 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::group_select.property_id);
4244 commit_reversible_command ();
4248 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4250 atv.use_new_playlist (sz > 1 ? false : true, playlists, false);
4254 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4256 atv.use_new_playlist (sz > 1 ? false : true, playlists, true);
4260 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4262 atv.clear_playlist ();
4266 Editor::get_y_origin () const
4268 return vertical_adjustment.get_value ();
4271 /** Queue up a change to the viewport x origin.
4272 * @param sample New x origin.
4275 Editor::reset_x_origin (samplepos_t sample)
4277 pending_visual_change.add (VisualChange::TimeOrigin);
4278 pending_visual_change.time_origin = sample;
4279 ensure_visual_change_idle_handler ();
4283 Editor::reset_y_origin (double y)
4285 pending_visual_change.add (VisualChange::YOrigin);
4286 pending_visual_change.y_origin = y;
4287 ensure_visual_change_idle_handler ();
4291 Editor::reset_zoom (samplecnt_t spp)
4293 if (spp == samples_per_pixel) {
4297 pending_visual_change.add (VisualChange::ZoomLevel);
4298 pending_visual_change.samples_per_pixel = spp;
4299 ensure_visual_change_idle_handler ();
4303 Editor::reposition_and_zoom (samplepos_t sample, double fpu)
4305 reset_x_origin (sample);
4308 if (!no_save_visual) {
4309 undo_visual_stack.push_back (current_visual_state(false));
4313 Editor::VisualState::VisualState (bool with_tracks)
4314 : gui_state (with_tracks ? new GUIObjectState : 0)
4318 Editor::VisualState::~VisualState ()
4323 Editor::VisualState*
4324 Editor::current_visual_state (bool with_tracks)
4326 VisualState* vs = new VisualState (with_tracks);
4327 vs->y_position = vertical_adjustment.get_value();
4328 vs->samples_per_pixel = samples_per_pixel;
4329 vs->_leftmost_sample = _leftmost_sample;
4330 vs->zoom_focus = zoom_focus;
4333 vs->gui_state->set_state (ARDOUR_UI::instance()->gui_object_state->get_state());
4340 Editor::undo_visual_state ()
4342 if (undo_visual_stack.empty()) {
4346 VisualState* vs = undo_visual_stack.back();
4347 undo_visual_stack.pop_back();
4350 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4353 use_visual_state (*vs);
4358 Editor::redo_visual_state ()
4360 if (redo_visual_stack.empty()) {
4364 VisualState* vs = redo_visual_stack.back();
4365 redo_visual_stack.pop_back();
4367 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4368 // why do we check here?
4369 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4372 use_visual_state (*vs);
4377 Editor::swap_visual_state ()
4379 if (undo_visual_stack.empty()) {
4380 redo_visual_state ();
4382 undo_visual_state ();
4387 Editor::use_visual_state (VisualState& vs)
4389 PBD::Unwinder<bool> nsv (no_save_visual, true);
4390 DisplaySuspender ds;
4392 vertical_adjustment.set_value (vs.y_position);
4394 set_zoom_focus (vs.zoom_focus);
4395 reposition_and_zoom (vs._leftmost_sample, vs.samples_per_pixel);
4398 ARDOUR_UI::instance()->gui_object_state->set_state (vs.gui_state->get_state());
4400 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4401 (*i)->clear_property_cache();
4402 (*i)->reset_visual_state ();
4406 _routes->update_visibility ();
4409 /** This is the core function that controls the zoom level of the canvas. It is called
4410 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4411 * @param spp new number of samples per pixel
4414 Editor::set_samples_per_pixel (samplecnt_t spp)
4420 const samplecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->sample_rate() : 48000);
4421 const samplecnt_t lots_of_pixels = 4000;
4423 /* if the zoom level is greater than what you'd get trying to display 3
4424 * days of audio on a really big screen, then it's too big.
4427 if (spp * lots_of_pixels > three_days) {
4431 samples_per_pixel = spp;
4435 Editor::on_samples_per_pixel_changed ()
4437 bool const showing_time_selection = selection->time.length() > 0;
4439 if (showing_time_selection && selection->time.start () != selection->time.end_sample ()) {
4440 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4441 (*i)->reshow_selection (selection->time);
4445 ZoomChanged (); /* EMIT_SIGNAL */
4447 ArdourCanvas::GtkCanvasViewport* c;
4449 c = get_track_canvas();
4451 c->canvas()->zoomed ();
4454 if (playhead_cursor) {
4455 playhead_cursor->set_position (playhead_cursor->current_sample ());
4458 refresh_location_display();
4459 _summary->set_overlays_dirty ();
4461 update_marker_labels ();
4467 Editor::playhead_cursor_sample () const
4469 return playhead_cursor->current_sample();
4473 Editor::queue_visual_videotimeline_update ()
4475 pending_visual_change.add (VisualChange::VideoTimeline);
4476 ensure_visual_change_idle_handler ();
4480 Editor::ensure_visual_change_idle_handler ()
4482 if (pending_visual_change.idle_handler_id < 0) {
4483 // see comment in add_to_idle_resize above.
4484 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4485 pending_visual_change.being_handled = false;
4490 Editor::_idle_visual_changer (void* arg)
4492 return static_cast<Editor*>(arg)->idle_visual_changer ();
4496 Editor::pre_render ()
4498 visual_change_queued = false;
4500 if (pending_visual_change.pending != 0) {
4501 ensure_visual_change_idle_handler();
4506 Editor::idle_visual_changer ()
4508 pending_visual_change.idle_handler_id = -1;
4510 if (pending_visual_change.pending == 0) {
4514 /* set_horizontal_position() below (and maybe other calls) call
4515 gtk_main_iteration(), so it's possible that a signal will be handled
4516 half-way through this method. If this signal wants an
4517 idle_visual_changer we must schedule another one after this one, so
4518 mark the idle_handler_id as -1 here to allow that. Also make a note
4519 that we are doing the visual change, so that changes in response to
4520 super-rapid-screen-update can be dropped if we are still processing
4524 if (visual_change_queued) {
4528 pending_visual_change.being_handled = true;
4530 VisualChange vc = pending_visual_change;
4532 pending_visual_change.pending = (VisualChange::Type) 0;
4534 visual_changer (vc);
4536 pending_visual_change.being_handled = false;
4538 visual_change_queued = true;
4540 return 0; /* this is always a one-shot call */
4544 Editor::visual_changer (const VisualChange& vc)
4547 * Changed first so the correct horizontal canvas position is calculated in
4548 * Editor::set_horizontal_position
4550 if (vc.pending & VisualChange::ZoomLevel) {
4551 set_samples_per_pixel (vc.samples_per_pixel);
4554 if (vc.pending & VisualChange::TimeOrigin) {
4555 double new_time_origin = sample_to_pixel_unrounded (vc.time_origin);
4556 set_horizontal_position (new_time_origin);
4559 if (vc.pending & VisualChange::YOrigin) {
4560 vertical_adjustment.set_value (vc.y_origin);
4564 * Now the canvas is in the final state before render the canvas items that
4565 * support the Item::prepare_for_render interface can calculate the correct
4566 * item to visible canvas intersection.
4568 if (vc.pending & VisualChange::ZoomLevel) {
4569 on_samples_per_pixel_changed ();
4571 compute_fixed_ruler_scale ();
4573 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4574 update_tempo_based_rulers ();
4577 if (!(vc.pending & VisualChange::ZoomLevel)) {
4579 * If the canvas is not being zoomed then the canvas items will not change
4580 * and cause Item::prepare_for_render to be called so do it here manually.
4582 * Not ideal, but I can't think of a better solution atm.
4584 _track_canvas->prepare_for_render();
4587 // If we are only scrolling vertically there is no need to update these
4588 if (vc.pending != VisualChange::YOrigin) {
4589 update_fixed_rulers ();
4590 redisplay_grid (true);
4592 /* video frames & position need to be updated for zoom, horiz-scroll
4593 * and (explicitly) VisualChange::VideoTimeline.
4595 update_video_timeline();
4598 _summary->set_overlays_dirty ();
4601 struct EditorOrderTimeAxisSorter {
4602 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4603 return a->order () < b->order ();
4608 Editor::sort_track_selection (TrackViewList& sel)
4610 EditorOrderTimeAxisSorter cmp;
4615 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4618 samplepos_t where = 0;
4619 EditPoint ep = _edit_point;
4621 if (Profile->get_mixbus()) {
4622 if (ep == EditAtSelectedMarker) {
4623 ep = EditAtPlayhead;
4627 if (from_outside_canvas && (ep == EditAtMouse)) {
4628 ep = EditAtPlayhead;
4629 } else if (from_context_menu && (ep == EditAtMouse)) {
4630 return canvas_event_sample (&context_click_event, 0, 0);
4633 if (entered_marker) {
4634 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4635 return entered_marker->position();
4638 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4639 ep = EditAtSelectedMarker;
4642 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4643 ep = EditAtPlayhead;
4646 MusicSample snap_mf (0, 0);
4649 case EditAtPlayhead:
4650 if (_dragging_playhead && _control_scroll_target) {
4651 where = *_control_scroll_target;
4653 where = _session->audible_sample();
4655 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4658 case EditAtSelectedMarker:
4659 if (!selection->markers.empty()) {
4661 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4664 where = loc->start();
4668 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4676 if (!mouse_sample (where, ignored)) {
4677 /* XXX not right but what can we do ? */
4680 snap_mf.sample = where;
4682 where = snap_mf.sample;
4683 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4691 Editor::set_loop_range (samplepos_t start, samplepos_t end, string cmd)
4693 if (!_session) return;
4695 begin_reversible_command (cmd);
4699 if ((tll = transport_loop_location()) == 0) {
4700 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop, get_grid_music_divisions(0));
4701 XMLNode &before = _session->locations()->get_state();
4702 _session->locations()->add (loc, true);
4703 _session->set_auto_loop_location (loc);
4704 XMLNode &after = _session->locations()->get_state();
4705 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4707 XMLNode &before = tll->get_state();
4708 tll->set_hidden (false, this);
4709 tll->set (start, end);
4710 XMLNode &after = tll->get_state();
4711 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4714 commit_reversible_command ();
4718 Editor::set_punch_range (samplepos_t start, samplepos_t end, string cmd)
4720 if (!_session) return;
4722 begin_reversible_command (cmd);
4726 if ((tpl = transport_punch_location()) == 0) {
4727 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch, get_grid_music_divisions(0));
4728 XMLNode &before = _session->locations()->get_state();
4729 _session->locations()->add (loc, true);
4730 _session->set_auto_punch_location (loc);
4731 XMLNode &after = _session->locations()->get_state();
4732 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4734 XMLNode &before = tpl->get_state();
4735 tpl->set_hidden (false, this);
4736 tpl->set (start, end);
4737 XMLNode &after = tpl->get_state();
4738 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4741 commit_reversible_command ();
4744 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4745 * @param rs List to which found regions are added.
4746 * @param where Time to look at.
4747 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4750 Editor::get_regions_at (RegionSelection& rs, samplepos_t where, const TrackViewList& ts) const
4752 const TrackViewList* tracks;
4755 tracks = &track_views;
4760 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4762 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4765 boost::shared_ptr<Track> tr;
4766 boost::shared_ptr<Playlist> pl;
4768 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4770 boost::shared_ptr<RegionList> regions = pl->regions_at (where);
4772 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4773 RegionView* rv = rtv->view()->find_view (*i);
4784 Editor::get_regions_after (RegionSelection& rs, samplepos_t where, const TrackViewList& ts) const
4786 const TrackViewList* tracks;
4789 tracks = &track_views;
4794 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4795 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4797 boost::shared_ptr<Track> tr;
4798 boost::shared_ptr<Playlist> pl;
4800 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4802 boost::shared_ptr<RegionList> regions = pl->regions_touched (where, max_samplepos);
4804 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4806 RegionView* rv = rtv->view()->find_view (*i);
4817 /** Get regions using the following method:
4819 * Make a region list using:
4820 * (a) any selected regions
4821 * (b) the intersection of any selected tracks and the edit point(*)
4822 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4824 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4826 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4830 Editor::get_regions_from_selection_and_edit_point (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4832 RegionSelection regions;
4834 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4835 regions.add (entered_regionview);
4837 regions = selection->regions;
4840 if ( regions.empty() ) {
4841 TrackViewList tracks = selection->tracks;
4843 if (!tracks.empty()) {
4844 /* no region selected or entered, but some selected tracks:
4845 * act on all regions on the selected tracks at the edit point
4847 samplepos_t const where = get_preferred_edit_position (ignore, from_context_menu, from_outside_canvas);
4848 get_regions_at(regions, where, tracks);
4855 /** Get regions using the following method:
4857 * Make a region list using:
4858 * (a) any selected regions
4859 * (b) the intersection of any selected tracks and the edit point(*)
4860 * (c) if neither exists, then whatever region is under the mouse
4862 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4864 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4867 Editor::get_regions_from_selection_and_mouse (samplepos_t pos)
4869 RegionSelection regions;
4871 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4872 regions.add (entered_regionview);
4874 regions = selection->regions;
4877 if ( regions.empty() ) {
4878 TrackViewList tracks = selection->tracks;
4880 if (!tracks.empty()) {
4881 /* no region selected or entered, but some selected tracks:
4882 * act on all regions on the selected tracks at the edit point
4884 get_regions_at(regions, pos, tracks);
4891 /** Start with regions that are selected, or the entered regionview if none are selected.
4892 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4893 * of the regions that we started with.
4897 Editor::get_regions_from_selection_and_entered () const
4899 RegionSelection regions = selection->regions;
4901 if (regions.empty() && entered_regionview) {
4902 regions.add (entered_regionview);
4909 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4911 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4912 RouteTimeAxisView* rtav;
4914 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4915 boost::shared_ptr<Playlist> pl;
4916 std::vector<boost::shared_ptr<Region> > results;
4917 boost::shared_ptr<Track> tr;
4919 if ((tr = rtav->track()) == 0) {
4924 if ((pl = (tr->playlist())) != 0) {
4925 boost::shared_ptr<Region> r = pl->region_by_id (id);
4927 RegionView* rv = rtav->view()->find_view (r);
4929 regions.push_back (rv);
4938 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Temporal::Beats> > > > > &selection) const
4941 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4942 MidiTimeAxisView* mtav;
4944 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4946 mtav->get_per_region_note_selection (selection);
4953 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4955 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4957 RouteTimeAxisView* tatv;
4959 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4961 boost::shared_ptr<Playlist> pl;
4962 vector<boost::shared_ptr<Region> > results;
4964 boost::shared_ptr<Track> tr;
4966 if ((tr = tatv->track()) == 0) {
4971 if ((pl = (tr->playlist())) != 0) {
4972 if (src_comparison) {
4973 pl->get_source_equivalent_regions (region, results);
4975 pl->get_region_list_equivalent_regions (region, results);
4979 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4980 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4981 regions.push_back (marv);
4990 Editor::regionview_from_region (boost::shared_ptr<Region> region) const
4992 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4993 RouteTimeAxisView* tatv;
4994 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4995 if (!tatv->track()) {
4998 RegionView* marv = tatv->view()->find_view (region);
5008 Editor::rtav_from_route (boost::shared_ptr<Route> route) const
5010 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5011 RouteTimeAxisView* rtav;
5012 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
5013 if (rtav->route() == route) {
5022 Editor::show_rhythm_ferret ()
5024 if (rhythm_ferret == 0) {
5025 rhythm_ferret = new RhythmFerret(*this);
5028 rhythm_ferret->set_session (_session);
5029 rhythm_ferret->show ();
5030 rhythm_ferret->present ();
5034 Editor::first_idle ()
5036 MessageDialog* dialog = 0;
5038 if (track_views.size() > 1) {
5039 Timers::TimerSuspender t;
5040 dialog = new MessageDialog (
5041 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5045 ARDOUR_UI::instance()->flush_pending (60);
5048 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5052 /* now that all regionviews should exist, setup region selection */
5056 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5057 /* this is cumulative: rs is NOT cleared each time */
5058 get_regionviews_by_id (*pr, rs);
5061 selection->set (rs);
5063 // first idle adds route children (automation tracks), so we need to redisplay here
5064 _routes->redisplay ();
5068 if (_session->undo_depth() == 0) {
5069 undo_action->set_sensitive(false);
5071 redo_action->set_sensitive(false);
5072 begin_selection_op_history ();
5078 Editor::_idle_resize (gpointer arg)
5080 return ((Editor*)arg)->idle_resize ();
5084 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5086 if (resize_idle_id < 0) {
5087 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5088 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5089 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5091 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5092 _pending_resize_amount = 0;
5095 /* make a note of the smallest resulting height, so that we can clamp the
5096 lower limit at TimeAxisView::hSmall */
5098 int32_t min_resulting = INT32_MAX;
5100 _pending_resize_amount += h;
5101 _pending_resize_view = view;
5103 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5105 if (selection->tracks.contains (_pending_resize_view)) {
5106 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5107 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5111 if (min_resulting < 0) {
5116 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5117 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5121 /** Handle pending resizing of tracks */
5123 Editor::idle_resize ()
5125 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5127 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5128 selection->tracks.contains (_pending_resize_view)) {
5130 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5131 if (*i != _pending_resize_view) {
5132 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5137 _pending_resize_amount = 0;
5138 _group_tabs->set_dirty ();
5139 resize_idle_id = -1;
5147 ENSURE_GUI_THREAD (*this, &Editor::located);
5150 playhead_cursor->set_position (_session->audible_sample ());
5151 if (_follow_playhead && !_pending_initial_locate) {
5152 reset_x_origin_to_follow_playhead ();
5156 _pending_locate_request = false;
5157 _pending_initial_locate = false;
5158 _last_update_time = 0;
5162 Editor::region_view_added (RegionView * rv)
5164 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5166 list<pair<PBD::ID const, list<Evoral::event_id_t> > >::iterator rnote;
5167 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5168 if (rv->region()->id () == (*rnote).first) {
5169 mrv->select_notes ((*rnote).second);
5170 selection->pending_midi_note_selection.erase(rnote);
5176 _summary->set_background_dirty ();
5178 mark_region_boundary_cache_dirty ();
5182 Editor::region_view_removed ()
5184 _summary->set_background_dirty ();
5186 mark_region_boundary_cache_dirty ();
5190 Editor::axis_view_by_stripable (boost::shared_ptr<Stripable> s) const
5192 for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
5193 if ((*j)->stripable() == s) {
5202 Editor::axis_view_by_control (boost::shared_ptr<AutomationControl> c) const
5204 for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
5205 if ((*j)->control() == c) {
5209 TimeAxisView::Children kids = (*j)->get_child_list ();
5211 for (TimeAxisView::Children::iterator k = kids.begin(); k != kids.end(); ++k) {
5212 if ((*k)->control() == c) {
5222 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5226 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5227 TimeAxisView* tv = time_axis_view_from_stripable (*i);
5237 Editor::suspend_route_redisplay ()
5240 _routes->suspend_redisplay();
5245 Editor::resume_route_redisplay ()
5248 _routes->redisplay(); // queue redisplay
5249 _routes->resume_redisplay();
5254 Editor::add_vcas (VCAList& vlist)
5258 for (VCAList::iterator v = vlist.begin(); v != vlist.end(); ++v) {
5259 sl.push_back (boost::dynamic_pointer_cast<Stripable> (*v));
5262 add_stripables (sl);
5266 Editor::add_routes (RouteList& rlist)
5270 for (RouteList::iterator r = rlist.begin(); r != rlist.end(); ++r) {
5274 add_stripables (sl);
5278 Editor::add_stripables (StripableList& sl)
5280 list<TimeAxisView*> new_views;
5281 boost::shared_ptr<VCA> v;
5282 boost::shared_ptr<Route> r;
5283 TrackViewList new_selection;
5284 bool from_scratch = (track_views.size() == 0);
5286 sl.sort (Stripable::Sorter());
5288 for (StripableList::iterator s = sl.begin(); s != sl.end(); ++s) {
5290 if ((v = boost::dynamic_pointer_cast<VCA> (*s)) != 0) {
5292 VCATimeAxisView* vtv = new VCATimeAxisView (*this, _session, *_track_canvas);
5294 new_views.push_back (vtv);
5296 } else if ((r = boost::dynamic_pointer_cast<Route> (*s)) != 0) {
5298 if (r->is_auditioner() || r->is_monitor()) {
5302 RouteTimeAxisView* rtv;
5303 DataType dt = r->input()->default_type();
5305 if (dt == ARDOUR::DataType::AUDIO) {
5306 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5308 } else if (dt == ARDOUR::DataType::MIDI) {
5309 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5312 throw unknown_type();
5315 new_views.push_back (rtv);
5316 track_views.push_back (rtv);
5317 new_selection.push_back (rtv);
5319 rtv->effective_gain_display ();
5321 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5322 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5326 if (new_views.size() > 0) {
5327 _routes->time_axis_views_added (new_views);
5328 //_summary->routes_added (new_selection); /* XXX requires RouteTimeAxisViewList */
5331 /* note: !new_selection.empty() means that we got some routes rather
5335 if (!from_scratch && !new_selection.empty()) {
5336 selection->set (new_selection);
5337 begin_selection_op_history();
5340 if (show_editor_mixer_when_tracks_arrive && !new_selection.empty()) {
5341 show_editor_mixer (true);
5344 editor_list_button.set_sensitive (true);
5348 Editor::timeaxisview_deleted (TimeAxisView *tv)
5350 if (tv == entered_track) {
5354 if (_session && _session->deletion_in_progress()) {
5355 /* the situation is under control */
5359 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5361 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5363 _routes->route_removed (tv);
5365 TimeAxisView::Children c = tv->get_child_list ();
5366 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5367 if (entered_track == i->get()) {
5372 /* remove it from the list of track views */
5374 TrackViewList::iterator i;
5376 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5377 i = track_views.erase (i);
5380 /* update whatever the current mixer strip is displaying, if revelant */
5382 boost::shared_ptr<Route> route;
5385 route = rtav->route ();
5388 if (current_mixer_strip && current_mixer_strip->route() == route) {
5390 TimeAxisView* next_tv;
5392 if (track_views.empty()) {
5394 } else if (i == track_views.end()) {
5395 next_tv = track_views.front();
5400 // skip VCAs (cannot be selected, n/a in editor-mixer)
5401 if (dynamic_cast<VCATimeAxisView*> (next_tv)) {
5402 /* VCAs are sorted last in line -- route_sorter.h, jump to top */
5403 next_tv = track_views.front();
5405 if (dynamic_cast<VCATimeAxisView*> (next_tv)) {
5406 /* just in case: no master, only a VCA remains */
5412 set_selected_mixer_strip (*next_tv);
5414 /* make the editor mixer strip go away setting the
5415 * button to inactive (which also unticks the menu option)
5418 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5424 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5430 DisplaySuspender ds;
5431 PresentationInfo::ChangeSuspender cs;
5433 if (apply_to_selection) {
5434 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5436 TrackSelection::iterator j = i;
5439 hide_track_in_display (*i, false);
5444 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5446 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5447 // this will hide the mixer strip
5448 set_selected_mixer_strip (*tv);
5451 _routes->hide_track_in_display (*tv);
5456 Editor::show_track_in_display (TimeAxisView* tv, bool move_into_view)
5461 _routes->show_track_in_display (*tv);
5462 if (move_into_view) {
5463 ensure_time_axis_view_is_visible (*tv, false);
5468 Editor::sync_track_view_list_and_routes ()
5470 track_views = TrackViewList (_routes->views ());
5472 _summary->set_background_dirty();
5473 _group_tabs->set_dirty ();
5475 return false; // do not call again (until needed)
5479 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5481 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5486 /** Find a StripableTimeAxisView by the ID of its stripable */
5487 StripableTimeAxisView*
5488 Editor::get_stripable_time_axis_by_id (const PBD::ID& id) const
5490 StripableTimeAxisView* v;
5492 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5493 if((v = dynamic_cast<StripableTimeAxisView*>(*i)) != 0) {
5494 if(v->stripable()->id() == id) {
5504 Editor::fit_route_group (RouteGroup *g)
5506 TrackViewList ts = axis_views_from_routes (g->route_list ());
5511 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5513 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5516 _session->cancel_audition ();
5520 if (_session->is_auditioning()) {
5521 _session->cancel_audition ();
5522 if (r == last_audition_region) {
5527 _session->audition_region (r);
5528 last_audition_region = r;
5533 Editor::hide_a_region (boost::shared_ptr<Region> r)
5535 r->set_hidden (true);
5539 Editor::show_a_region (boost::shared_ptr<Region> r)
5541 r->set_hidden (false);
5545 Editor::audition_region_from_region_list ()
5547 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5551 Editor::hide_region_from_region_list ()
5553 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5557 Editor::show_region_in_region_list ()
5559 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5563 Editor::step_edit_status_change (bool yn)
5566 start_step_editing ();
5568 stop_step_editing ();
5573 Editor::start_step_editing ()
5575 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5579 Editor::stop_step_editing ()
5581 step_edit_connection.disconnect ();
5585 Editor::check_step_edit ()
5587 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5588 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5590 mtv->check_step_edit ();
5594 return true; // do it again, till we stop
5598 Editor::scroll_press (Direction dir)
5600 ++_scroll_callbacks;
5602 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5603 /* delay the first auto-repeat */
5609 scroll_backward (1);
5617 scroll_up_one_track ();
5621 scroll_down_one_track ();
5625 /* do hacky auto-repeat */
5626 if (!_scroll_connection.connected ()) {
5628 _scroll_connection = Glib::signal_timeout().connect (
5629 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5632 _scroll_callbacks = 0;
5639 Editor::scroll_release ()
5641 _scroll_connection.disconnect ();
5644 /** Queue a change for the Editor viewport x origin to follow the playhead */
5646 Editor::reset_x_origin_to_follow_playhead ()
5648 samplepos_t const sample = playhead_cursor->current_sample ();
5650 if (sample < _leftmost_sample || sample > _leftmost_sample + current_page_samples()) {
5652 if (_session->transport_speed() < 0) {
5654 if (sample > (current_page_samples() / 2)) {
5655 center_screen (sample-(current_page_samples()/2));
5657 center_screen (current_page_samples()/2);
5664 if (sample < _leftmost_sample) {
5666 if (_session->transport_rolling()) {
5667 /* rolling; end up with the playhead at the right of the page */
5668 l = sample - current_page_samples ();
5670 /* not rolling: end up with the playhead 1/4 of the way along the page */
5671 l = sample - current_page_samples() / 4;
5675 if (_session->transport_rolling()) {
5676 /* rolling: end up with the playhead on the left of the page */
5679 /* not rolling: end up with the playhead 3/4 of the way along the page */
5680 l = sample - 3 * current_page_samples() / 4;
5688 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5694 Editor::super_rapid_screen_update ()
5696 if (!_session || !_session->engine().running()) {
5700 /* METERING / MIXER STRIPS */
5702 /* update track meters, if required */
5703 if (contents().is_mapped() && meters_running) {
5704 RouteTimeAxisView* rtv;
5705 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5706 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5707 rtv->fast_update ();
5712 /* and any current mixer strip */
5713 if (current_mixer_strip) {
5714 current_mixer_strip->fast_update ();
5717 bool latent_locate = false;
5718 samplepos_t sample = _session->audible_sample (&latent_locate);
5719 const int64_t now = g_get_monotonic_time ();
5722 if (_session->exporting ()) {
5723 /* freewheel/export may be faster or slower than transport_speed() / SR.
5724 * Also exporting multiple ranges locates/jumps without a _pending_locate_request.
5726 _last_update_time = 0;
5729 if (_last_update_time > 0) {
5730 /* interpolate and smoothen playhead position */
5731 const double ds = (now - _last_update_time) * _session->transport_speed() * _session->nominal_sample_rate () * 1e-6;
5732 samplepos_t guess = playhead_cursor->current_sample () + rint (ds);
5733 err = sample - guess;
5735 guess += err * .12 + _err_screen_engine; // time-constant based on 25fps (super_rapid_screen_update)
5736 _err_screen_engine += .0144 * (err - _err_screen_engine); // tc^2
5739 printf ("eng: %ld gui:%ld (%+6.1f) diff: %6.1f (err: %7.2f)\n",
5741 err, _err_screen_engine);
5746 _err_screen_engine = 0;
5749 if (err > 8192 || latent_locate) {
5750 // in case of x-runs or freewheeling
5751 _last_update_time = 0;
5752 sample = _session->audible_sample ();
5754 _last_update_time = now;
5757 //snapped cursor stuff ( the snapped_cursor shows where an operation is going to occur )
5759 MusicSample where (sample, 0);
5760 if ( !UIConfiguration::instance().get_show_snapped_cursor() ) {
5761 snapped_cursor->hide ();
5762 } else if ( _edit_point == EditAtPlayhead && !_dragging_playhead) {
5763 snap_to (where); // can't use snap_to_with_modifier?
5764 snapped_cursor->set_position (where.sample);
5765 snapped_cursor->show ();
5766 } else if ( _edit_point == EditAtSelectedMarker ) {
5767 //NOTE: I don't think EditAtSelectedMarker should snap. they are what they are.
5768 //however, the current editing code -does- snap so I'll draw it that way for now.
5769 MusicSample ms (selection->markers.front()->position(), 0);
5770 snap_to (ms); // should use snap_to_with_modifier?
5771 snapped_cursor->set_position ( ms.sample );
5772 snapped_cursor->show ();
5773 } else if (mouse_sample (where.sample, ignored)) { //cursor is in the editing canvas. show it.
5774 snapped_cursor->show ();
5775 } else { //mouse is out of the editing canvas. hide the snapped_cursor
5776 snapped_cursor->hide ();
5779 /* There are a few reasons why we might not update the playhead / viewport stuff:
5781 * 1. we don't update things when there's a pending locate request, otherwise
5782 * when the editor requests a locate there is a chance that this method
5783 * will move the playhead before the locate request is processed, causing
5785 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5786 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5788 if (_pending_locate_request) {
5789 _last_update_time = 0;
5793 if (_dragging_playhead) {
5794 _last_update_time = 0;
5798 if (playhead_cursor->current_sample () == sample) {
5802 playhead_cursor->set_position (sample);
5804 if (_session->requested_return_sample() >= 0) {
5805 _last_update_time = 0;
5809 if (!_follow_playhead || pending_visual_change.being_handled) {
5810 /* We only do this if we aren't already
5811 * handling a visual change (ie if
5812 * pending_visual_change.being_handled is
5813 * false) so that these requests don't stack
5814 * up there are too many of them to handle in
5820 if (!_stationary_playhead) {
5821 reset_x_origin_to_follow_playhead ();
5823 samplepos_t const sample = playhead_cursor->current_sample ();
5824 double target = ((double)sample - (double)current_page_samples() / 2.0);
5825 if (target <= 0.0) {
5828 // compare to EditorCursor::set_position()
5829 double const old_pos = sample_to_pixel_unrounded (_leftmost_sample);
5830 double const new_pos = sample_to_pixel_unrounded (target);
5831 if (rint (new_pos) != rint (old_pos)) {
5832 reset_x_origin (pixel_to_sample (new_pos));
5839 Editor::session_going_away ()
5841 _have_idled = false;
5843 _session_connections.drop_connections ();
5845 super_rapid_screen_update_connection.disconnect ();
5847 selection->clear ();
5848 cut_buffer->clear ();
5850 clicked_regionview = 0;
5851 clicked_axisview = 0;
5852 clicked_routeview = 0;
5853 entered_regionview = 0;
5855 _last_update_time = 0;
5858 playhead_cursor->hide ();
5860 /* rip everything out of the list displays */
5864 _route_groups->clear ();
5866 /* do this first so that deleting a track doesn't reset cms to null
5867 and thus cause a leak.
5870 if (current_mixer_strip) {
5871 if (current_mixer_strip->get_parent() != 0) {
5872 global_hpacker.remove (*current_mixer_strip);
5874 delete current_mixer_strip;
5875 current_mixer_strip = 0;
5878 /* delete all trackviews */
5880 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5883 track_views.clear ();
5885 nudge_clock->set_session (0);
5887 editor_list_button.set_active(false);
5888 editor_list_button.set_sensitive(false);
5890 /* clear tempo/meter rulers */
5891 remove_metric_marks ();
5892 clear_marker_display ();
5898 stop_step_editing ();
5902 /* get rid of any existing editor mixer strip */
5904 WindowTitle title(Glib::get_application_name());
5905 title += _("Editor");
5907 own_window()->set_title (title.get_string());
5910 SessionHandlePtr::session_going_away ();
5914 Editor::trigger_script (int i)
5916 LuaInstance::instance()-> call_action (i);
5920 Editor::show_editor_list (bool yn)
5923 _editor_list_vbox.show ();
5925 _editor_list_vbox.hide ();
5930 Editor::change_region_layering_order (bool from_context_menu)
5932 const samplepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5934 if (!clicked_routeview) {
5935 if (layering_order_editor) {
5936 layering_order_editor->hide ();
5941 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5947 boost::shared_ptr<Playlist> pl = track->playlist();
5953 if (layering_order_editor == 0) {
5954 layering_order_editor = new RegionLayeringOrderEditor (*this);
5957 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5958 layering_order_editor->maybe_present ();
5962 Editor::update_region_layering_order_editor ()
5964 if (layering_order_editor && layering_order_editor->is_visible ()) {
5965 change_region_layering_order (true);
5970 Editor::setup_fade_images ()
5972 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5973 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5974 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5975 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5976 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5978 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5979 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5980 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5981 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5982 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5986 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5988 Editor::action_menu_item (std::string const & name)
5990 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5993 return *manage (a->create_menu_item ());
5997 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5999 EventBox* b = manage (new EventBox);
6000 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
6001 Label* l = manage (new Label (name));
6005 _the_notebook.append_page (widget, *b);
6009 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
6011 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
6012 _the_notebook.set_current_page (_the_notebook.page_num (*page));
6015 if (ev->type == GDK_2BUTTON_PRESS) {
6017 /* double-click on a notebook tab shrinks or expands the notebook */
6019 if (_notebook_shrunk) {
6020 if (pre_notebook_shrink_pane_width) {
6021 edit_pane.set_divider (0, *pre_notebook_shrink_pane_width);
6023 _notebook_shrunk = false;
6025 pre_notebook_shrink_pane_width = edit_pane.get_divider();
6027 /* this expands the LHS of the edit pane to cover the notebook
6028 PAGE but leaves the tabs visible.
6030 edit_pane.set_divider (0, edit_pane.get_divider() + page->get_width());
6031 _notebook_shrunk = true;
6039 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
6041 using namespace Menu_Helpers;
6043 MenuList& items = _control_point_context_menu.items ();
6046 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
6047 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
6048 if (!can_remove_control_point (item)) {
6049 items.back().set_sensitive (false);
6052 _control_point_context_menu.popup (event->button.button, event->button.time);
6056 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
6058 using namespace Menu_Helpers;
6060 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
6065 /* We need to get the selection here and pass it to the operations, since
6066 popping up the menu will cause a region leave event which clears
6067 entered_regionview. */
6069 MidiRegionView& mrv = note->region_view();
6070 const RegionSelection rs = get_regions_from_selection_and_entered ();
6071 const uint32_t sel_size = mrv.selection_size ();
6073 MenuList& items = _note_context_menu.items();
6077 items.push_back(MenuElem(_("Delete"),
6078 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
6081 items.push_back(MenuElem(_("Edit..."),
6082 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
6083 if (sel_size != 1) {
6084 items.back().set_sensitive (false);
6087 items.push_back(MenuElem(_("Transpose..."),
6088 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
6091 items.push_back(MenuElem(_("Legatize"),
6092 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
6094 items.back().set_sensitive (false);
6097 items.push_back(MenuElem(_("Quantize..."),
6098 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
6100 items.push_back(MenuElem(_("Remove Overlap"),
6101 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
6103 items.back().set_sensitive (false);
6106 items.push_back(MenuElem(_("Transform..."),
6107 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
6109 _note_context_menu.popup (event->button.button, event->button.time);
6113 Editor::zoom_vertical_modifier_released()
6115 _stepping_axis_view = 0;
6119 Editor::ui_parameter_changed (string parameter)
6121 if (parameter == "icon-set") {
6122 while (!_cursor_stack.empty()) {
6123 _cursor_stack.pop_back();
6125 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
6126 _cursor_stack.push_back(_cursors->grabber);
6127 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
6128 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
6130 } else if (parameter == "draggable-playhead") {
6131 if (_verbose_cursor) {
6132 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
6138 Editor::use_own_window (bool and_fill_it)
6140 bool new_window = !own_window();
6142 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
6144 if (win && new_window) {
6145 win->set_name ("EditorWindow");
6147 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
6149 // win->signal_realize().connect (*this, &Editor::on_realize);
6150 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
6151 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
6152 win->set_data ("ardour-bindings", bindings);
6157 DisplaySuspender ds;
6158 contents().show_all ();
6160 /* XXX: this is a bit unfortunate; it would probably
6161 be nicer if we could just call show () above rather
6162 than needing the show_all ()
6165 /* re-hide stuff if necessary */
6166 editor_list_button_toggled ();
6167 parameter_changed ("show-summary");
6168 parameter_changed ("show-group-tabs");
6169 parameter_changed ("show-zoom-tools");
6171 /* now reset all audio_time_axis heights, because widgets might need
6177 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6178 tv = (static_cast<TimeAxisView*>(*i));
6179 tv->reset_height ();
6182 if (current_mixer_strip) {
6183 current_mixer_strip->hide_things ();
6184 current_mixer_strip->parameter_changed ("mixer-element-visibility");