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));
571 selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
573 editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
575 selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
576 selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
578 edit_controls_vbox.set_spacing (0);
579 vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
580 _track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
582 HBox* h = manage (new HBox);
583 _group_tabs = new EditorGroupTabs (this);
584 if (!ARDOUR::Profile->get_trx()) {
585 h->pack_start (*_group_tabs, PACK_SHRINK);
587 h->pack_start (edit_controls_vbox);
588 controls_layout.add (*h);
590 controls_layout.set_name ("EditControlsBase");
591 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK|Gdk::SCROLL_MASK);
592 controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
593 controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
595 _cursors = new MouseCursors;
596 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
597 cerr << "Set cursor set to " << UIConfiguration::instance().get_icon_set() << endl;
599 /* Push default cursor to ever-present bottom of cursor stack. */
600 push_canvas_cursor(_cursors->grabber);
602 ArdourCanvas::GtkCanvas* time_pad = manage (new ArdourCanvas::GtkCanvas ());
604 ArdourCanvas::Line* pad_line_1 = new ArdourCanvas::Line (time_pad->root());
605 pad_line_1->set (ArdourCanvas::Duple (0.0, 1.0), ArdourCanvas::Duple (100.0, 1.0));
606 pad_line_1->set_outline_color (0xFF0000FF);
612 edit_packer.set_col_spacings (0);
613 edit_packer.set_row_spacings (0);
614 edit_packer.set_homogeneous (false);
615 edit_packer.set_border_width (0);
616 edit_packer.set_name ("EditorWindow");
618 time_bars_event_box.add (time_bars_vbox);
619 time_bars_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
620 time_bars_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
622 /* labels for the time bars */
623 edit_packer.attach (time_bars_event_box, 0, 1, 0, 1, FILL, SHRINK, 0, 0);
625 edit_packer.attach (controls_layout, 0, 1, 1, 2, FILL, FILL|EXPAND, 0, 0);
627 edit_packer.attach (*_track_canvas_viewport, 1, 2, 0, 2, FILL|EXPAND, FILL|EXPAND, 0, 0);
629 bottom_hbox.set_border_width (2);
630 bottom_hbox.set_spacing (3);
632 PresentationInfo::Change.connect (*this, MISSING_INVALIDATOR, boost::bind (&Editor::presentation_info_changed, this, _1), gui_context());
634 _route_groups = new EditorRouteGroups (this);
635 _routes = new EditorRoutes (this);
636 _regions = new EditorRegions (this);
637 _snapshots = new EditorSnapshots (this);
638 _locations = new EditorLocations (this);
639 _time_info_box = new TimeInfoBox ("EditorTimeInfo", true);
641 /* these are static location signals */
643 Location::start_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
644 Location::end_changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
645 Location::changed.connect (*this, invalidator (*this), boost::bind (&Editor::location_changed, this, _1), gui_context());
647 add_notebook_page (_("Regions"), _regions->widget ());
648 add_notebook_page (_("Tracks & Busses"), _routes->widget ());
649 add_notebook_page (_("Snapshots"), _snapshots->widget ());
650 add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
651 add_notebook_page (_("Ranges & Marks"), _locations->widget ());
653 _the_notebook.set_show_tabs (true);
654 _the_notebook.set_scrollable (true);
655 _the_notebook.popup_disable ();
656 _the_notebook.set_tab_pos (Gtk::POS_RIGHT);
657 _the_notebook.show_all ();
659 _notebook_shrunk = false;
662 /* Pick up some settings we need to cache, early */
664 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
667 settings->get_property ("notebook-shrunk", _notebook_shrunk);
670 editor_summary_pane.set_check_divider_position (true);
671 editor_summary_pane.add (edit_packer);
673 Button* summary_arrow_left = manage (new Button);
674 summary_arrow_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
675 summary_arrow_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
676 summary_arrow_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
678 Button* summary_arrow_right = manage (new Button);
679 summary_arrow_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
680 summary_arrow_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
681 summary_arrow_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
683 VBox* summary_arrows_left = manage (new VBox);
684 summary_arrows_left->pack_start (*summary_arrow_left);
686 VBox* summary_arrows_right = manage (new VBox);
687 summary_arrows_right->pack_start (*summary_arrow_right);
689 Frame* summary_sample = manage (new Frame);
690 summary_sample->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
692 summary_sample->add (*_summary);
693 summary_sample->show ();
695 _summary_hbox.pack_start (*summary_arrows_left, false, false);
696 _summary_hbox.pack_start (*summary_sample, true, true);
697 _summary_hbox.pack_start (*summary_arrows_right, false, false);
699 if (!ARDOUR::Profile->get_trx()) {
700 editor_summary_pane.add (_summary_hbox);
703 edit_pane.set_check_divider_position (true);
704 edit_pane.add (editor_summary_pane);
705 if (!ARDOUR::Profile->get_trx()) {
706 _editor_list_vbox.pack_start (*_time_info_box, false, false, 0);
707 _editor_list_vbox.pack_start (_the_notebook);
708 edit_pane.add (_editor_list_vbox);
709 edit_pane.set_child_minsize (_editor_list_vbox, 30); /* rough guess at width of notebook tabs */
712 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
713 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
716 if (!settings || !settings->get_property ("edit-horizontal-pane-pos", fract) || fract > 1.0) {
717 /* initial allocation is 90% to canvas, 10% to notebook */
720 edit_pane.set_divider (0, fract);
722 if (!settings || !settings->get_property ("edit-vertical-pane-pos", fract) || fract > 1.0) {
723 /* initial allocation is 90% to canvas, 10% to summary */
726 editor_summary_pane.set_divider (0, fract);
728 global_vpacker.set_spacing (2);
729 global_vpacker.set_border_width (0);
731 //the next three EventBoxes provide the ability for their child widgets to have a background color. That is all.
733 Gtk::EventBox* ebox = manage (new Gtk::EventBox); //a themeable box
734 ebox->set_name("EditorWindow");
735 ebox->add (toolbar_hbox);
737 Gtk::EventBox* epane_box = manage (new EventBoxExt); //a themeable box
738 epane_box->set_name("EditorWindow");
739 epane_box->add (edit_pane);
741 Gtk::EventBox* epane_box2 = manage (new EventBoxExt); //a themeable box
742 epane_box2->set_name("EditorWindow");
743 epane_box2->add (global_vpacker);
745 global_vpacker.pack_start (*ebox, false, false);
746 global_vpacker.pack_start (*epane_box, true, true);
747 global_hpacker.pack_start (*epane_box2, true, true);
749 /* need to show the "contents" widget so that notebook will show if tab is switched to
752 global_hpacker.show ();
754 /* register actions now so that set_state() can find them and set toggles/checks etc */
761 _playlist_selector = new PlaylistSelector();
762 _playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
764 RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
768 nudge_forward_button.set_name ("nudge button");
769 nudge_forward_button.set_icon(ArdourIcon::NudgeRight);
771 nudge_backward_button.set_name ("nudge button");
772 nudge_backward_button.set_icon(ArdourIcon::NudgeLeft);
774 fade_context_menu.set_name ("ArdourContextMenu");
776 Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
778 /* allow external control surfaces/protocols to do various things */
780 ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
781 ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
782 ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
783 ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
784 ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
785 ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
786 ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
787 ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
788 ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
789 ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
790 ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
791 ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
792 ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
793 ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
795 ControlProtocol::AddStripableToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
796 ControlProtocol::RemoveStripableFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
797 ControlProtocol::SetStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
798 ControlProtocol::ToggleStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
799 ControlProtocol::ClearStripableSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
801 BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
805 ARDOUR_UI::instance()->Escape.connect (*this, invalidator (*this), boost::bind (&Editor::escape, this), gui_context());
807 /* problematic: has to return a value and thus cannot be x-thread */
809 Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
811 Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
812 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &Editor::ui_parameter_changed));
814 TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
816 _ignore_region_action = false;
817 _last_region_menu_was_main = false;
818 _popup_region_menu_item = 0;
820 _show_marker_lines = false;
822 /* Button bindings */
824 button_bindings = new Bindings ("editor-mouse");
826 XMLNode* node = button_settings();
828 for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
829 button_bindings->load_operation (**i);
835 /* grab current parameter state */
836 boost::function<void (string)> pc (boost::bind (&Editor::ui_parameter_changed, this, _1));
837 UIConfiguration::instance().map_parameters (pc);
839 setup_fade_images ();
841 set_grid_to (GridTypeNone);
848 delete button_bindings;
850 delete _route_groups;
851 delete _track_canvas_viewport;
854 delete _verbose_cursor;
855 delete quantize_dialog;
861 delete _playlist_selector;
862 delete _time_info_box;
867 LuaInstance::destroy_instance ();
869 for (list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
872 for (std::map<ARDOUR::FadeShape, Gtk::Image*>::const_iterator i = _xfade_in_images.begin(); i != _xfade_in_images.end (); ++i) {
875 for (std::map<ARDOUR::FadeShape, Gtk::Image*>::const_iterator i = _xfade_out_images.begin(); i != _xfade_out_images.end (); ++i) {
881 Editor::button_settings () const
883 XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
884 XMLNode* node = find_named_node (*settings, X_("Buttons"));
887 node = new XMLNode (X_("Buttons"));
894 Editor::get_smart_mode () const
896 return ((current_mouse_mode() == MouseObject) && smart_mode_action->get_active());
900 Editor::catch_vanishing_regionview (RegionView *rv)
902 /* note: the selection will take care of the vanishing
903 audioregionview by itself.
906 if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
910 if (clicked_regionview == rv) {
911 clicked_regionview = 0;
914 if (entered_regionview == rv) {
915 set_entered_regionview (0);
918 if (!_all_region_actions_sensitized) {
919 sensitize_all_region_actions (true);
924 Editor::set_entered_regionview (RegionView* rv)
926 if (rv == entered_regionview) {
930 if (entered_regionview) {
931 entered_regionview->exited ();
934 entered_regionview = rv;
936 if (entered_regionview != 0) {
937 entered_regionview->entered ();
940 if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
941 /* This RegionView entry might have changed what region actions
942 are allowed, so sensitize them all in case a key is pressed.
944 sensitize_all_region_actions (true);
949 Editor::set_entered_track (TimeAxisView* tav)
952 entered_track->exited ();
958 entered_track->entered ();
963 Editor::instant_save ()
965 if (!constructed || !ARDOUR_UI::instance()->session_loaded || no_save_instant) {
970 _session->add_instant_xml(get_state());
972 Config->add_instant_xml(get_state());
977 Editor::control_vertical_zoom_in_all ()
979 tav_zoom_smooth (false, true);
983 Editor::control_vertical_zoom_out_all ()
985 tav_zoom_smooth (true, true);
989 Editor::control_vertical_zoom_in_selected ()
991 tav_zoom_smooth (false, false);
995 Editor::control_vertical_zoom_out_selected ()
997 tav_zoom_smooth (true, false);
1001 Editor::control_view (uint32_t view)
1003 goto_visual_state (view);
1007 Editor::control_unselect ()
1009 selection->clear_tracks ();
1013 Editor::control_select (boost::shared_ptr<Stripable> s, Selection::Operation op)
1015 TimeAxisView* tav = time_axis_view_from_stripable (s);
1019 case Selection::Add:
1020 selection->add (tav);
1022 case Selection::Toggle:
1023 selection->toggle (tav);
1025 case Selection::Extend:
1027 case Selection::Set:
1028 selection->set (tav);
1032 selection->clear_tracks ();
1037 Editor::control_step_tracks_up ()
1039 scroll_tracks_up_line ();
1043 Editor::control_step_tracks_down ()
1045 scroll_tracks_down_line ();
1049 Editor::control_scroll (float fraction)
1051 ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1057 double step = fraction * current_page_samples();
1060 _control_scroll_target is an optional<T>
1062 it acts like a pointer to an samplepos_t, with
1063 a operator conversion to boolean to check
1064 that it has a value could possibly use
1065 playhead_cursor->current_sample to store the
1066 value and a boolean in the class to know
1067 when it's out of date
1070 if (!_control_scroll_target) {
1071 _control_scroll_target = _session->transport_sample();
1072 _dragging_playhead = true;
1075 if ((fraction < 0.0f) && (*_control_scroll_target <= (samplepos_t) fabs(step))) {
1076 *_control_scroll_target = 0;
1077 } else if ((fraction > 0.0f) && (max_samplepos - *_control_scroll_target < step)) {
1078 *_control_scroll_target = max_samplepos - (current_page_samples()*2); // allow room for slop in where the PH is on the screen
1080 *_control_scroll_target += (samplepos_t) trunc (step);
1083 /* move visuals, we'll catch up with it later */
1085 playhead_cursor->set_position (*_control_scroll_target);
1086 UpdateAllTransportClocks (*_control_scroll_target);
1088 if (*_control_scroll_target > (current_page_samples() / 2)) {
1089 /* try to center PH in window */
1090 reset_x_origin (*_control_scroll_target - (current_page_samples()/2));
1096 Now we do a timeout to actually bring the session to the right place
1097 according to the playhead. This is to avoid reading disk buffers on every
1098 call to control_scroll, which is driven by ScrollTimeline and therefore
1099 probably by a control surface wheel which can generate lots of events.
1101 /* cancel the existing timeout */
1103 control_scroll_connection.disconnect ();
1105 /* add the next timeout */
1107 control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1111 Editor::deferred_control_scroll (samplepos_t /*target*/)
1113 _session->request_locate (*_control_scroll_target, _session->transport_rolling());
1114 // reset for next stream
1115 _control_scroll_target = boost::none;
1116 _dragging_playhead = false;
1121 Editor::access_action (const std::string& action_group, const std::string& action_item)
1127 ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1130 act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1138 Editor::set_toggleaction (const std::string& action_group, const std::string& action_item, bool s)
1140 ActionManager::set_toggleaction_state (action_group.c_str(), action_item.c_str(), s);
1144 Editor::on_realize ()
1148 if (UIConfiguration::instance().get_lock_gui_after_seconds()) {
1149 start_lock_event_timing ();
1154 Editor::start_lock_event_timing ()
1156 /* check if we should lock the GUI every 30 seconds */
1158 Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::lock_timeout_callback), 30 * 1000);
1162 Editor::generic_event_handler (GdkEvent* ev)
1165 case GDK_BUTTON_PRESS:
1166 case GDK_BUTTON_RELEASE:
1167 case GDK_MOTION_NOTIFY:
1169 case GDK_KEY_RELEASE:
1170 if (contents().is_mapped()) {
1171 gettimeofday (&last_event_time, 0);
1175 case GDK_LEAVE_NOTIFY:
1176 switch (ev->crossing.detail) {
1177 case GDK_NOTIFY_UNKNOWN:
1178 case GDK_NOTIFY_INFERIOR:
1179 case GDK_NOTIFY_ANCESTOR:
1181 case GDK_NOTIFY_VIRTUAL:
1182 case GDK_NOTIFY_NONLINEAR:
1183 case GDK_NOTIFY_NONLINEAR_VIRTUAL:
1184 /* leaving window, so reset focus, thus ending any and
1185 all text entry operations.
1187 ARDOUR_UI::instance()->reset_focus (&contents());
1200 Editor::lock_timeout_callback ()
1202 struct timeval now, delta;
1204 gettimeofday (&now, 0);
1206 timersub (&now, &last_event_time, &delta);
1208 if (delta.tv_sec > (time_t) UIConfiguration::instance().get_lock_gui_after_seconds()) {
1210 /* don't call again. Returning false will effectively
1211 disconnect us from the timer callback.
1213 unlock() will call start_lock_event_timing() to get things
1223 Editor::map_position_change (samplepos_t sample)
1225 ENSURE_GUI_THREAD (*this, &Editor::map_position_change, sample)
1227 if (_session == 0) {
1231 if (_follow_playhead) {
1232 center_screen (sample);
1235 playhead_cursor->set_position (sample);
1239 Editor::center_screen (samplepos_t sample)
1241 samplecnt_t const page = _visible_canvas_width * samples_per_pixel;
1243 /* if we're off the page, then scroll.
1246 if (sample < _leftmost_sample || sample >= _leftmost_sample + page) {
1247 center_screen_internal (sample, page);
1252 Editor::center_screen_internal (samplepos_t sample, float page)
1256 if (sample > page) {
1257 sample -= (samplepos_t) page;
1262 reset_x_origin (sample);
1267 Editor::update_title ()
1269 ENSURE_GUI_THREAD (*this, &Editor::update_title);
1271 if (!own_window()) {
1276 bool dirty = _session->dirty();
1278 string session_name;
1280 if (_session->snap_name() != _session->name()) {
1281 session_name = _session->snap_name();
1283 session_name = _session->name();
1287 session_name = "*" + session_name;
1290 WindowTitle title(session_name);
1291 title += S_("Window|Editor");
1292 title += Glib::get_application_name();
1293 own_window()->set_title (title.get_string());
1295 /* ::session_going_away() will have taken care of it */
1300 Editor::set_session (Session *t)
1302 SessionHandlePtr::set_session (t);
1308 //initialize _leftmost_sample to the extents of the session
1309 //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
1310 _leftmost_sample = session_gui_extents().first;
1312 _playlist_selector->set_session (_session);
1313 nudge_clock->set_session (_session);
1314 _summary->set_session (_session);
1315 _group_tabs->set_session (_session);
1316 _route_groups->set_session (_session);
1317 _regions->set_session (_session);
1318 _snapshots->set_session (_session);
1319 _routes->set_session (_session);
1320 _locations->set_session (_session);
1321 _time_info_box->set_session (_session);
1323 if (rhythm_ferret) {
1324 rhythm_ferret->set_session (_session);
1327 if (analysis_window) {
1328 analysis_window->set_session (_session);
1332 sfbrowser->set_session (_session);
1335 compute_fixed_ruler_scale ();
1337 /* Make sure we have auto loop and auto punch ranges */
1339 Location* loc = _session->locations()->auto_loop_location();
1341 loc->set_name (_("Loop"));
1344 loc = _session->locations()->auto_punch_location();
1347 loc->set_name (_("Punch"));
1350 refresh_location_display ();
1352 /* This must happen after refresh_location_display(), as (amongst other things) we restore
1353 the selected Marker; this needs the LocationMarker list to be available.
1355 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1356 set_state (*node, Stateful::loading_state_version);
1358 /* catch up on selection state, etc. */
1361 sc.add (Properties::selected);
1362 presentation_info_changed (sc);
1364 /* catch up with the playhead */
1366 _session->request_locate (playhead_cursor->current_sample ());
1367 _pending_initial_locate = true;
1371 /* These signals can all be emitted by a non-GUI thread. Therefore the
1372 handlers for them must not attempt to directly interact with the GUI,
1373 but use PBD::Signal<T>::connect() which accepts an event loop
1374 ("context") where the handler will be asked to run.
1377 _session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1378 _session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1379 _session->TransportLooped.connect (_session_connections, invalidator (*this), boost::bind (&Editor::transport_looped, this), gui_context());
1380 _session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1381 _session->vca_manager().VCAAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_vcas, this, _1), gui_context());
1382 _session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1383 _session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1384 _session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1385 _session->tempo_map().MetricPositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempometric_position_changed, this, _1), gui_context());
1386 _session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1387 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1388 _session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1389 _session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1390 _session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1391 _session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1392 _session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1394 playhead_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
1395 playhead_cursor->show ();
1397 snapped_cursor->track_canvas_item().reparent ((ArdourCanvas::Item*) get_cursor_scroll_group());
1398 snapped_cursor->set_color (UIConfiguration::instance().color ("edit point"));
1399 snapped_cursor->show ();
1401 boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1402 Config->map_parameters (pc);
1403 _session->config.map_parameters (pc);
1405 restore_ruler_visibility ();
1406 //tempo_map_changed (PropertyChange (0));
1407 _session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1409 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1410 (static_cast<TimeAxisView*>(*i))->set_samples_per_pixel (samples_per_pixel);
1413 super_rapid_screen_update_connection = Timers::super_rapid_connect (
1414 sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1417 /* register for undo history */
1418 _session->register_with_memento_command_factory(id(), this);
1419 _session->register_with_memento_command_factory(_selection_memento->id(), _selection_memento);
1421 LuaInstance::instance()->set_session(_session);
1423 start_updating_meters ();
1427 Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1429 using namespace Menu_Helpers;
1431 void (Editor::*emf)(FadeShape);
1432 std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1435 images = &_xfade_in_images;
1436 emf = &Editor::set_fade_in_shape;
1438 images = &_xfade_out_images;
1439 emf = &Editor::set_fade_out_shape;
1444 _("Linear (for highly correlated material)"),
1445 *(*images)[FadeLinear],
1446 sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1450 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1454 _("Constant power"),
1455 *(*images)[FadeConstantPower],
1456 sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1459 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1464 *(*images)[FadeSymmetric],
1465 sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1469 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1474 *(*images)[FadeSlow],
1475 sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1478 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1483 *(*images)[FadeFast],
1484 sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1487 dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1490 /** Pop up a context menu for when the user clicks on a start crossfade */
1492 Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1494 using namespace Menu_Helpers;
1495 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1500 MenuList& items (xfade_in_context_menu.items());
1503 if (arv->audio_region()->fade_in_active()) {
1504 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1506 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1509 items.push_back (SeparatorElem());
1510 fill_xfade_menu (items, true);
1512 xfade_in_context_menu.popup (button, time);
1515 /** Pop up a context menu for when the user clicks on an end crossfade */
1517 Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType /*item_type*/)
1519 using namespace Menu_Helpers;
1520 AudioRegionView* arv = dynamic_cast<AudioRegionView*> ((RegionView*)item->get_data ("regionview"));
1525 MenuList& items (xfade_out_context_menu.items());
1528 if (arv->audio_region()->fade_out_active()) {
1529 items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1531 items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1534 items.push_back (SeparatorElem());
1535 fill_xfade_menu (items, false);
1537 xfade_out_context_menu.popup (button, time);
1541 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1543 using namespace Menu_Helpers;
1544 Menu* (Editor::*build_menu_function)();
1547 switch (item_type) {
1549 case RegionViewName:
1550 case RegionViewNameHighlight:
1551 case LeftFrameHandle:
1552 case RightFrameHandle:
1553 if (with_selection) {
1554 build_menu_function = &Editor::build_track_selection_context_menu;
1556 build_menu_function = &Editor::build_track_region_context_menu;
1561 if (with_selection) {
1562 build_menu_function = &Editor::build_track_selection_context_menu;
1564 build_menu_function = &Editor::build_track_context_menu;
1569 if (clicked_routeview->track()) {
1570 build_menu_function = &Editor::build_track_context_menu;
1572 build_menu_function = &Editor::build_track_bus_context_menu;
1577 /* probably shouldn't happen but if it does, we don't care */
1581 menu = (this->*build_menu_function)();
1582 menu->set_name ("ArdourContextMenu");
1584 /* now handle specific situations */
1586 switch (item_type) {
1588 case RegionViewName:
1589 case RegionViewNameHighlight:
1590 case LeftFrameHandle:
1591 case RightFrameHandle:
1592 if (!with_selection) {
1593 if (region_edit_menu_split_item) {
1594 if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1595 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1597 ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1600 if (region_edit_menu_split_multichannel_item) {
1601 if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1602 region_edit_menu_split_multichannel_item->set_sensitive (true);
1604 region_edit_menu_split_multichannel_item->set_sensitive (false);
1617 /* probably shouldn't happen but if it does, we don't care */
1621 if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1623 /* Bounce to disk */
1625 using namespace Menu_Helpers;
1626 MenuList& edit_items = menu->items();
1628 edit_items.push_back (SeparatorElem());
1630 switch (clicked_routeview->audio_track()->freeze_state()) {
1631 case AudioTrack::NoFreeze:
1632 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1635 case AudioTrack::Frozen:
1636 edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1639 case AudioTrack::UnFrozen:
1640 edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1646 if (item_type == StreamItem && clicked_routeview) {
1647 clicked_routeview->build_underlay_menu(menu);
1650 /* When the region menu is opened, we setup the actions so that they look right
1653 sensitize_the_right_region_actions (false);
1654 _last_region_menu_was_main = false;
1656 menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1657 menu->popup (button, time);
1661 Editor::build_track_context_menu ()
1663 using namespace Menu_Helpers;
1665 MenuList& edit_items = track_context_menu.items();
1668 add_dstream_context_items (edit_items);
1669 return &track_context_menu;
1673 Editor::build_track_bus_context_menu ()
1675 using namespace Menu_Helpers;
1677 MenuList& edit_items = track_context_menu.items();
1680 add_bus_context_items (edit_items);
1681 return &track_context_menu;
1685 Editor::build_track_region_context_menu ()
1687 using namespace Menu_Helpers;
1688 MenuList& edit_items = track_region_context_menu.items();
1691 /* we've just cleared the track region context menu, so the menu that these
1692 two items were on will have disappeared; stop them dangling.
1694 region_edit_menu_split_item = 0;
1695 region_edit_menu_split_multichannel_item = 0;
1697 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1700 boost::shared_ptr<Track> tr;
1701 boost::shared_ptr<Playlist> pl;
1703 if ((tr = rtv->track())) {
1704 add_region_context_items (edit_items, tr);
1708 add_dstream_context_items (edit_items);
1710 return &track_region_context_menu;
1714 Editor::loudness_analyze_region_selection ()
1719 Selection& s (PublicEditor::instance ().get_selection ());
1720 RegionSelection ars = s.regions;
1721 ARDOUR::AnalysisGraph ag (_session);
1722 samplecnt_t total_work = 0;
1724 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1725 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1729 if (!boost::dynamic_pointer_cast<AudioRegion> (arv->region ())) {
1732 assert (dynamic_cast<RouteTimeAxisView *> (&arv->get_time_axis_view ()));
1733 total_work += arv->region ()->length ();
1736 SimpleProgressDialog spd (_("Region Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1738 ag.set_total_samples (total_work);
1739 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1742 for (RegionSelection::iterator j = ars.begin (); j != ars.end (); ++j) {
1743 AudioRegionView* arv = dynamic_cast<AudioRegionView*> (*j);
1747 boost::shared_ptr<AudioRegion> ar = boost::dynamic_pointer_cast<AudioRegion> (arv->region ());
1751 ag.analyze_region (ar);
1754 if (!ag.canceled ()) {
1755 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1761 Editor::loudness_analyze_range_selection ()
1766 Selection& s (PublicEditor::instance ().get_selection ());
1767 TimeSelection ts = s.time;
1768 ARDOUR::AnalysisGraph ag (_session);
1769 samplecnt_t total_work = 0;
1771 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1772 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1776 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1780 for (std::list<AudioRange>::iterator j = ts.begin (); j != ts.end (); ++j) {
1781 total_work += j->length ();
1785 SimpleProgressDialog spd (_("Range Loudness Analysis"), sigc::mem_fun (ag, &AnalysisGraph::cancel));
1787 ag.set_total_samples (total_work);
1788 ag.Progress.connect_same_thread (c, boost::bind (&SimpleProgressDialog::update_progress, &spd, _1, _2));
1791 for (TrackSelection::iterator i = s.tracks.begin (); i != s.tracks.end (); ++i) {
1792 boost::shared_ptr<AudioPlaylist> pl = boost::dynamic_pointer_cast<AudioPlaylist> ((*i)->playlist ());
1796 RouteUI *rui = dynamic_cast<RouteUI *> (*i);
1800 ag.analyze_range (rui->route (), pl, ts);
1803 if (!ag.canceled ()) {
1804 ExportReport er (_("Audio Report/Analysis"), ag.results ());
1810 Editor::spectral_analyze_region_selection ()
1812 if (analysis_window == 0) {
1813 analysis_window = new AnalysisWindow();
1816 analysis_window->set_session(_session);
1818 analysis_window->show_all();
1821 analysis_window->set_regionmode();
1822 analysis_window->analyze();
1824 analysis_window->present();
1828 Editor::spectral_analyze_range_selection()
1830 if (analysis_window == 0) {
1831 analysis_window = new AnalysisWindow();
1834 analysis_window->set_session(_session);
1836 analysis_window->show_all();
1839 analysis_window->set_rangemode();
1840 analysis_window->analyze();
1842 analysis_window->present();
1846 Editor::build_track_selection_context_menu ()
1848 using namespace Menu_Helpers;
1849 MenuList& edit_items = track_selection_context_menu.items();
1850 edit_items.clear ();
1852 add_selection_context_items (edit_items);
1853 // edit_items.push_back (SeparatorElem());
1854 // add_dstream_context_items (edit_items);
1856 return &track_selection_context_menu;
1860 Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1862 using namespace Menu_Helpers;
1864 /* OK, stick the region submenu at the top of the list, and then add
1868 RegionSelection rs = get_regions_from_selection_and_entered ();
1870 string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1872 if (_popup_region_menu_item == 0) {
1873 _popup_region_menu_item = new MenuItem (menu_item_name, false);
1874 _popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1875 _popup_region_menu_item->show ();
1877 _popup_region_menu_item->set_label (menu_item_name);
1880 /* No layering allowed in later is higher layering model */
1881 RefPtr<Action> act = ActionManager::get_action (X_("EditorMenu"), X_("RegionMenuLayering"));
1882 if (act && Config->get_layer_model() == LaterHigher) {
1883 act->set_sensitive (false);
1885 act->set_sensitive (true);
1888 const samplepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, true);
1890 edit_items.push_back (*_popup_region_menu_item);
1891 if (Config->get_layer_model() == Manual && track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1892 edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1894 edit_items.push_back (SeparatorElem());
1897 /** Add context menu items relevant to selection ranges.
1898 * @param edit_items List to add the items to.
1901 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1903 using namespace Menu_Helpers;
1905 edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1906 edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1908 edit_items.push_back (SeparatorElem());
1909 edit_items.push_back (MenuElem (_("Zoom to Range"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), Horizontal)));
1911 edit_items.push_back (SeparatorElem());
1912 edit_items.push_back (MenuElem (_("Loudness Analysis"), sigc::mem_fun(*this, &Editor::loudness_analyze_range_selection)));
1913 edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::spectral_analyze_range_selection)));
1915 edit_items.push_back (SeparatorElem());
1917 edit_items.push_back (
1919 _("Move Range Start to Previous Region Boundary"),
1920 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1924 edit_items.push_back (
1926 _("Move Range Start to Next Region Boundary"),
1927 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1931 edit_items.push_back (
1933 _("Move Range End to Previous Region Boundary"),
1934 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1938 edit_items.push_back (
1940 _("Move Range End to Next Region Boundary"),
1941 sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1945 edit_items.push_back (SeparatorElem());
1946 edit_items.push_back (MenuElem (_("Separate"), mem_fun(*this, &Editor::separate_region_from_selection)));
1947 edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1949 edit_items.push_back (SeparatorElem());
1950 edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1952 edit_items.push_back (SeparatorElem());
1953 edit_items.push_back (MenuElem (_("Set Loop from Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1954 edit_items.push_back (MenuElem (_("Set Punch from Selection"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1955 edit_items.push_back (MenuElem (_("Set Session Start/End from Selection"), sigc::mem_fun(*this, &Editor::set_session_extents_from_selection)));
1957 edit_items.push_back (SeparatorElem());
1958 edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1960 edit_items.push_back (SeparatorElem());
1961 edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1962 edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1964 edit_items.push_back (SeparatorElem());
1965 edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1966 edit_items.push_back (MenuElem (_("Consolidate Range with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1967 edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1968 edit_items.push_back (MenuElem (_("Bounce Range to Region List with Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1969 edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1970 if (ARDOUR_UI::instance()->video_timeline->get_duration() > 0) {
1971 edit_items.push_back (MenuElem (_("Export Video Range..."), sigc::bind (sigc::mem_fun(*(ARDOUR_UI::instance()), &ARDOUR_UI::export_video), true)));
1977 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1979 using namespace Menu_Helpers;
1983 Menu *play_menu = manage (new Menu);
1984 MenuList& play_items = play_menu->items();
1985 play_menu->set_name ("ArdourContextMenu");
1987 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1988 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1989 play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1990 play_items.push_back (SeparatorElem());
1991 play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1993 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1997 Menu *select_menu = manage (new Menu);
1998 MenuList& select_items = select_menu->items();
1999 select_menu->set_name ("ArdourContextMenu");
2001 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2002 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2003 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2004 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2005 select_items.push_back (SeparatorElem());
2006 select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
2007 select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
2008 select_items.push_back (MenuElem (_("Set Range to Selected Regions"), sigc::mem_fun(*this, &Editor::set_selection_from_region)));
2009 select_items.push_back (SeparatorElem());
2010 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2011 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2012 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2013 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2014 select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
2015 select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
2016 select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
2018 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2022 Menu *cutnpaste_menu = manage (new Menu);
2023 MenuList& cutnpaste_items = cutnpaste_menu->items();
2024 cutnpaste_menu->set_name ("ArdourContextMenu");
2026 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2027 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2028 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2030 cutnpaste_items.push_back (SeparatorElem());
2032 cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
2033 cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
2035 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
2037 /* Adding new material */
2039 edit_items.push_back (SeparatorElem());
2040 edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
2041 edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
2045 Menu *nudge_menu = manage (new Menu());
2046 MenuList& nudge_items = nudge_menu->items();
2047 nudge_menu->set_name ("ArdourContextMenu");
2049 edit_items.push_back (SeparatorElem());
2050 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2051 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2052 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2053 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2055 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2059 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2061 using namespace Menu_Helpers;
2065 Menu *play_menu = manage (new Menu);
2066 MenuList& play_items = play_menu->items();
2067 play_menu->set_name ("ArdourContextMenu");
2069 play_items.push_back (MenuElem (_("Play from Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2070 play_items.push_back (MenuElem (_("Play from Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2071 edit_items.push_back (MenuElem (_("Play"), *play_menu));
2075 Menu *select_menu = manage (new Menu);
2076 MenuList& select_items = select_menu->items();
2077 select_menu->set_name ("ArdourContextMenu");
2079 select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2080 select_items.push_back (MenuElem (_("Select All Objects"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_objects), Selection::Set)));
2081 select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2082 select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2083 select_items.push_back (SeparatorElem());
2084 select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true, true)));
2085 select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false, true)));
2086 select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2087 select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2089 edit_items.push_back (MenuElem (_("Select"), *select_menu));
2093 Menu *cutnpaste_menu = manage (new Menu);
2094 MenuList& cutnpaste_items = cutnpaste_menu->items();
2095 cutnpaste_menu->set_name ("ArdourContextMenu");
2097 cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2098 cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2099 cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2101 Menu *nudge_menu = manage (new Menu());
2102 MenuList& nudge_items = nudge_menu->items();
2103 nudge_menu->set_name ("ArdourContextMenu");
2105 edit_items.push_back (SeparatorElem());
2106 nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2107 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2108 nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2109 nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2111 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2115 Editor::grid_type() const
2121 Editor::grid_musical() const
2123 switch (_grid_type) {
2124 case GridTypeBeatDiv32:
2125 case GridTypeBeatDiv28:
2126 case GridTypeBeatDiv24:
2127 case GridTypeBeatDiv20:
2128 case GridTypeBeatDiv16:
2129 case GridTypeBeatDiv14:
2130 case GridTypeBeatDiv12:
2131 case GridTypeBeatDiv10:
2132 case GridTypeBeatDiv8:
2133 case GridTypeBeatDiv7:
2134 case GridTypeBeatDiv6:
2135 case GridTypeBeatDiv5:
2136 case GridTypeBeatDiv4:
2137 case GridTypeBeatDiv3:
2138 case GridTypeBeatDiv2:
2144 case GridTypeMinSec:
2145 case GridTypeSamples:
2152 Editor::grid_nonmusical() const
2154 switch (_grid_type) {
2156 case GridTypeMinSec:
2157 case GridTypeSamples:
2159 case GridTypeBeatDiv32:
2160 case GridTypeBeatDiv28:
2161 case GridTypeBeatDiv24:
2162 case GridTypeBeatDiv20:
2163 case GridTypeBeatDiv16:
2164 case GridTypeBeatDiv14:
2165 case GridTypeBeatDiv12:
2166 case GridTypeBeatDiv10:
2167 case GridTypeBeatDiv8:
2168 case GridTypeBeatDiv7:
2169 case GridTypeBeatDiv6:
2170 case GridTypeBeatDiv5:
2171 case GridTypeBeatDiv4:
2172 case GridTypeBeatDiv3:
2173 case GridTypeBeatDiv2:
2182 Editor::snap_mode() const
2188 Editor::set_grid_to (GridType gt)
2190 if (_grid_type == gt) { //already set
2194 unsigned int grid_ind = (unsigned int)gt;
2196 if (internal_editing()) {
2197 internal_grid_type = gt;
2199 pre_internal_grid_type = gt;
2204 if (grid_ind > grid_type_strings.size() - 1) {
2206 _grid_type = (GridType)grid_ind;
2209 string str = grid_type_strings[grid_ind];
2211 if (str != grid_type_selector.get_text()) {
2212 grid_type_selector.set_text (str);
2215 //show appropriate rulers for this grid setting. (ToDo: perhaps make this optional)
2216 //Currently this is 'required' because the RULER calculates the grid_marks which will be used by grid_lines
2217 if ( grid_musical() ) {
2218 ruler_tempo_action->set_active(true);
2219 ruler_meter_action->set_active(true);
2221 ruler_bbt_action->set_active(true);
2222 ruler_timecode_action->set_active(false);
2223 ruler_minsec_action->set_active(false);
2224 ruler_samples_action->set_active(false);
2225 } else if (_grid_type == GridTypeSmpte ) {
2226 ruler_tempo_action->set_active(false);
2227 ruler_meter_action->set_active(false);
2229 ruler_bbt_action->set_active(false);
2230 ruler_timecode_action->set_active(true);
2231 ruler_minsec_action->set_active(false);
2232 ruler_samples_action->set_active(false);
2233 } else if (_grid_type == GridTypeMinSec ) {
2234 ruler_tempo_action->set_active(false);
2235 ruler_meter_action->set_active(false);
2237 ruler_bbt_action->set_active(false);
2238 ruler_timecode_action->set_active(false);
2239 ruler_minsec_action->set_active(true);
2240 ruler_samples_action->set_active(false);
2241 } else if (_grid_type == GridTypeSamples ) {
2242 ruler_tempo_action->set_active(false);
2243 ruler_meter_action->set_active(false);
2245 ruler_bbt_action->set_active(false);
2246 ruler_timecode_action->set_active(false);
2247 ruler_minsec_action->set_active(false);
2248 ruler_samples_action->set_active(true);
2253 if ( grid_musical() ) {
2254 compute_bbt_ruler_scale (_leftmost_sample, _leftmost_sample + current_page_samples());
2255 update_tempo_based_rulers ();
2258 mark_region_boundary_cache_dirty ();
2260 redisplay_grid (false);
2262 SnapChanged (); /* EMIT SIGNAL */
2266 Editor::set_snap_mode (SnapMode mode)
2268 if (internal_editing()) {
2269 internal_snap_mode = mode;
2271 pre_internal_snap_mode = mode;
2276 if (_snap_mode == SnapOff ) {
2277 snap_mode_button.set_active_state (Gtkmm2ext::Off);
2279 snap_mode_button.set_active_state (Gtkmm2ext::ExplicitActive);
2286 Editor::set_edit_point_preference (EditPoint ep, bool force)
2288 bool changed = (_edit_point != ep);
2291 if (Profile->get_mixbus())
2292 if (ep == EditAtSelectedMarker)
2293 ep = EditAtPlayhead;
2295 string str = edit_point_strings[(int)ep];
2296 if (str != edit_point_selector.get_text ()) {
2297 edit_point_selector.set_text (str);
2300 update_all_enter_cursors();
2302 if (!force && !changed) {
2306 const char* action=NULL;
2308 switch (_edit_point) {
2309 case EditAtPlayhead:
2310 action = "edit-at-playhead";
2312 case EditAtSelectedMarker:
2313 action = "edit-at-marker";
2316 action = "edit-at-mouse";
2320 Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2322 Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2326 bool in_track_canvas;
2328 if (!mouse_sample (foo, in_track_canvas)) {
2329 in_track_canvas = false;
2332 reset_canvas_action_sensitivity (in_track_canvas);
2333 sensitize_the_right_region_actions (false);
2339 Editor::set_state (const XMLNode& node, int version)
2342 PBD::Unwinder<bool> nsi (no_save_instant, true);
2345 Tabbable::set_state (node, version);
2348 if (_session && node.get_property ("playhead", ph_pos)) {
2350 playhead_cursor->set_position (ph_pos);
2352 warning << _("Playhead position stored with a negative value - ignored (use zero instead)") << endmsg;
2353 playhead_cursor->set_position (0);
2356 playhead_cursor->set_position (0);
2359 node.get_property ("mixer-width", editor_mixer_strip_width);
2361 node.get_property ("zoom-focus", zoom_focus);
2362 zoom_focus_selection_done (zoom_focus);
2365 if (node.get_property ("zoom", z)) {
2366 /* older versions of ardour used floating point samples_per_pixel */
2367 reset_zoom (llrintf (z));
2369 reset_zoom (samples_per_pixel);
2373 if (node.get_property ("visible-track-count", cnt)) {
2374 set_visible_track_count (cnt);
2378 if (!node.get_property ("grid-type", grid_type)) {
2379 grid_type = _grid_type;
2381 set_grid_to (grid_type);
2384 if (node.get_property ("snap-mode", sm)) {
2385 snap_mode_selection_done(sm);
2386 /* set text of Dropdown. in case _snap_mode == SnapOff (default)
2387 * snap_mode_selection_done() will only mark an already active item as active
2388 * which does not trigger set_text().
2392 set_snap_mode (_snap_mode);
2395 node.get_property ("internal-grid-type", internal_grid_type);
2396 node.get_property ("internal-snap-mode", internal_snap_mode);
2397 node.get_property ("pre-internal-grid-type", pre_internal_grid_type);
2398 node.get_property ("pre-internal-snap-mode", pre_internal_snap_mode);
2401 if (node.get_property ("mouse-mode", mm_str)) {
2402 MouseMode m = str2mousemode(mm_str);
2403 set_mouse_mode (m, true);
2405 set_mouse_mode (MouseObject, true);
2409 if (node.get_property ("left-frame", lf_pos)) {
2413 reset_x_origin (lf_pos);
2417 if (node.get_property ("y-origin", y_origin)) {
2418 reset_y_origin (y_origin);
2421 if (node.get_property ("join-object-range", yn)) {
2422 RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2424 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2425 tact->set_active (!yn);
2426 tact->set_active (yn);
2428 set_mouse_mode(mouse_mode, true);
2432 if (node.get_property ("edit-point", ep)) {
2433 set_edit_point_preference (ep, true);
2435 set_edit_point_preference (_edit_point);
2438 if (node.get_property ("follow-playhead", yn)) {
2439 set_follow_playhead (yn);
2442 if (node.get_property ("stationary-playhead", yn)) {
2443 set_stationary_playhead (yn);
2446 RegionListSortType sort_type;
2447 if (node.get_property ("region-list-sort-type", sort_type)) {
2448 _regions->reset_sort_type (sort_type, true);
2451 if (node.get_property ("show-editor-mixer", yn)) {
2453 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2456 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2458 /* do it twice to force the change */
2460 tact->set_active (!yn);
2461 tact->set_active (yn);
2464 if (node.get_property ("show-editor-list", yn)) {
2466 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2469 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2471 /* do it twice to force the change */
2473 tact->set_active (!yn);
2474 tact->set_active (yn);
2478 if (node.get_property (X_("editor-list-page"), el_page)) {
2479 _the_notebook.set_current_page (el_page);
2482 if (node.get_property (X_("show-marker-lines"), yn)) {
2483 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2485 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2487 tact->set_active (!yn);
2488 tact->set_active (yn);
2491 XMLNodeList children = node.children ();
2492 for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2493 selection->set_state (**i, Stateful::current_state_version);
2494 _regions->set_state (**i);
2495 _locations->set_state (**i);
2498 if (node.get_property ("maximised", yn)) {
2499 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Common"), X_("ToggleMaximalEditor"));
2501 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2502 bool fs = tact && tact->get_active();
2504 ActionManager::do_action ("Common", "ToggleMaximalEditor");
2508 samplepos_t nudge_clock_value;
2509 if (node.get_property ("nudge-clock-value", nudge_clock_value)) {
2510 nudge_clock->set (nudge_clock_value);
2512 nudge_clock->set_mode (AudioClock::Timecode);
2513 nudge_clock->set (_session->sample_rate() * 5, true);
2518 * Not all properties may have been in XML, but
2519 * those that are linked to a private variable may need changing
2523 act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2524 yn = _follow_playhead;
2526 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2527 if (tact->get_active() != yn) {
2528 tact->set_active (yn);
2532 act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2533 yn = _stationary_playhead;
2535 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2536 if (tact->get_active() != yn) {
2537 tact->set_active (yn);
2542 return LuaInstance::instance()->set_state(node);
2546 Editor::get_state ()
2548 XMLNode* node = new XMLNode (X_("Editor"));
2550 node->set_property ("id", id().to_s ());
2552 node->add_child_nocopy (Tabbable::get_state());
2554 node->set_property("edit-horizontal-pane-pos", edit_pane.get_divider ());
2555 node->set_property("notebook-shrunk", _notebook_shrunk);
2556 node->set_property("edit-vertical-pane-pos", editor_summary_pane.get_divider());
2558 maybe_add_mixer_strip_width (*node);
2560 node->set_property ("zoom-focus", zoom_focus);
2562 node->set_property ("zoom", samples_per_pixel);
2563 node->set_property ("grid-type", _grid_type);
2564 node->set_property ("snap-mode", _snap_mode);
2565 node->set_property ("internal-grid-type", internal_grid_type);
2566 node->set_property ("internal-snap-mode", internal_snap_mode);
2567 node->set_property ("pre-internal-grid-type", pre_internal_grid_type);
2568 node->set_property ("pre-internal-snap-mode", pre_internal_snap_mode);
2569 node->set_property ("edit-point", _edit_point);
2570 node->set_property ("visible-track-count", _visible_track_count);
2572 node->set_property ("playhead", playhead_cursor->current_sample ());
2573 node->set_property ("left-frame", _leftmost_sample);
2574 node->set_property ("y-origin", vertical_adjustment.get_value ());
2576 node->set_property ("maximised", _maximised);
2577 node->set_property ("follow-playhead", _follow_playhead);
2578 node->set_property ("stationary-playhead", _stationary_playhead);
2579 node->set_property ("region-list-sort-type", _regions->sort_type ());
2580 node->set_property ("mouse-mode", mouse_mode);
2581 node->set_property ("join-object-range", smart_mode_action->get_active ());
2583 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2585 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2586 node->set_property (X_("show-editor-mixer"), tact->get_active());
2589 act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2591 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2592 node->set_property (X_("show-editor-list"), tact->get_active());
2595 node->set_property (X_("editor-list-page"), _the_notebook.get_current_page ());
2597 if (button_bindings) {
2598 XMLNode* bb = new XMLNode (X_("Buttons"));
2599 button_bindings->save (*bb);
2600 node->add_child_nocopy (*bb);
2603 node->set_property (X_("show-marker-lines"), _show_marker_lines);
2605 node->add_child_nocopy (selection->get_state ());
2606 node->add_child_nocopy (_regions->get_state ());
2608 node->set_property ("nudge-clock-value", nudge_clock->current_duration());
2610 node->add_child_nocopy (LuaInstance::instance()->get_action_state());
2611 node->add_child_nocopy (LuaInstance::instance()->get_hook_state());
2612 node->add_child_nocopy (_locations->get_state ());
2617 /** if @param trackview_relative_offset is true, @param y y is an offset into the trackview area, in pixel units
2618 * if @param trackview_relative_offset is false, @param y y is a global canvas * coordinate, in pixel units
2620 * @return pair: TimeAxisView that y is over, layer index.
2622 * TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2623 * in stacked or expanded region display mode, otherwise 0.
2625 std::pair<TimeAxisView *, double>
2626 Editor::trackview_by_y_position (double y, bool trackview_relative_offset) const
2628 if (!trackview_relative_offset) {
2629 y -= _trackview_group->canvas_origin().y;
2633 return std::make_pair ( (TimeAxisView *) 0, 0);
2636 for (TrackViewList::const_iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2638 std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2645 return std::make_pair ( (TimeAxisView *) 0, 0);
2649 Editor::set_snapped_cursor_position (samplepos_t pos)
2651 if ( _edit_point == EditAtMouse ) {
2652 snapped_cursor->set_position(pos);
2657 /** Snap a position to the grid, if appropriate, taking into account current
2658 * grid settings and also the state of any snap modifier keys that may be pressed.
2659 * @param start Position to snap.
2660 * @param event Event to get current key modifier information from, or 0.
2663 Editor::snap_to_with_modifier (MusicSample& start, GdkEvent const * event, RoundMode direction, SnapPref pref, bool for_mark)
2665 if (!_session || !event) {
2669 if (ArdourKeyboard::indicates_snap (event->button.state)) {
2670 if (_snap_mode == SnapOff) {
2671 snap_to_internal (start, direction, pref, for_mark);
2673 start.set (start.sample, 0);
2676 if (_snap_mode != SnapOff) {
2677 snap_to_internal (start, direction, pref, for_mark);
2678 } else if (ArdourKeyboard::indicates_snap_delta (event->button.state)) {
2679 /* SnapOff, but we pressed the snap_delta modifier */
2680 snap_to_internal (start, direction, pref, for_mark);
2682 start.set (start.sample, 0);
2688 Editor::snap_to (MusicSample& start, RoundMode direction, SnapPref pref, bool for_mark, bool ensure_snap)
2690 if (!_session || (_snap_mode == SnapOff && !ensure_snap)) {
2691 start.set (start.sample, 0);
2695 snap_to_internal (start, direction, pref, for_mark, ensure_snap);
2699 check_best_snap ( samplepos_t presnap, samplepos_t &test, samplepos_t &dist, samplepos_t &best )
2701 samplepos_t diff = abs( test - presnap );
2702 if ( diff < dist ) {
2707 test = max_samplepos; //reset this so it doesn't get accidentally reused
2711 Editor::snap_to_grid (vector<ArdourCanvas::Ruler::Mark> marks, samplepos_t presnap, RoundMode direction)
2717 before = after = max_samplepos;
2719 //get marks to either side of presnap
2720 vector<ArdourCanvas::Ruler::Mark>::const_iterator m = marks.begin();
2721 while ( m != marks.end() && (m->position < presnap) ) {
2725 if (m == marks.end ()) {
2726 /* ran out of marks */
2727 before = marks.back().position;
2730 after = m->position;
2732 if (m != marks.begin ()) {
2734 before = m->position;
2737 if (before == max_samplepos && after == max_samplepos) {
2738 /* No smpte to snap to, so just don't snap */
2740 } else if (before == max_samplepos) {
2742 } else if (after == max_samplepos) {
2745 if ((direction == RoundUpMaybe || direction == RoundUpAlways))
2747 else if ((direction == RoundDownMaybe || direction == RoundDownAlways))
2749 else if (direction == 0 ) {
2750 if ((presnap - before) < (after - presnap)) {
2762 Editor::marker_snap_to_internal (samplepos_t presnap, RoundMode direction)
2768 _session->locations()->marks_either_side (presnap, before, after);
2770 if (before == max_samplepos && after == max_samplepos) {
2771 /* No marks to snap to, so just don't snap */
2773 } else if (before == max_samplepos) {
2775 } else if (after == max_samplepos) {
2778 if ((direction == RoundUpMaybe || direction == RoundUpAlways)) {
2780 } else if ((direction == RoundDownMaybe || direction == RoundDownAlways)) {
2782 } else if (direction == 0 ) {
2783 if ((presnap - before) < (after - presnap)) {
2795 Editor::snap_to_internal (MusicSample& start, RoundMode direction, SnapPref pref, bool for_mark, bool ensure_snap)
2797 const samplepos_t presnap = start.sample;
2799 samplepos_t test = max_samplepos; //for each snap, we'll use this value
2800 samplepos_t dist = max_samplepos; //this records the distance of the best snap result we've found so far
2801 samplepos_t best = max_samplepos; //this records the best snap-result we've found so far
2803 //check snap-to-marker
2804 if ( UIConfiguration::instance().get_snap_to_marks() ) {
2809 test = marker_snap_to_internal ( presnap, direction );
2810 check_best_snap(presnap, test, dist, best);
2813 //check snap-to-region-{start/end/sync}
2814 if ( UIConfiguration::instance().get_snap_to_region_start() || UIConfiguration::instance().get_snap_to_region_end() || UIConfiguration::instance().get_snap_to_region_sync() ) {
2815 if (!region_boundary_cache.empty()) {
2817 vector<samplepos_t>::iterator prev = region_boundary_cache.end ();
2818 vector<samplepos_t>::iterator next = region_boundary_cache.end ();
2820 if (direction > 0) {
2821 next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap);
2823 next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), presnap);
2826 if (next != region_boundary_cache.begin ()) {
2831 samplepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2832 samplepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2834 if (presnap > (p + n) / 2) {
2841 check_best_snap(presnap, test, dist, best);
2845 if (UIConfiguration::instance().get_snap_to_grid() && (_grid_type != GridTypeNone) ) {
2847 //if SnapToGrid is selected, the user wants to prioritize the music grid
2848 //in this case we should reset the best distance, so Grid will prevail
2849 dist = max_samplepos;
2851 test = snap_to_grid (grid_marks, presnap, direction);
2852 check_best_snap(presnap, test, dist, best);
2855 //now check "magnetic" state: is the grid within reasonable on-screen distance to trigger a snap?
2856 //this also helps to avoid snapping to somewhere the user can't see. ( i.e.: I clicked on a region and it disappeared!! )
2857 //ToDo: perhaps this should only occur if EditPointMouse?
2858 int snap_threshold_s = pixel_to_sample(UIConfiguration::instance().get_snap_threshold());
2860 start.set (best, 0);
2862 } else if (presnap > best) {
2863 if (presnap > (best+ snap_threshold_s)) {
2866 } else if (presnap < best) {
2867 if (presnap < (best - snap_threshold_s)) {
2872 start.set (best, 0);
2877 Editor::setup_toolbar ()
2879 HBox* mode_box = manage(new HBox);
2880 mode_box->set_border_width (2);
2881 mode_box->set_spacing(2);
2883 HBox* mouse_mode_box = manage (new HBox);
2884 HBox* mouse_mode_hbox = manage (new HBox);
2885 VBox* mouse_mode_vbox = manage (new VBox);
2886 Alignment* mouse_mode_align = manage (new Alignment);
2888 Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2889 mouse_mode_size_group->add_widget (smart_mode_button);
2890 mouse_mode_size_group->add_widget (mouse_move_button);
2891 mouse_mode_size_group->add_widget (mouse_cut_button);
2892 mouse_mode_size_group->add_widget (mouse_select_button);
2893 mouse_mode_size_group->add_widget (mouse_timefx_button);
2894 mouse_mode_size_group->add_widget (mouse_audition_button);
2895 mouse_mode_size_group->add_widget (mouse_draw_button);
2896 mouse_mode_size_group->add_widget (mouse_content_button);
2898 if (!Profile->get_mixbus()) {
2899 mouse_mode_size_group->add_widget (zoom_in_button);
2900 mouse_mode_size_group->add_widget (zoom_out_button);
2901 mouse_mode_size_group->add_widget (zoom_out_full_button);
2902 mouse_mode_size_group->add_widget (zoom_focus_selector);
2903 mouse_mode_size_group->add_widget (tav_shrink_button);
2904 mouse_mode_size_group->add_widget (tav_expand_button);
2906 mouse_mode_size_group->add_widget (zoom_preset_selector);
2907 mouse_mode_size_group->add_widget (visible_tracks_selector);
2910 mouse_mode_size_group->add_widget (grid_type_selector);
2911 mouse_mode_size_group->add_widget (snap_mode_button);
2913 mouse_mode_size_group->add_widget (edit_point_selector);
2914 mouse_mode_size_group->add_widget (edit_mode_selector);
2916 mouse_mode_size_group->add_widget (*nudge_clock);
2917 mouse_mode_size_group->add_widget (nudge_forward_button);
2918 mouse_mode_size_group->add_widget (nudge_backward_button);
2920 mouse_mode_hbox->set_spacing (2);
2922 if (!ARDOUR::Profile->get_trx()) {
2923 mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2926 mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2927 mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2929 if (!ARDOUR::Profile->get_mixbus()) {
2930 mouse_mode_hbox->pack_start (mouse_cut_button, false, false);
2931 mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2934 if (!ARDOUR::Profile->get_trx()) {
2935 mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2936 mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2937 mouse_mode_hbox->pack_start (mouse_content_button, false, false);
2940 mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2942 mouse_mode_align->add (*mouse_mode_vbox);
2943 mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2945 mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2947 edit_mode_selector.set_name ("mouse mode button");
2949 if (!ARDOUR::Profile->get_trx()) {
2950 mode_box->pack_start (edit_mode_selector, false, false);
2953 mode_box->pack_start (*mouse_mode_box, false, false);
2957 _zoom_box.set_spacing (2);
2958 _zoom_box.set_border_width (2);
2962 zoom_preset_selector.set_name ("zoom button");
2963 zoom_preset_selector.set_icon (ArdourIcon::ZoomExpand);
2965 zoom_in_button.set_name ("zoom button");
2966 zoom_in_button.set_icon (ArdourIcon::ZoomIn);
2967 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2968 zoom_in_button.set_related_action (act);
2970 zoom_out_button.set_name ("zoom button");
2971 zoom_out_button.set_icon (ArdourIcon::ZoomOut);
2972 act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2973 zoom_out_button.set_related_action (act);
2975 zoom_out_full_button.set_name ("zoom button");
2976 zoom_out_full_button.set_icon (ArdourIcon::ZoomFull);
2977 act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2978 zoom_out_full_button.set_related_action (act);
2980 zoom_focus_selector.set_name ("zoom button");
2982 if (ARDOUR::Profile->get_mixbus()) {
2983 _zoom_box.pack_start (zoom_preset_selector, false, false);
2984 } else if (ARDOUR::Profile->get_trx()) {
2985 mode_box->pack_start (zoom_out_button, false, false);
2986 mode_box->pack_start (zoom_in_button, false, false);
2988 _zoom_box.pack_start (zoom_out_button, false, false);
2989 _zoom_box.pack_start (zoom_in_button, false, false);
2990 _zoom_box.pack_start (zoom_out_full_button, false, false);
2991 _zoom_box.pack_start (zoom_focus_selector, false, false);
2994 /* Track zoom buttons */
2995 _track_box.set_spacing (2);
2996 _track_box.set_border_width (2);
2998 visible_tracks_selector.set_name ("zoom button");
2999 if (Profile->get_mixbus()) {
3000 visible_tracks_selector.set_icon (ArdourIcon::TimeAxisExpand);
3002 set_size_request_to_display_given_text (visible_tracks_selector, _("All"), 30, 2);
3005 tav_expand_button.set_name ("zoom button");
3006 tav_expand_button.set_icon (ArdourIcon::TimeAxisExpand);
3007 act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
3008 tav_expand_button.set_related_action (act);
3010 tav_shrink_button.set_name ("zoom button");
3011 tav_shrink_button.set_icon (ArdourIcon::TimeAxisShrink);
3012 act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
3013 tav_shrink_button.set_related_action (act);
3015 if (ARDOUR::Profile->get_mixbus()) {
3016 _track_box.pack_start (visible_tracks_selector);
3017 } else if (ARDOUR::Profile->get_trx()) {
3018 _track_box.pack_start (tav_shrink_button);
3019 _track_box.pack_start (tav_expand_button);
3021 _track_box.pack_start (visible_tracks_selector);
3022 _track_box.pack_start (tav_shrink_button);
3023 _track_box.pack_start (tav_expand_button);
3026 snap_box.set_spacing (2);
3027 snap_box.set_border_width (2);
3029 grid_type_selector.set_name ("mouse mode button");
3031 snap_mode_button.set_name ("mouse mode button");
3033 edit_point_selector.set_name ("mouse mode button");
3035 snap_box.pack_start (snap_mode_button, false, false);
3036 snap_box.pack_start (grid_type_selector, false, false);
3039 HBox *ep_box = manage (new HBox);
3040 ep_box->set_spacing (2);
3041 ep_box->set_border_width (2);
3043 ep_box->pack_start (edit_point_selector, false, false);
3047 HBox *nudge_box = manage (new HBox);
3048 nudge_box->set_spacing (2);
3049 nudge_box->set_border_width (2);
3051 nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3052 nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3054 nudge_box->pack_start (nudge_backward_button, false, false);
3055 nudge_box->pack_start (nudge_forward_button, false, false);
3056 nudge_box->pack_start (*nudge_clock, false, false);
3059 /* Pack everything in... */
3061 toolbar_hbox.set_spacing (2);
3062 toolbar_hbox.set_border_width (2);
3064 toolbar_hbox.pack_start (*mode_box, false, false);
3066 if (!ARDOUR::Profile->get_trx()) {
3068 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3070 toolbar_hbox.pack_start (_zoom_box, false, false);
3072 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3074 toolbar_hbox.pack_start (_track_box, false, false);
3076 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3078 toolbar_hbox.pack_start (snap_box, false, false);
3080 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3082 toolbar_hbox.pack_start (*ep_box, false, false);
3084 toolbar_hbox.pack_start (*(manage (new ArdourVSpacer ())), false, false, 3);
3086 toolbar_hbox.pack_start (*nudge_box, false, false);
3089 toolbar_hbox.show_all ();
3093 Editor::build_edit_point_menu ()
3095 using namespace Menu_Helpers;
3097 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtPlayhead)));
3098 if(!Profile->get_mixbus())
3099 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtSelectedMarker], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtSelectedMarker)));
3100 edit_point_selector.AddMenuElem (MenuElem ( edit_point_strings[(int)EditAtMouse], sigc::bind (sigc::mem_fun(*this, &Editor::edit_point_selection_done), (EditPoint) EditAtMouse)));
3102 set_size_request_to_display_given_text (edit_point_selector, edit_point_strings, COMBO_TRIANGLE_WIDTH, 2);
3106 Editor::build_edit_mode_menu ()
3108 using namespace Menu_Helpers;
3110 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Slide], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Slide)));
3111 // edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Splice], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Splice)));
3112 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Ripple], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Ripple)));
3113 edit_mode_selector.AddMenuElem (MenuElem ( edit_mode_strings[(int)Lock], sigc::bind (sigc::mem_fun(*this, &Editor::edit_mode_selection_done), (EditMode) Lock)));
3115 set_size_request_to_display_given_text (edit_mode_selector, edit_mode_strings, COMBO_TRIANGLE_WIDTH, 2);
3119 Editor::build_grid_type_menu ()
3121 using namespace Menu_Helpers;
3123 //main grid: bars, quarter-notes, etc
3124 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeNone], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeNone)));
3125 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBar], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBar)));
3126 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeat], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeat)));
3127 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv2], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv2)));
3128 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv4], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv4)));
3129 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv8], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv8)));
3130 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv16], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv16)));
3131 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeBeatDiv32], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv32)));
3134 grid_type_selector.AddMenuElem(SeparatorElem());
3135 Gtk::Menu *_triplet_menu = manage (new Menu);
3136 MenuList& triplet_items (_triplet_menu->items());
3138 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv3], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv3) ));
3139 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv6], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv6) ));
3140 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv12], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv12) ));
3141 triplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv24], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv24) ));
3143 grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Triplets"), *_triplet_menu));
3146 Gtk::Menu *_quintuplet_menu = manage (new Menu);
3147 MenuList& quintuplet_items (_quintuplet_menu->items());
3149 quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv5], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv5) ));
3150 quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv10], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv10) ));
3151 quintuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv20], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv20) ));
3153 grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Quintuplets"), *_quintuplet_menu));
3156 Gtk::Menu *_septuplet_menu = manage (new Menu);
3157 MenuList& septuplet_items (_septuplet_menu->items());
3159 septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv7], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv7) ));
3160 septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv14], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv14) ));
3161 septuplet_items.push_back( MenuElem( grid_type_strings[(int)GridTypeBeatDiv28], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeBeatDiv28) ));
3163 grid_type_selector.AddMenuElem (Menu_Helpers::MenuElem (_("Septuplets"), *_septuplet_menu));
3165 grid_type_selector.AddMenuElem(SeparatorElem());
3166 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeSmpte], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeSmpte)));
3167 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeMinSec], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeMinSec)));
3168 grid_type_selector.AddMenuElem (MenuElem ( grid_type_strings[(int)GridTypeSamples], sigc::bind (sigc::mem_fun(*this, &Editor::grid_type_selection_done), (GridType) GridTypeSamples)));
3170 set_size_request_to_display_given_text (grid_type_selector, "No Grid", COMBO_TRIANGLE_WIDTH, 2);
3174 Editor::setup_tooltips ()
3176 set_tooltip (smart_mode_button, _("Smart Mode (add range functions to Grab Mode)"));
3177 set_tooltip (mouse_move_button, _("Grab Mode (select/move objects)"));
3178 set_tooltip (mouse_cut_button, _("Cut Mode (split regions)"));
3179 set_tooltip (mouse_select_button, _("Range Mode (select time ranges)"));
3180 set_tooltip (mouse_draw_button, _("Draw Mode (draw and edit gain/notes/automation)"));
3181 set_tooltip (mouse_timefx_button, _("Stretch Mode (time-stretch audio and midi regions, preserving pitch)"));
3182 set_tooltip (mouse_audition_button, _("Audition Mode (listen to regions)"));
3183 set_tooltip (mouse_content_button, _("Internal Edit Mode (edit notes and automation points)"));
3184 set_tooltip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3185 set_tooltip (nudge_forward_button, _("Nudge Region/Selection Later"));
3186 set_tooltip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3187 set_tooltip (zoom_in_button, _("Zoom In"));
3188 set_tooltip (zoom_out_button, _("Zoom Out"));
3189 set_tooltip (zoom_preset_selector, _("Zoom to Time Scale"));
3190 set_tooltip (zoom_out_full_button, _("Zoom to Session"));
3191 set_tooltip (zoom_focus_selector, _("Zoom Focus"));
3192 set_tooltip (tav_expand_button, _("Expand Tracks"));
3193 set_tooltip (tav_shrink_button, _("Shrink Tracks"));
3194 set_tooltip (visible_tracks_selector, _("Number of visible tracks"));
3195 set_tooltip (grid_type_selector, _("Grid Mode"));
3196 set_tooltip (snap_mode_button, _("Snap Mode\n\nRight-click to visit Snap preferences."));
3197 set_tooltip (edit_point_selector, _("Edit Point"));
3198 set_tooltip (edit_mode_selector, _("Edit Mode"));
3199 set_tooltip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3203 Editor::convert_drop_to_paths (
3204 vector<string>& paths,
3205 const RefPtr<Gdk::DragContext>& /*context*/,
3208 const SelectionData& data,
3212 if (_session == 0) {
3216 vector<string> uris = data.get_uris();
3220 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
3221 are actually URI lists. So do it by hand.
3224 if (data.get_target() != "text/plain") {
3228 /* Parse the "uri-list" format that Nautilus provides,
3229 where each pathname is delimited by \r\n.
3231 THERE MAY BE NO NULL TERMINATING CHAR!!!
3234 string txt = data.get_text();
3238 p = (char *) malloc (txt.length() + 1);
3239 txt.copy (p, txt.length(), 0);
3240 p[txt.length()] = '\0';
3246 while (g_ascii_isspace (*p))
3250 while (*q && (*q != '\n') && (*q != '\r')) {
3257 while (q > p && g_ascii_isspace (*q))
3262 uris.push_back (string (p, q - p + 1));
3266 p = strchr (p, '\n');
3278 for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3279 if ((*i).substr (0,7) == "file://") {
3280 paths.push_back (Glib::filename_from_uri (*i));
3288 Editor::new_tempo_section ()
3293 Editor::map_transport_state ()
3295 ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3297 if (_session && _session->transport_stopped()) {
3298 have_pending_keyboard_selection = false;
3301 update_loop_range_view ();
3305 Editor::transport_looped ()
3307 /* reset Playhead position interpolation.
3308 * see Editor::super_rapid_screen_update
3310 _last_update_time = 0;
3316 Editor::begin_selection_op_history ()
3318 selection_op_cmd_depth = 0;
3319 selection_op_history_it = 0;
3321 while(!selection_op_history.empty()) {
3322 delete selection_op_history.front();
3323 selection_op_history.pop_front();
3326 selection_undo_action->set_sensitive (false);
3327 selection_redo_action->set_sensitive (false);
3328 selection_op_history.push_front (&_selection_memento->get_state ());
3332 Editor::begin_reversible_selection_op (string name)
3335 //cerr << name << endl;
3336 /* begin/commit pairs can be nested */
3337 selection_op_cmd_depth++;
3342 Editor::commit_reversible_selection_op ()
3345 if (selection_op_cmd_depth == 1) {
3347 if (selection_op_history_it > 0 && selection_op_history_it < selection_op_history.size()) {
3349 The user has undone some selection ops and then made a new one,
3350 making anything earlier in the list invalid.
3353 list<XMLNode *>::iterator it = selection_op_history.begin();
3354 list<XMLNode *>::iterator e_it = it;
3355 advance (e_it, selection_op_history_it);
3357 for ( ; it != e_it; ++it) {
3360 selection_op_history.erase (selection_op_history.begin(), e_it);
3363 selection_op_history.push_front (&_selection_memento->get_state ());
3364 selection_op_history_it = 0;
3366 selection_undo_action->set_sensitive (true);
3367 selection_redo_action->set_sensitive (false);
3370 if (selection_op_cmd_depth > 0) {
3371 selection_op_cmd_depth--;
3377 Editor::undo_selection_op ()
3380 selection_op_history_it++;
3382 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3383 if (n == selection_op_history_it) {
3384 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3385 selection_redo_action->set_sensitive (true);
3389 /* is there an earlier entry? */
3390 if ((selection_op_history_it + 1) >= selection_op_history.size()) {
3391 selection_undo_action->set_sensitive (false);
3397 Editor::redo_selection_op ()
3400 if (selection_op_history_it > 0) {
3401 selection_op_history_it--;
3404 for (std::list<XMLNode *>::iterator i = selection_op_history.begin(); i != selection_op_history.end(); ++i) {
3405 if (n == selection_op_history_it) {
3406 _selection_memento->set_state (*(*i), Stateful::current_state_version);
3407 selection_undo_action->set_sensitive (true);
3412 if (selection_op_history_it == 0) {
3413 selection_redo_action->set_sensitive (false);
3419 Editor::begin_reversible_command (string name)
3422 before.push_back (&_selection_memento->get_state ());
3423 _session->begin_reversible_command (name);
3428 Editor::begin_reversible_command (GQuark q)
3431 before.push_back (&_selection_memento->get_state ());
3432 _session->begin_reversible_command (q);
3437 Editor::abort_reversible_command ()
3440 while(!before.empty()) {
3441 delete before.front();
3444 _session->abort_reversible_command ();
3449 Editor::commit_reversible_command ()
3452 if (before.size() == 1) {
3453 _session->add_command (new MementoCommand<SelectionMemento>(*(_selection_memento), before.front(), &_selection_memento->get_state ()));
3454 redo_action->set_sensitive(false);
3455 undo_action->set_sensitive(true);
3456 begin_selection_op_history ();
3459 if (before.empty()) {
3460 cerr << "Please call begin_reversible_command() before commit_reversible_command()." << endl;
3465 _session->commit_reversible_command ();
3470 Editor::history_changed ()
3474 if (undo_action && _session) {
3475 if (_session->undo_depth() == 0) {
3476 label = S_("Command|Undo");
3478 label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3480 undo_action->property_label() = label;
3483 if (redo_action && _session) {
3484 if (_session->redo_depth() == 0) {
3486 redo_action->set_sensitive (false);
3488 label = string_compose(_("Redo (%1)"), _session->next_redo());
3489 redo_action->set_sensitive (true);
3491 redo_action->property_label() = label;
3496 Editor::duplicate_range (bool with_dialog)
3500 RegionSelection rs = get_regions_from_selection_and_entered ();
3502 if ( selection->time.length() == 0 && rs.empty()) {
3508 ArdourDialog win (_("Duplicate"));
3509 Label label (_("Number of duplications:"));
3510 Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3511 SpinButton spinner (adjustment, 0.0, 1);
3514 win.get_vbox()->set_spacing (12);
3515 win.get_vbox()->pack_start (hbox);
3516 hbox.set_border_width (6);
3517 hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3519 /* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3520 place, visually. so do this by hand.
3523 hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3524 spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3525 spinner.grab_focus();
3531 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3532 win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3533 win.set_default_response (RESPONSE_ACCEPT);
3535 spinner.grab_focus ();
3537 switch (win.run ()) {
3538 case RESPONSE_ACCEPT:
3544 times = adjustment.get_value();
3547 if ((current_mouse_mode() == MouseRange)) {
3548 if (selection->time.length()) {
3549 duplicate_selection (times);
3551 } else if (get_smart_mode()) {
3552 if (selection->time.length()) {
3553 duplicate_selection (times);
3555 duplicate_some_regions (rs, times);
3557 duplicate_some_regions (rs, times);
3562 Editor::set_edit_mode (EditMode m)
3564 Config->set_edit_mode (m);
3568 Editor::cycle_edit_mode ()
3570 switch (Config->get_edit_mode()) {
3572 Config->set_edit_mode (Ripple);
3576 Config->set_edit_mode (Lock);
3579 Config->set_edit_mode (Slide);
3585 Editor::edit_mode_selection_done ( EditMode m )
3587 Config->set_edit_mode ( m );
3591 Editor::grid_type_selection_done (GridType gridtype)
3593 RefPtr<RadioAction> ract = grid_type_action (gridtype);
3595 ract->set_active ();
3600 Editor::snap_mode_selection_done (SnapMode mode)
3602 RefPtr<RadioAction> ract = snap_mode_action (mode);
3605 ract->set_active (true);
3610 Editor::cycle_edit_point (bool with_marker)
3612 if(Profile->get_mixbus())
3613 with_marker = false;
3615 switch (_edit_point) {
3617 set_edit_point_preference (EditAtPlayhead);
3619 case EditAtPlayhead:
3621 set_edit_point_preference (EditAtSelectedMarker);
3623 set_edit_point_preference (EditAtMouse);
3626 case EditAtSelectedMarker:
3627 set_edit_point_preference (EditAtMouse);
3633 Editor::edit_point_selection_done (EditPoint ep)
3635 set_edit_point_preference ( ep );
3639 Editor::build_zoom_focus_menu ()
3641 using namespace Menu_Helpers;
3643 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusLeft], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusLeft)));
3644 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusRight], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusRight)));
3645 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusCenter], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusCenter)));
3646 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusPlayhead], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusPlayhead)));
3647 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusMouse], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusMouse)));
3648 zoom_focus_selector.AddMenuElem (MenuElem ( zoom_focus_strings[(int)ZoomFocusEdit], sigc::bind (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done), (ZoomFocus) ZoomFocusEdit)));
3650 set_size_request_to_display_given_text (zoom_focus_selector, zoom_focus_strings, COMBO_TRIANGLE_WIDTH, 2);
3654 Editor::zoom_focus_selection_done ( ZoomFocus f )
3656 RefPtr<RadioAction> ract = zoom_focus_action (f);
3658 ract->set_active ();
3663 Editor::build_track_count_menu ()
3665 using namespace Menu_Helpers;
3667 if (!Profile->get_mixbus()) {
3668 visible_tracks_selector.AddMenuElem (MenuElem (X_("1"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3669 visible_tracks_selector.AddMenuElem (MenuElem (X_("2"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3670 visible_tracks_selector.AddMenuElem (MenuElem (X_("3"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 3)));
3671 visible_tracks_selector.AddMenuElem (MenuElem (X_("4"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3672 visible_tracks_selector.AddMenuElem (MenuElem (X_("8"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3673 visible_tracks_selector.AddMenuElem (MenuElem (X_("12"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 12)));
3674 visible_tracks_selector.AddMenuElem (MenuElem (X_("16"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3675 visible_tracks_selector.AddMenuElem (MenuElem (X_("20"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 20)));
3676 visible_tracks_selector.AddMenuElem (MenuElem (X_("24"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3677 visible_tracks_selector.AddMenuElem (MenuElem (X_("32"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3678 visible_tracks_selector.AddMenuElem (MenuElem (X_("64"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 64)));
3679 visible_tracks_selector.AddMenuElem (MenuElem (_("Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3680 visible_tracks_selector.AddMenuElem (MenuElem (_("All"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3682 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 1 track"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 1)));
3683 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 2 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 2)));
3684 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 4 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 4)));
3685 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 8 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 8)));
3686 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 16 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 16)));
3687 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 24 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 24)));
3688 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 32 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 32)));
3689 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit 48 tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 48)));
3690 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit All tracks"), sigc::bind (sigc::mem_fun(*this, &Editor::set_visible_track_count), 0)));
3691 visible_tracks_selector.AddMenuElem (MenuElem (_("Fit Selection"), sigc::mem_fun(*this, &Editor::fit_selection)));
3693 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10)));
3694 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 100 ms"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 100)));
3695 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 1 * 1000)));
3696 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 sec"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 1000)));
3697 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 1000)));
3698 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 10 min"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 10 * 60 * 1000)));
3699 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 1 hour"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 60 * 60 * 1000)));
3700 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 8 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 8 * 60 * 60 * 1000)));
3701 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to 24 hours"), sigc::bind (sigc::mem_fun(*this, &Editor::set_zoom_preset), 24 * 60 * 60 * 1000)));
3702 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Session"), sigc::mem_fun(*this, &Editor::temporal_zoom_session)));
3703 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Extents"), sigc::mem_fun(*this, &Editor::temporal_zoom_extents)));
3704 zoom_preset_selector.AddMenuElem (MenuElem (_("Zoom to Range/Region Selection"), sigc::bind (sigc::mem_fun(*this, &Editor::temporal_zoom_selection), Horizontal)));
3709 Editor::set_zoom_preset (int64_t ms)
3712 temporal_zoom_session();
3716 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3717 temporal_zoom( (sample_rate * ms / 1000) / _visible_canvas_width );
3721 Editor::set_visible_track_count (int32_t n)
3723 _visible_track_count = n;
3725 /* if the canvas hasn't really been allocated any size yet, just
3726 record the desired number of visible tracks and return. when canvas
3727 allocation happens, we will get called again and then we can do the
3731 if (_visible_canvas_height <= 1) {
3737 DisplaySuspender ds;
3739 if (_visible_track_count > 0) {
3740 h = trackviews_height() / _visible_track_count;
3741 std::ostringstream s;
3742 s << _visible_track_count;
3744 } else if (_visible_track_count == 0) {
3746 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
3747 if ((*i)->marked_for_display()) {
3749 TimeAxisView::Children cl ((*i)->get_child_list ());
3750 for (TimeAxisView::Children::const_iterator j = cl.begin(); j != cl.end(); ++j) {
3751 if ((*j)->marked_for_display()) {
3758 visible_tracks_selector.set_text (X_("*"));
3761 h = trackviews_height() / n;
3764 /* negative value means that the visible track count has
3765 been overridden by explicit track height changes.
3767 visible_tracks_selector.set_text (X_("*"));
3771 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3772 (*i)->set_height (h, TimeAxisView::HeightPerLane);
3775 if (str != visible_tracks_selector.get_text()) {
3776 visible_tracks_selector.set_text (str);
3781 Editor::override_visible_track_count ()
3783 _visible_track_count = -1;
3784 visible_tracks_selector.set_text ( _("*") );
3788 Editor::edit_controls_button_release (GdkEventButton* ev)
3790 if (Keyboard::is_context_menu_event (ev)) {
3791 ARDOUR_UI::instance()->add_route ();
3792 } else if (ev->button == 1) {
3793 selection->clear_tracks ();
3800 Editor::mouse_select_button_release (GdkEventButton* ev)
3802 /* this handles just right-clicks */
3804 if (ev->button != 3) {
3812 Editor::set_zoom_focus (ZoomFocus f)
3814 string str = zoom_focus_strings[(int)f];
3816 if (str != zoom_focus_selector.get_text()) {
3817 zoom_focus_selector.set_text (str);
3820 if (zoom_focus != f) {
3827 Editor::cycle_zoom_focus ()
3829 switch (zoom_focus) {
3831 set_zoom_focus (ZoomFocusRight);
3833 case ZoomFocusRight:
3834 set_zoom_focus (ZoomFocusCenter);
3836 case ZoomFocusCenter:
3837 set_zoom_focus (ZoomFocusPlayhead);
3839 case ZoomFocusPlayhead:
3840 set_zoom_focus (ZoomFocusMouse);
3842 case ZoomFocusMouse:
3843 set_zoom_focus (ZoomFocusEdit);
3846 set_zoom_focus (ZoomFocusLeft);
3852 Editor::update_grid ()
3854 if ( grid_musical() ) {
3855 std::vector<TempoMap::BBTPoint> grid;
3856 if (bbt_ruler_scale != bbt_show_many) {
3857 compute_current_bbt_points (grid, _leftmost_sample, _leftmost_sample + current_page_samples());
3859 maybe_draw_grid_lines ();
3860 } else if ( grid_nonmusical() ) {
3861 maybe_draw_grid_lines ();
3868 Editor::toggle_follow_playhead ()
3870 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3872 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3873 set_follow_playhead (tact->get_active());
3877 /** @param yn true to follow playhead, otherwise false.
3878 * @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3881 Editor::set_follow_playhead (bool yn, bool catch_up)
3883 if (_follow_playhead != yn) {
3884 if ((_follow_playhead = yn) == true && catch_up) {
3886 reset_x_origin_to_follow_playhead ();
3893 Editor::toggle_stationary_playhead ()
3895 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3897 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3898 set_stationary_playhead (tact->get_active());
3903 Editor::set_stationary_playhead (bool yn)
3905 if (_stationary_playhead != yn) {
3906 if ((_stationary_playhead = yn) == true) {
3908 // FIXME need a 3.0 equivalent of this 2.X call
3909 // update_current_screen ();
3916 Editor::playlist_selector () const
3918 return *_playlist_selector;
3922 Editor::get_paste_offset (samplepos_t pos, unsigned paste_count, samplecnt_t duration)
3924 if (paste_count == 0) {
3925 /* don't bother calculating an offset that will be zero anyway */
3929 /* calculate basic unsnapped multi-paste offset */
3930 samplecnt_t offset = paste_count * duration;
3932 /* snap offset so pos + offset is aligned to the grid */
3933 MusicSample offset_pos (pos + offset, 0);
3934 snap_to(offset_pos, RoundUpMaybe);
3935 offset = offset_pos.sample - pos;
3941 Editor::get_grid_beat_divisions(samplepos_t position)
3943 switch (_grid_type) {
3944 case GridTypeBeatDiv32: return 32;
3945 case GridTypeBeatDiv28: return 28;
3946 case GridTypeBeatDiv24: return 24;
3947 case GridTypeBeatDiv20: return 20;
3948 case GridTypeBeatDiv16: return 16;
3949 case GridTypeBeatDiv14: return 14;
3950 case GridTypeBeatDiv12: return 12;
3951 case GridTypeBeatDiv10: return 10;
3952 case GridTypeBeatDiv8: return 8;
3953 case GridTypeBeatDiv7: return 7;
3954 case GridTypeBeatDiv6: return 6;
3955 case GridTypeBeatDiv5: return 5;
3956 case GridTypeBeatDiv4: return 4;
3957 case GridTypeBeatDiv3: return 3;
3958 case GridTypeBeatDiv2: return 2;
3960 case GridTypeNone: return 0;
3961 case GridTypeSmpte: return 0;
3962 case GridTypeMinSec: return 0;
3963 case GridTypeSamples: return 0;
3969 /** returns the current musical grid divisiions using the supplied modifier mask from a GtkEvent.
3970 if the grid is non-musical, returns 0.
3971 if the grid is snapped to bars, returns -1.
3972 @param event_state the current keyboard modifier mask.
3975 Editor::get_grid_music_divisions (uint32_t event_state)
3977 if (snap_mode() == SnapOff && !ArdourKeyboard::indicates_snap (event_state)) {
3981 if (snap_mode() != SnapOff && ArdourKeyboard::indicates_snap (event_state)) {
3985 switch (_grid_type) {
3986 case GridTypeBeatDiv32: return 32;
3987 case GridTypeBeatDiv28: return 28;
3988 case GridTypeBeatDiv24: return 24;
3989 case GridTypeBeatDiv20: return 20;
3990 case GridTypeBeatDiv16: return 16;
3991 case GridTypeBeatDiv14: return 14;
3992 case GridTypeBeatDiv12: return 12;
3993 case GridTypeBeatDiv10: return 10;
3994 case GridTypeBeatDiv8: return 8;
3995 case GridTypeBeatDiv7: return 7;
3996 case GridTypeBeatDiv6: return 6;
3997 case GridTypeBeatDiv5: return 5;
3998 case GridTypeBeatDiv4: return 4;
3999 case GridTypeBeatDiv3: return 3;
4000 case GridTypeBeatDiv2: return 2;
4001 case GridTypeBeat: return 1;
4002 case GridTypeBar : return -1;
4004 case GridTypeNone: return 0;
4005 case GridTypeSmpte: return 0;
4006 case GridTypeMinSec: return 0;
4007 case GridTypeSamples: return 0;
4013 Editor::get_grid_type_as_beats (bool& success, samplepos_t position)
4017 const unsigned divisions = get_grid_beat_divisions(position);
4019 return Temporal::Beats(1.0 / (double)get_grid_beat_divisions(position));
4022 switch (_grid_type) {
4024 return Temporal::Beats(4.0 / _session->tempo_map().meter_at_sample (position).note_divisor());
4027 const Meter& m = _session->tempo_map().meter_at_sample (position);
4028 return Temporal::Beats((4.0 * m.divisions_per_bar()) / m.note_divisor());
4036 return Temporal::Beats();
4040 Editor::get_nudge_distance (samplepos_t pos, samplecnt_t& next)
4044 ret = nudge_clock->current_duration (pos);
4045 next = ret + 1; /* XXXX fix me */
4051 Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
4053 ArdourDialog dialog (_("Playlist Deletion"));
4054 Label label (string_compose (_("Playlist %1 is currently unused.\n"
4055 "If it is kept, its audio files will not be cleaned.\n"
4056 "If it is deleted, audio files used by it alone will be cleaned."),
4059 dialog.set_position (WIN_POS_CENTER);
4060 dialog.get_vbox()->pack_start (label);
4064 dialog.add_button (_("Delete All Unused"), RESPONSE_YES); // needs clarification. this and all remaining ones
4065 dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
4066 Button* keep = dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
4067 dialog.add_button (_("Keep Remaining"), RESPONSE_NO); // ditto
4068 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
4070 // by default gtk uses the left most button
4071 keep->grab_focus ();
4073 switch (dialog.run ()) {
4075 /* keep this and all remaining ones */
4080 /* delete this and all others */
4084 case RESPONSE_ACCEPT:
4085 /* delete the playlist */
4089 case RESPONSE_REJECT:
4090 /* keep the playlist */
4102 Editor::audio_region_selection_covers (samplepos_t where)
4104 for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
4105 if ((*a)->region()->covers (where)) {
4114 Editor::prepare_for_cleanup ()
4116 cut_buffer->clear_regions ();
4117 cut_buffer->clear_playlists ();
4119 selection->clear_regions ();
4120 selection->clear_playlists ();
4122 _regions->suspend_redisplay ();
4126 Editor::finish_cleanup ()
4128 _regions->resume_redisplay ();
4132 Editor::transport_loop_location()
4135 return _session->locations()->auto_loop_location();
4142 Editor::transport_punch_location()
4145 return _session->locations()->auto_punch_location();
4152 Editor::control_layout_scroll (GdkEventScroll* ev)
4154 /* Just forward to the normal canvas scroll method. The coordinate
4155 systems are different but since the canvas is always larger than the
4156 track headers, and aligned with the trackview area, this will work.
4158 In the not too distant future this layout is going away anyway and
4159 headers will be on the canvas.
4161 return canvas_scroll_event (ev, false);
4165 Editor::session_state_saved (string)
4168 _snapshots->redisplay ();
4172 Editor::maximise_editing_space ()
4178 Gtk::Window* toplevel = current_toplevel();
4181 toplevel->fullscreen ();
4187 Editor::restore_editing_space ()
4193 Gtk::Window* toplevel = current_toplevel();
4196 toplevel->unfullscreen();
4202 * Make new playlists for a given track and also any others that belong
4203 * to the same active route group with the `select' property.
4208 Editor::new_playlists (TimeAxisView* v)
4210 begin_reversible_command (_("new playlists"));
4211 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4212 _session->playlists->get (playlists);
4213 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
4214 commit_reversible_command ();
4218 * Use a copy of the current playlist for a given track and also any others that belong
4219 * to the same active route group with the `select' property.
4224 Editor::copy_playlists (TimeAxisView* v)
4226 begin_reversible_command (_("copy playlists"));
4227 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4228 _session->playlists->get (playlists);
4229 mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::group_select.property_id);
4230 commit_reversible_command ();
4233 /** Clear the current playlist for a given track and also any others that belong
4234 * to the same active route group with the `select' property.
4239 Editor::clear_playlists (TimeAxisView* v)
4241 begin_reversible_command (_("clear playlists"));
4242 vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4243 _session->playlists->get (playlists);
4244 mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::group_select.property_id);
4245 commit_reversible_command ();
4249 Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4251 atv.use_new_playlist (sz > 1 ? false : true, playlists, false);
4255 Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4257 atv.use_new_playlist (sz > 1 ? false : true, playlists, true);
4261 Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4263 atv.clear_playlist ();
4267 Editor::get_y_origin () const
4269 return vertical_adjustment.get_value ();
4272 /** Queue up a change to the viewport x origin.
4273 * @param sample New x origin.
4276 Editor::reset_x_origin (samplepos_t sample)
4278 pending_visual_change.add (VisualChange::TimeOrigin);
4279 pending_visual_change.time_origin = sample;
4280 ensure_visual_change_idle_handler ();
4284 Editor::reset_y_origin (double y)
4286 pending_visual_change.add (VisualChange::YOrigin);
4287 pending_visual_change.y_origin = y;
4288 ensure_visual_change_idle_handler ();
4292 Editor::reset_zoom (samplecnt_t spp)
4294 if (spp == samples_per_pixel) {
4298 pending_visual_change.add (VisualChange::ZoomLevel);
4299 pending_visual_change.samples_per_pixel = spp;
4300 ensure_visual_change_idle_handler ();
4304 Editor::reposition_and_zoom (samplepos_t sample, double fpu)
4306 reset_x_origin (sample);
4309 if (!no_save_visual) {
4310 undo_visual_stack.push_back (current_visual_state(false));
4314 Editor::VisualState::VisualState (bool with_tracks)
4315 : gui_state (with_tracks ? new GUIObjectState : 0)
4319 Editor::VisualState::~VisualState ()
4324 Editor::VisualState*
4325 Editor::current_visual_state (bool with_tracks)
4327 VisualState* vs = new VisualState (with_tracks);
4328 vs->y_position = vertical_adjustment.get_value();
4329 vs->samples_per_pixel = samples_per_pixel;
4330 vs->_leftmost_sample = _leftmost_sample;
4331 vs->zoom_focus = zoom_focus;
4334 vs->gui_state->set_state (ARDOUR_UI::instance()->gui_object_state->get_state());
4341 Editor::undo_visual_state ()
4343 if (undo_visual_stack.empty()) {
4347 VisualState* vs = undo_visual_stack.back();
4348 undo_visual_stack.pop_back();
4351 redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4354 use_visual_state (*vs);
4359 Editor::redo_visual_state ()
4361 if (redo_visual_stack.empty()) {
4365 VisualState* vs = redo_visual_stack.back();
4366 redo_visual_stack.pop_back();
4368 // can 'vs' really be 0? Is there a place that puts NULL pointers onto the stack?
4369 // why do we check here?
4370 undo_visual_stack.push_back (current_visual_state (vs ? (vs->gui_state != 0) : false));
4373 use_visual_state (*vs);
4378 Editor::swap_visual_state ()
4380 if (undo_visual_stack.empty()) {
4381 redo_visual_state ();
4383 undo_visual_state ();
4388 Editor::use_visual_state (VisualState& vs)
4390 PBD::Unwinder<bool> nsv (no_save_visual, true);
4391 DisplaySuspender ds;
4393 vertical_adjustment.set_value (vs.y_position);
4395 set_zoom_focus (vs.zoom_focus);
4396 reposition_and_zoom (vs._leftmost_sample, vs.samples_per_pixel);
4399 ARDOUR_UI::instance()->gui_object_state->set_state (vs.gui_state->get_state());
4401 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4402 (*i)->clear_property_cache();
4403 (*i)->reset_visual_state ();
4407 _routes->update_visibility ();
4410 /** This is the core function that controls the zoom level of the canvas. It is called
4411 * whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4412 * @param spp new number of samples per pixel
4415 Editor::set_samples_per_pixel (samplecnt_t spp)
4421 const samplecnt_t three_days = 3 * 24 * 60 * 60 * (_session ? _session->sample_rate() : 48000);
4422 const samplecnt_t lots_of_pixels = 4000;
4424 /* if the zoom level is greater than what you'd get trying to display 3
4425 * days of audio on a really big screen, then it's too big.
4428 if (spp * lots_of_pixels > three_days) {
4432 samples_per_pixel = spp;
4436 Editor::on_samples_per_pixel_changed ()
4438 bool const showing_time_selection = selection->time.length() > 0;
4440 if (showing_time_selection && selection->time.start () != selection->time.end_sample ()) {
4441 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4442 (*i)->reshow_selection (selection->time);
4446 ZoomChanged (); /* EMIT_SIGNAL */
4448 ArdourCanvas::GtkCanvasViewport* c;
4450 c = get_track_canvas();
4452 c->canvas()->zoomed ();
4455 if (playhead_cursor) {
4456 playhead_cursor->set_position (playhead_cursor->current_sample ());
4459 refresh_location_display();
4460 _summary->set_overlays_dirty ();
4462 update_marker_labels ();
4468 Editor::playhead_cursor_sample () const
4470 return playhead_cursor->current_sample();
4474 Editor::queue_visual_videotimeline_update ()
4476 pending_visual_change.add (VisualChange::VideoTimeline);
4477 ensure_visual_change_idle_handler ();
4481 Editor::ensure_visual_change_idle_handler ()
4483 if (pending_visual_change.idle_handler_id < 0) {
4484 // see comment in add_to_idle_resize above.
4485 pending_visual_change.idle_handler_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_visual_changer, this, NULL);
4486 pending_visual_change.being_handled = false;
4491 Editor::_idle_visual_changer (void* arg)
4493 return static_cast<Editor*>(arg)->idle_visual_changer ();
4497 Editor::pre_render ()
4499 visual_change_queued = false;
4501 if (pending_visual_change.pending != 0) {
4502 ensure_visual_change_idle_handler();
4507 Editor::idle_visual_changer ()
4509 pending_visual_change.idle_handler_id = -1;
4511 if (pending_visual_change.pending == 0) {
4515 /* set_horizontal_position() below (and maybe other calls) call
4516 gtk_main_iteration(), so it's possible that a signal will be handled
4517 half-way through this method. If this signal wants an
4518 idle_visual_changer we must schedule another one after this one, so
4519 mark the idle_handler_id as -1 here to allow that. Also make a note
4520 that we are doing the visual change, so that changes in response to
4521 super-rapid-screen-update can be dropped if we are still processing
4525 if (visual_change_queued) {
4529 pending_visual_change.being_handled = true;
4531 VisualChange vc = pending_visual_change;
4533 pending_visual_change.pending = (VisualChange::Type) 0;
4535 visual_changer (vc);
4537 pending_visual_change.being_handled = false;
4539 visual_change_queued = true;
4541 return 0; /* this is always a one-shot call */
4545 Editor::visual_changer (const VisualChange& vc)
4548 * Changed first so the correct horizontal canvas position is calculated in
4549 * Editor::set_horizontal_position
4551 if (vc.pending & VisualChange::ZoomLevel) {
4552 set_samples_per_pixel (vc.samples_per_pixel);
4555 if (vc.pending & VisualChange::TimeOrigin) {
4556 double new_time_origin = sample_to_pixel_unrounded (vc.time_origin);
4557 set_horizontal_position (new_time_origin);
4560 if (vc.pending & VisualChange::YOrigin) {
4561 vertical_adjustment.set_value (vc.y_origin);
4565 * Now the canvas is in the final state before render the canvas items that
4566 * support the Item::prepare_for_render interface can calculate the correct
4567 * item to visible canvas intersection.
4569 if (vc.pending & VisualChange::ZoomLevel) {
4570 on_samples_per_pixel_changed ();
4572 compute_fixed_ruler_scale ();
4574 compute_bbt_ruler_scale (vc.time_origin, pending_visual_change.time_origin + current_page_samples());
4575 update_tempo_based_rulers ();
4578 if (!(vc.pending & VisualChange::ZoomLevel)) {
4580 * If the canvas is not being zoomed then the canvas items will not change
4581 * and cause Item::prepare_for_render to be called so do it here manually.
4583 * Not ideal, but I can't think of a better solution atm.
4585 _track_canvas->prepare_for_render();
4588 // If we are only scrolling vertically there is no need to update these
4589 if (vc.pending != VisualChange::YOrigin) {
4590 update_fixed_rulers ();
4591 redisplay_grid (true);
4593 /* video frames & position need to be updated for zoom, horiz-scroll
4594 * and (explicitly) VisualChange::VideoTimeline.
4596 update_video_timeline();
4599 _summary->set_overlays_dirty ();
4602 struct EditorOrderTimeAxisSorter {
4603 bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4604 return a->order () < b->order ();
4609 Editor::sort_track_selection (TrackViewList& sel)
4611 EditorOrderTimeAxisSorter cmp;
4616 Editor::get_preferred_edit_position (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4619 samplepos_t where = 0;
4620 EditPoint ep = _edit_point;
4622 if (Profile->get_mixbus()) {
4623 if (ep == EditAtSelectedMarker) {
4624 ep = EditAtPlayhead;
4628 if (from_outside_canvas && (ep == EditAtMouse)) {
4629 ep = EditAtPlayhead;
4630 } else if (from_context_menu && (ep == EditAtMouse)) {
4631 return canvas_event_sample (&context_click_event, 0, 0);
4634 if (entered_marker) {
4635 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4636 return entered_marker->position();
4639 if ( (ignore==EDIT_IGNORE_PHEAD) && ep == EditAtPlayhead) {
4640 ep = EditAtSelectedMarker;
4643 if ( (ignore==EDIT_IGNORE_MOUSE) && ep == EditAtMouse) {
4644 ep = EditAtPlayhead;
4647 MusicSample snap_mf (0, 0);
4650 case EditAtPlayhead:
4651 if (_dragging_playhead && _control_scroll_target) {
4652 where = *_control_scroll_target;
4654 where = _session->audible_sample();
4656 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4659 case EditAtSelectedMarker:
4660 if (!selection->markers.empty()) {
4662 Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4665 where = loc->start();
4669 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4677 if (!mouse_sample (where, ignored)) {
4678 /* XXX not right but what can we do ? */
4681 snap_mf.sample = where;
4683 where = snap_mf.sample;
4684 DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4692 Editor::set_loop_range (samplepos_t start, samplepos_t end, string cmd)
4694 if (!_session) return;
4696 begin_reversible_command (cmd);
4700 if ((tll = transport_loop_location()) == 0) {
4701 Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop, get_grid_music_divisions(0));
4702 XMLNode &before = _session->locations()->get_state();
4703 _session->locations()->add (loc, true);
4704 _session->set_auto_loop_location (loc);
4705 XMLNode &after = _session->locations()->get_state();
4706 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4708 XMLNode &before = tll->get_state();
4709 tll->set_hidden (false, this);
4710 tll->set (start, end);
4711 XMLNode &after = tll->get_state();
4712 _session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4715 commit_reversible_command ();
4719 Editor::set_punch_range (samplepos_t start, samplepos_t end, string cmd)
4721 if (!_session) return;
4723 begin_reversible_command (cmd);
4727 if ((tpl = transport_punch_location()) == 0) {
4728 Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch, get_grid_music_divisions(0));
4729 XMLNode &before = _session->locations()->get_state();
4730 _session->locations()->add (loc, true);
4731 _session->set_auto_punch_location (loc);
4732 XMLNode &after = _session->locations()->get_state();
4733 _session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4735 XMLNode &before = tpl->get_state();
4736 tpl->set_hidden (false, this);
4737 tpl->set (start, end);
4738 XMLNode &after = tpl->get_state();
4739 _session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4742 commit_reversible_command ();
4745 /** Find regions which exist at a given time, and optionally on a given list of tracks.
4746 * @param rs List to which found regions are added.
4747 * @param where Time to look at.
4748 * @param ts Tracks to look on; if this is empty, all tracks are examined.
4751 Editor::get_regions_at (RegionSelection& rs, samplepos_t where, const TrackViewList& ts) const
4753 const TrackViewList* tracks;
4756 tracks = &track_views;
4761 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4763 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4766 boost::shared_ptr<Track> tr;
4767 boost::shared_ptr<Playlist> pl;
4769 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4771 boost::shared_ptr<RegionList> regions = pl->regions_at (where);
4773 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4774 RegionView* rv = rtv->view()->find_view (*i);
4785 Editor::get_regions_after (RegionSelection& rs, samplepos_t where, const TrackViewList& ts) const
4787 const TrackViewList* tracks;
4790 tracks = &track_views;
4795 for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4796 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4798 boost::shared_ptr<Track> tr;
4799 boost::shared_ptr<Playlist> pl;
4801 if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4803 boost::shared_ptr<RegionList> regions = pl->regions_touched (where, max_samplepos);
4805 for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4807 RegionView* rv = rtv->view()->find_view (*i);
4818 /** Get regions using the following method:
4820 * Make a region list using:
4821 * (a) any selected regions
4822 * (b) the intersection of any selected tracks and the edit point(*)
4823 * (c) if neither exists, and edit_point == mouse, then whatever region is under the mouse
4825 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4827 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4831 Editor::get_regions_from_selection_and_edit_point (EditIgnoreOption ignore, bool from_context_menu, bool from_outside_canvas)
4833 RegionSelection regions;
4835 if (_edit_point == EditAtMouse && entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4836 regions.add (entered_regionview);
4838 regions = selection->regions;
4841 if ( regions.empty() ) {
4842 TrackViewList tracks = selection->tracks;
4844 if (!tracks.empty()) {
4845 /* no region selected or entered, but some selected tracks:
4846 * act on all regions on the selected tracks at the edit point
4848 samplepos_t const where = get_preferred_edit_position (ignore, from_context_menu, from_outside_canvas);
4849 get_regions_at(regions, where, tracks);
4856 /** Get regions using the following method:
4858 * Make a region list using:
4859 * (a) any selected regions
4860 * (b) the intersection of any selected tracks and the edit point(*)
4861 * (c) if neither exists, then whatever region is under the mouse
4863 * (*) NOTE: in this case, if 'No Selection = All Tracks' is active, search all tracks
4865 * Note that we have forced the rule that selected regions and selected tracks are mutually exclusive
4868 Editor::get_regions_from_selection_and_mouse (samplepos_t pos)
4870 RegionSelection regions;
4872 if (entered_regionview && selection->tracks.empty() && selection->regions.empty() ) {
4873 regions.add (entered_regionview);
4875 regions = selection->regions;
4878 if ( regions.empty() ) {
4879 TrackViewList tracks = selection->tracks;
4881 if (!tracks.empty()) {
4882 /* no region selected or entered, but some selected tracks:
4883 * act on all regions on the selected tracks at the edit point
4885 get_regions_at(regions, pos, tracks);
4892 /** Start with regions that are selected, or the entered regionview if none are selected.
4893 * Then add equivalent regions on tracks in the same active edit-enabled route group as any
4894 * of the regions that we started with.
4898 Editor::get_regions_from_selection_and_entered () const
4900 RegionSelection regions = selection->regions;
4902 if (regions.empty() && entered_regionview) {
4903 regions.add (entered_regionview);
4910 Editor::get_regionviews_by_id (PBD::ID const id, RegionSelection & regions) const
4912 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4913 RouteTimeAxisView* rtav;
4915 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4916 boost::shared_ptr<Playlist> pl;
4917 std::vector<boost::shared_ptr<Region> > results;
4918 boost::shared_ptr<Track> tr;
4920 if ((tr = rtav->track()) == 0) {
4925 if ((pl = (tr->playlist())) != 0) {
4926 boost::shared_ptr<Region> r = pl->region_by_id (id);
4928 RegionView* rv = rtav->view()->find_view (r);
4930 regions.push_back (rv);
4939 Editor::get_per_region_note_selection (list<pair<PBD::ID, set<boost::shared_ptr<Evoral::Note<Temporal::Beats> > > > > &selection) const
4942 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4943 MidiTimeAxisView* mtav;
4945 if ((mtav = dynamic_cast<MidiTimeAxisView*> (*i)) != 0) {
4947 mtav->get_per_region_note_selection (selection);
4954 Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4956 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4958 RouteTimeAxisView* tatv;
4960 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4962 boost::shared_ptr<Playlist> pl;
4963 vector<boost::shared_ptr<Region> > results;
4965 boost::shared_ptr<Track> tr;
4967 if ((tr = tatv->track()) == 0) {
4972 if ((pl = (tr->playlist())) != 0) {
4973 if (src_comparison) {
4974 pl->get_source_equivalent_regions (region, results);
4976 pl->get_region_list_equivalent_regions (region, results);
4980 for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4981 if ((marv = tatv->view()->find_view (*ir)) != 0) {
4982 regions.push_back (marv);
4991 Editor::regionview_from_region (boost::shared_ptr<Region> region) const
4993 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4994 RouteTimeAxisView* tatv;
4995 if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4996 if (!tatv->track()) {
4999 RegionView* marv = tatv->view()->find_view (region);
5009 Editor::rtav_from_route (boost::shared_ptr<Route> route) const
5011 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5012 RouteTimeAxisView* rtav;
5013 if ((rtav = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
5014 if (rtav->route() == route) {
5023 Editor::show_rhythm_ferret ()
5025 if (rhythm_ferret == 0) {
5026 rhythm_ferret = new RhythmFerret(*this);
5029 rhythm_ferret->set_session (_session);
5030 rhythm_ferret->show ();
5031 rhythm_ferret->present ();
5035 Editor::first_idle ()
5037 MessageDialog* dialog = 0;
5039 if (track_views.size() > 1) {
5040 Timers::TimerSuspender t;
5041 dialog = new MessageDialog (
5042 string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
5046 ARDOUR_UI::instance()->flush_pending (60);
5049 for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
5053 /* now that all regionviews should exist, setup region selection */
5057 for (list<PBD::ID>::iterator pr = selection->regions.pending.begin (); pr != selection->regions.pending.end (); ++pr) {
5058 /* this is cumulative: rs is NOT cleared each time */
5059 get_regionviews_by_id (*pr, rs);
5062 selection->set (rs);
5064 // first idle adds route children (automation tracks), so we need to redisplay here
5065 _routes->redisplay ();
5069 if (_session->undo_depth() == 0) {
5070 undo_action->set_sensitive(false);
5072 redo_action->set_sensitive(false);
5073 begin_selection_op_history ();
5079 Editor::_idle_resize (gpointer arg)
5081 return ((Editor*)arg)->idle_resize ();
5085 Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
5087 if (resize_idle_id < 0) {
5088 /* https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#G-PRIORITY-HIGH-IDLE:CAPS
5089 * GTK+ uses G_PRIORITY_HIGH_IDLE + 10 for resizing operations, and G_PRIORITY_HIGH_IDLE + 20 for redrawing operations.
5090 * (This is done to ensure that any pending resizes are processed before any pending redraws, so that widgets are not redrawn twice unnecessarily.)
5092 resize_idle_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 10, _idle_resize, this, NULL);
5093 _pending_resize_amount = 0;
5096 /* make a note of the smallest resulting height, so that we can clamp the
5097 lower limit at TimeAxisView::hSmall */
5099 int32_t min_resulting = INT32_MAX;
5101 _pending_resize_amount += h;
5102 _pending_resize_view = view;
5104 min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
5106 if (selection->tracks.contains (_pending_resize_view)) {
5107 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5108 min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
5112 if (min_resulting < 0) {
5117 if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
5118 _pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
5122 /** Handle pending resizing of tracks */
5124 Editor::idle_resize ()
5126 _pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
5128 if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
5129 selection->tracks.contains (_pending_resize_view)) {
5131 for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
5132 if (*i != _pending_resize_view) {
5133 (*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
5138 _pending_resize_amount = 0;
5139 _group_tabs->set_dirty ();
5140 resize_idle_id = -1;
5148 ENSURE_GUI_THREAD (*this, &Editor::located);
5151 playhead_cursor->set_position (_session->audible_sample ());
5152 if (_follow_playhead && !_pending_initial_locate) {
5153 reset_x_origin_to_follow_playhead ();
5157 _pending_locate_request = false;
5158 _pending_initial_locate = false;
5159 _last_update_time = 0;
5163 Editor::region_view_added (RegionView * rv)
5165 MidiRegionView* mrv = dynamic_cast<MidiRegionView*> (rv);
5167 list<pair<PBD::ID const, list<Evoral::event_id_t> > >::iterator rnote;
5168 for (rnote = selection->pending_midi_note_selection.begin(); rnote != selection->pending_midi_note_selection.end(); ++rnote) {
5169 if (rv->region()->id () == (*rnote).first) {
5170 mrv->select_notes ((*rnote).second);
5171 selection->pending_midi_note_selection.erase(rnote);
5177 _summary->set_background_dirty ();
5179 mark_region_boundary_cache_dirty ();
5183 Editor::region_view_removed ()
5185 _summary->set_background_dirty ();
5187 mark_region_boundary_cache_dirty ();
5191 Editor::axis_view_by_stripable (boost::shared_ptr<Stripable> s) const
5193 for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
5194 if ((*j)->stripable() == s) {
5203 Editor::axis_view_by_control (boost::shared_ptr<AutomationControl> c) const
5205 for (TrackViewList::const_iterator j = track_views.begin (); j != track_views.end(); ++j) {
5206 if ((*j)->control() == c) {
5210 TimeAxisView::Children kids = (*j)->get_child_list ();
5212 for (TimeAxisView::Children::iterator k = kids.begin(); k != kids.end(); ++k) {
5213 if ((*k)->control() == c) {
5223 Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
5227 for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
5228 TimeAxisView* tv = time_axis_view_from_stripable (*i);
5238 Editor::suspend_route_redisplay ()
5241 _routes->suspend_redisplay();
5246 Editor::resume_route_redisplay ()
5249 _routes->redisplay(); // queue redisplay
5250 _routes->resume_redisplay();
5255 Editor::add_vcas (VCAList& vlist)
5259 for (VCAList::iterator v = vlist.begin(); v != vlist.end(); ++v) {
5260 sl.push_back (boost::dynamic_pointer_cast<Stripable> (*v));
5263 add_stripables (sl);
5267 Editor::add_routes (RouteList& rlist)
5271 for (RouteList::iterator r = rlist.begin(); r != rlist.end(); ++r) {
5275 add_stripables (sl);
5279 Editor::add_stripables (StripableList& sl)
5281 list<TimeAxisView*> new_views;
5282 boost::shared_ptr<VCA> v;
5283 boost::shared_ptr<Route> r;
5284 TrackViewList new_selection;
5285 bool from_scratch = (track_views.size() == 0);
5287 sl.sort (Stripable::Sorter());
5289 for (StripableList::iterator s = sl.begin(); s != sl.end(); ++s) {
5291 if ((v = boost::dynamic_pointer_cast<VCA> (*s)) != 0) {
5293 VCATimeAxisView* vtv = new VCATimeAxisView (*this, _session, *_track_canvas);
5295 new_views.push_back (vtv);
5297 } else if ((r = boost::dynamic_pointer_cast<Route> (*s)) != 0) {
5299 if (r->is_auditioner() || r->is_monitor()) {
5303 RouteTimeAxisView* rtv;
5304 DataType dt = r->input()->default_type();
5306 if (dt == ARDOUR::DataType::AUDIO) {
5307 rtv = new AudioTimeAxisView (*this, _session, *_track_canvas);
5309 } else if (dt == ARDOUR::DataType::MIDI) {
5310 rtv = new MidiTimeAxisView (*this, _session, *_track_canvas);
5313 throw unknown_type();
5316 new_views.push_back (rtv);
5317 track_views.push_back (rtv);
5318 new_selection.push_back (rtv);
5320 rtv->effective_gain_display ();
5322 rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
5323 rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
5327 if (new_views.size() > 0) {
5328 _routes->time_axis_views_added (new_views);
5329 //_summary->routes_added (new_selection); /* XXX requires RouteTimeAxisViewList */
5332 /* note: !new_selection.empty() means that we got some routes rather
5336 if (!from_scratch && !new_selection.empty()) {
5337 selection->set (new_selection);
5338 begin_selection_op_history();
5341 if (show_editor_mixer_when_tracks_arrive && !new_selection.empty()) {
5342 show_editor_mixer (true);
5345 editor_list_button.set_sensitive (true);
5349 Editor::timeaxisview_deleted (TimeAxisView *tv)
5351 if (tv == entered_track) {
5355 if (_session && _session->deletion_in_progress()) {
5356 /* the situation is under control */
5360 ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
5362 RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
5364 _routes->route_removed (tv);
5366 TimeAxisView::Children c = tv->get_child_list ();
5367 for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
5368 if (entered_track == i->get()) {
5373 /* remove it from the list of track views */
5375 TrackViewList::iterator i;
5377 if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
5378 i = track_views.erase (i);
5381 /* update whatever the current mixer strip is displaying, if revelant */
5383 boost::shared_ptr<Route> route;
5386 route = rtav->route ();
5389 if (current_mixer_strip && current_mixer_strip->route() == route) {
5391 TimeAxisView* next_tv;
5393 if (track_views.empty()) {
5395 } else if (i == track_views.end()) {
5396 next_tv = track_views.front();
5401 // skip VCAs (cannot be selected, n/a in editor-mixer)
5402 if (dynamic_cast<VCATimeAxisView*> (next_tv)) {
5403 /* VCAs are sorted last in line -- route_sorter.h, jump to top */
5404 next_tv = track_views.front();
5406 if (dynamic_cast<VCATimeAxisView*> (next_tv)) {
5407 /* just in case: no master, only a VCA remains */
5413 set_selected_mixer_strip (*next_tv);
5415 /* make the editor mixer strip go away setting the
5416 * button to inactive (which also unticks the menu option)
5419 ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
5425 Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
5431 DisplaySuspender ds;
5432 PresentationInfo::ChangeSuspender cs;
5434 if (apply_to_selection) {
5435 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
5437 TrackSelection::iterator j = i;
5440 hide_track_in_display (*i, false);
5445 RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
5447 if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
5448 // this will hide the mixer strip
5449 set_selected_mixer_strip (*tv);
5452 _routes->hide_track_in_display (*tv);
5457 Editor::show_track_in_display (TimeAxisView* tv, bool move_into_view)
5462 _routes->show_track_in_display (*tv);
5463 if (move_into_view) {
5464 ensure_time_axis_view_is_visible (*tv, false);
5469 Editor::sync_track_view_list_and_routes ()
5471 track_views = TrackViewList (_routes->views ());
5473 _summary->set_background_dirty();
5474 _group_tabs->set_dirty ();
5476 return false; // do not call again (until needed)
5480 Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
5482 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5487 /** Find a StripableTimeAxisView by the ID of its stripable */
5488 StripableTimeAxisView*
5489 Editor::get_stripable_time_axis_by_id (const PBD::ID& id) const
5491 StripableTimeAxisView* v;
5493 for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
5494 if((v = dynamic_cast<StripableTimeAxisView*>(*i)) != 0) {
5495 if(v->stripable()->id() == id) {
5505 Editor::fit_route_group (RouteGroup *g)
5507 TrackViewList ts = axis_views_from_routes (g->route_list ());
5512 Editor::consider_auditioning (boost::shared_ptr<Region> region)
5514 boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5517 _session->cancel_audition ();
5521 if (_session->is_auditioning()) {
5522 _session->cancel_audition ();
5523 if (r == last_audition_region) {
5528 _session->audition_region (r);
5529 last_audition_region = r;
5534 Editor::hide_a_region (boost::shared_ptr<Region> r)
5536 r->set_hidden (true);
5540 Editor::show_a_region (boost::shared_ptr<Region> r)
5542 r->set_hidden (false);
5546 Editor::audition_region_from_region_list ()
5548 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5552 Editor::hide_region_from_region_list ()
5554 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5558 Editor::show_region_in_region_list ()
5560 _regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5564 Editor::step_edit_status_change (bool yn)
5567 start_step_editing ();
5569 stop_step_editing ();
5574 Editor::start_step_editing ()
5576 step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5580 Editor::stop_step_editing ()
5582 step_edit_connection.disconnect ();
5586 Editor::check_step_edit ()
5588 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5589 MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5591 mtv->check_step_edit ();
5595 return true; // do it again, till we stop
5599 Editor::scroll_press (Direction dir)
5601 ++_scroll_callbacks;
5603 if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5604 /* delay the first auto-repeat */
5610 scroll_backward (1);
5618 scroll_up_one_track ();
5622 scroll_down_one_track ();
5626 /* do hacky auto-repeat */
5627 if (!_scroll_connection.connected ()) {
5629 _scroll_connection = Glib::signal_timeout().connect (
5630 sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5633 _scroll_callbacks = 0;
5640 Editor::scroll_release ()
5642 _scroll_connection.disconnect ();
5645 /** Queue a change for the Editor viewport x origin to follow the playhead */
5647 Editor::reset_x_origin_to_follow_playhead ()
5649 samplepos_t const sample = playhead_cursor->current_sample ();
5651 if (sample < _leftmost_sample || sample > _leftmost_sample + current_page_samples()) {
5653 if (_session->transport_speed() < 0) {
5655 if (sample > (current_page_samples() / 2)) {
5656 center_screen (sample-(current_page_samples()/2));
5658 center_screen (current_page_samples()/2);
5665 if (sample < _leftmost_sample) {
5667 if (_session->transport_rolling()) {
5668 /* rolling; end up with the playhead at the right of the page */
5669 l = sample - current_page_samples ();
5671 /* not rolling: end up with the playhead 1/4 of the way along the page */
5672 l = sample - current_page_samples() / 4;
5676 if (_session->transport_rolling()) {
5677 /* rolling: end up with the playhead on the left of the page */
5680 /* not rolling: end up with the playhead 3/4 of the way along the page */
5681 l = sample - 3 * current_page_samples() / 4;
5689 center_screen_internal (l + (current_page_samples() / 2), current_page_samples ());
5695 Editor::super_rapid_screen_update ()
5697 if (!_session || !_session->engine().running()) {
5701 /* METERING / MIXER STRIPS */
5703 /* update track meters, if required */
5704 if (contents().is_mapped() && meters_running) {
5705 RouteTimeAxisView* rtv;
5706 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5707 if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5708 rtv->fast_update ();
5713 /* and any current mixer strip */
5714 if (current_mixer_strip) {
5715 current_mixer_strip->fast_update ();
5718 bool latent_locate = false;
5719 samplepos_t sample = _session->audible_sample (&latent_locate);
5720 const int64_t now = g_get_monotonic_time ();
5723 if (_session->exporting ()) {
5724 /* freewheel/export may be faster or slower than transport_speed() / SR.
5725 * Also exporting multiple ranges locates/jumps without a _pending_locate_request.
5727 _last_update_time = 0;
5730 if (_last_update_time > 0) {
5731 /* interpolate and smoothen playhead position */
5732 const double ds = (now - _last_update_time) * _session->transport_speed() * _session->nominal_sample_rate () * 1e-6;
5733 samplepos_t guess = playhead_cursor->current_sample () + rint (ds);
5734 err = sample - guess;
5736 guess += err * .12 + _err_screen_engine; // time-constant based on 25fps (super_rapid_screen_update)
5737 _err_screen_engine += .0144 * (err - _err_screen_engine); // tc^2
5740 printf ("eng: %ld gui:%ld (%+6.1f) diff: %6.1f (err: %7.2f)\n",
5742 err, _err_screen_engine);
5747 _err_screen_engine = 0;
5750 if (err > 8192 || latent_locate) {
5751 // in case of x-runs or freewheeling
5752 _last_update_time = 0;
5753 sample = _session->audible_sample ();
5755 _last_update_time = now;
5758 //snapped cursor stuff ( the snapped_cursor shows where an operation is going to occur )
5760 MusicSample where (sample, 0);
5761 if ( !UIConfiguration::instance().get_show_snapped_cursor() ) {
5762 snapped_cursor->hide ();
5763 } else if ( _edit_point == EditAtPlayhead && !_dragging_playhead) {
5764 snap_to (where); // can't use snap_to_with_modifier?
5765 snapped_cursor->set_position (where.sample);
5766 snapped_cursor->show ();
5767 } else if ( _edit_point == EditAtSelectedMarker ) {
5768 //NOTE: I don't think EditAtSelectedMarker should snap. they are what they are.
5769 //however, the current editing code -does- snap so I'll draw it that way for now.
5770 if ( !selection->markers.empty() ) {
5771 MusicSample ms (selection->markers.front()->position(), 0);
5772 snap_to (ms); // should use snap_to_with_modifier?
5773 snapped_cursor->set_position ( ms.sample );
5774 snapped_cursor->show ();
5776 } else if (mouse_sample (where.sample, ignored)) { //cursor is in the editing canvas. show it.
5777 snapped_cursor->show ();
5778 } else { //mouse is out of the editing canvas. hide the snapped_cursor
5779 snapped_cursor->hide ();
5782 /* There are a few reasons why we might not update the playhead / viewport stuff:
5784 * 1. we don't update things when there's a pending locate request, otherwise
5785 * when the editor requests a locate there is a chance that this method
5786 * will move the playhead before the locate request is processed, causing
5788 * 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5789 * 3. if we're still at the same frame that we were last time, there's nothing to do.
5791 if (_pending_locate_request) {
5792 _last_update_time = 0;
5796 if (_dragging_playhead) {
5797 _last_update_time = 0;
5801 if (playhead_cursor->current_sample () == sample) {
5805 playhead_cursor->set_position (sample);
5807 if (_session->requested_return_sample() >= 0) {
5808 _last_update_time = 0;
5812 if (!_follow_playhead || pending_visual_change.being_handled) {
5813 /* We only do this if we aren't already
5814 * handling a visual change (ie if
5815 * pending_visual_change.being_handled is
5816 * false) so that these requests don't stack
5817 * up there are too many of them to handle in
5823 if (!_stationary_playhead) {
5824 reset_x_origin_to_follow_playhead ();
5826 samplepos_t const sample = playhead_cursor->current_sample ();
5827 double target = ((double)sample - (double)current_page_samples() / 2.0);
5828 if (target <= 0.0) {
5831 // compare to EditorCursor::set_position()
5832 double const old_pos = sample_to_pixel_unrounded (_leftmost_sample);
5833 double const new_pos = sample_to_pixel_unrounded (target);
5834 if (rint (new_pos) != rint (old_pos)) {
5835 reset_x_origin (pixel_to_sample (new_pos));
5842 Editor::session_going_away ()
5844 _have_idled = false;
5846 _session_connections.drop_connections ();
5848 super_rapid_screen_update_connection.disconnect ();
5850 selection->clear ();
5851 cut_buffer->clear ();
5853 clicked_regionview = 0;
5854 clicked_axisview = 0;
5855 clicked_routeview = 0;
5856 entered_regionview = 0;
5858 _last_update_time = 0;
5861 playhead_cursor->hide ();
5863 /* rip everything out of the list displays */
5867 _route_groups->clear ();
5869 /* do this first so that deleting a track doesn't reset cms to null
5870 and thus cause a leak.
5873 if (current_mixer_strip) {
5874 if (current_mixer_strip->get_parent() != 0) {
5875 global_hpacker.remove (*current_mixer_strip);
5877 delete current_mixer_strip;
5878 current_mixer_strip = 0;
5881 /* delete all trackviews */
5883 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5886 track_views.clear ();
5888 nudge_clock->set_session (0);
5890 editor_list_button.set_active(false);
5891 editor_list_button.set_sensitive(false);
5893 /* clear tempo/meter rulers */
5894 remove_metric_marks ();
5895 clear_marker_display ();
5901 stop_step_editing ();
5905 /* get rid of any existing editor mixer strip */
5907 WindowTitle title(Glib::get_application_name());
5908 title += _("Editor");
5910 own_window()->set_title (title.get_string());
5913 SessionHandlePtr::session_going_away ();
5917 Editor::trigger_script (int i)
5919 LuaInstance::instance()-> call_action (i);
5923 Editor::show_editor_list (bool yn)
5926 _editor_list_vbox.show ();
5928 _editor_list_vbox.hide ();
5933 Editor::change_region_layering_order (bool from_context_menu)
5935 const samplepos_t position = get_preferred_edit_position (EDIT_IGNORE_NONE, from_context_menu);
5937 if (!clicked_routeview) {
5938 if (layering_order_editor) {
5939 layering_order_editor->hide ();
5944 boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5950 boost::shared_ptr<Playlist> pl = track->playlist();
5956 if (layering_order_editor == 0) {
5957 layering_order_editor = new RegionLayeringOrderEditor (*this);
5960 layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5961 layering_order_editor->maybe_present ();
5965 Editor::update_region_layering_order_editor ()
5967 if (layering_order_editor && layering_order_editor->is_visible ()) {
5968 change_region_layering_order (true);
5973 Editor::setup_fade_images ()
5975 _xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5976 _xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-symmetric")));
5977 _xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5978 _xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5979 _xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-constant-power")));
5981 _xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5982 _xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-symmetric")));
5983 _xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5984 _xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5985 _xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-constant-power")));
5989 /** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5991 Editor::action_menu_item (std::string const & name)
5993 Glib::RefPtr<Action> a = editor_actions->get_action (name);
5996 return *manage (a->create_menu_item ());
6000 Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
6002 EventBox* b = manage (new EventBox);
6003 b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
6004 Label* l = manage (new Label (name));
6008 _the_notebook.append_page (widget, *b);
6012 Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
6014 if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
6015 _the_notebook.set_current_page (_the_notebook.page_num (*page));
6018 if (ev->type == GDK_2BUTTON_PRESS) {
6020 /* double-click on a notebook tab shrinks or expands the notebook */
6022 if (_notebook_shrunk) {
6023 if (pre_notebook_shrink_pane_width) {
6024 edit_pane.set_divider (0, *pre_notebook_shrink_pane_width);
6026 _notebook_shrunk = false;
6028 pre_notebook_shrink_pane_width = edit_pane.get_divider();
6030 /* this expands the LHS of the edit pane to cover the notebook
6031 PAGE but leaves the tabs visible.
6033 edit_pane.set_divider (0, edit_pane.get_divider() + page->get_width());
6034 _notebook_shrunk = true;
6042 Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
6044 using namespace Menu_Helpers;
6046 MenuList& items = _control_point_context_menu.items ();
6049 items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
6050 items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
6051 if (!can_remove_control_point (item)) {
6052 items.back().set_sensitive (false);
6055 _control_point_context_menu.popup (event->button.button, event->button.time);
6059 Editor::popup_note_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
6061 using namespace Menu_Helpers;
6063 NoteBase* note = reinterpret_cast<NoteBase*>(item->get_data("notebase"));
6068 /* We need to get the selection here and pass it to the operations, since
6069 popping up the menu will cause a region leave event which clears
6070 entered_regionview. */
6072 MidiRegionView& mrv = note->region_view();
6073 const RegionSelection rs = get_regions_from_selection_and_entered ();
6074 const uint32_t sel_size = mrv.selection_size ();
6076 MenuList& items = _note_context_menu.items();
6080 items.push_back(MenuElem(_("Delete"),
6081 sigc::mem_fun(mrv, &MidiRegionView::delete_selection)));
6084 items.push_back(MenuElem(_("Edit..."),
6085 sigc::bind(sigc::mem_fun(*this, &Editor::edit_notes), &mrv)));
6086 if (sel_size != 1) {
6087 items.back().set_sensitive (false);
6090 items.push_back(MenuElem(_("Transpose..."),
6091 sigc::bind(sigc::mem_fun(*this, &Editor::transpose_regions), rs)));
6094 items.push_back(MenuElem(_("Legatize"),
6095 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, false)));
6097 items.back().set_sensitive (false);
6100 items.push_back(MenuElem(_("Quantize..."),
6101 sigc::bind(sigc::mem_fun(*this, &Editor::quantize_regions), rs)));
6103 items.push_back(MenuElem(_("Remove Overlap"),
6104 sigc::bind(sigc::mem_fun(*this, &Editor::legatize_regions), rs, true)));
6106 items.back().set_sensitive (false);
6109 items.push_back(MenuElem(_("Transform..."),
6110 sigc::bind(sigc::mem_fun(*this, &Editor::transform_regions), rs)));
6112 _note_context_menu.popup (event->button.button, event->button.time);
6116 Editor::zoom_vertical_modifier_released()
6118 _stepping_axis_view = 0;
6122 Editor::ui_parameter_changed (string parameter)
6124 if (parameter == "icon-set") {
6125 while (!_cursor_stack.empty()) {
6126 _cursor_stack.pop_back();
6128 _cursors->set_cursor_set (UIConfiguration::instance().get_icon_set());
6129 _cursor_stack.push_back(_cursors->grabber);
6130 edit_pane.set_drag_cursor (*_cursors->expand_left_right);
6131 editor_summary_pane.set_drag_cursor (*_cursors->expand_up_down);
6133 } else if (parameter == "draggable-playhead") {
6134 if (_verbose_cursor) {
6135 playhead_cursor->set_sensitive (UIConfiguration::instance().get_draggable_playhead());
6141 Editor::use_own_window (bool and_fill_it)
6143 bool new_window = !own_window();
6145 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
6147 if (win && new_window) {
6148 win->set_name ("EditorWindow");
6150 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Editor"), this);
6152 // win->signal_realize().connect (*this, &Editor::on_realize);
6153 win->signal_event().connect (sigc::bind (sigc::ptr_fun (&Keyboard::catch_user_event_for_pre_dialog_focus), win));
6154 win->signal_event().connect (sigc::mem_fun (*this, &Editor::generic_event_handler));
6155 win->set_data ("ardour-bindings", bindings);
6160 DisplaySuspender ds;
6161 contents().show_all ();
6163 /* XXX: this is a bit unfortunate; it would probably
6164 be nicer if we could just call show () above rather
6165 than needing the show_all ()
6168 /* re-hide stuff if necessary */
6169 editor_list_button_toggled ();
6170 parameter_changed ("show-summary");
6171 parameter_changed ("show-group-tabs");
6172 parameter_changed ("show-zoom-tools");
6174 /* now reset all audio_time_axis heights, because widgets might need
6180 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
6181 tv = (static_cast<TimeAxisView*>(*i));
6182 tv->reset_height ();
6185 if (current_mixer_strip) {
6186 current_mixer_strip->hide_things ();
6187 current_mixer_strip->parameter_changed ("mixer-element-visibility");