2
Copyright (C) 2000-2009 Paul Davis
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
/* Note: public Editor methods are documented in public_editor.h */
30
#include "ardour_ui.h"
32
* ardour_ui.h include was moved to the top of the list
33
* due to a conflicting definition of 'Style' between
34
* Apple's MacTypes.h and BarController.
37
#include <boost/none.hpp>
39
#include <sigc++/bind.h>
41
#include "pbd/convert.h"
42
#include "pbd/error.h"
43
#include "pbd/enumwriter.h"
44
#include "pbd/memento_command.h"
45
#include "pbd/unknown_type.h"
46
#include "pbd/unwind.h"
47
#include "pbd/stacktrace.h"
49
#include <glibmm/miscutils.h>
50
#include <gtkmm/image.h>
51
#include <gdkmm/color.h>
52
#include <gdkmm/bitmap.h>
54
#include "gtkmm2ext/bindings.h"
55
#include "gtkmm2ext/grouped_buttons.h"
56
#include "gtkmm2ext/gtk_ui.h"
57
#include "gtkmm2ext/tearoff.h"
58
#include "gtkmm2ext/utils.h"
59
#include "gtkmm2ext/window_title.h"
60
#include "gtkmm2ext/choice.h"
61
#include "gtkmm2ext/cell_renderer_pixbuf_toggle.h"
63
#include "ardour/audio_track.h"
64
#include "ardour/audioengine.h"
65
#include "ardour/audioregion.h"
66
#include "ardour/location.h"
67
#include "ardour/profile.h"
68
#include "ardour/route_group.h"
69
#include "ardour/session_playlists.h"
70
#include "ardour/tempo.h"
71
#include "ardour/utils.h"
73
#include "control_protocol/control_protocol.h"
77
#include "analysis_window.h"
78
#include "audio_clock.h"
79
#include "audio_region_view.h"
80
#include "audio_streamview.h"
81
#include "audio_time_axis.h"
82
#include "automation_time_axis.h"
83
#include "bundle_manager.h"
84
#include "canvas-noevent-text.h"
85
#include "canvas_impl.h"
86
#include "crossfade_edit.h"
90
#include "editor_cursors.h"
91
#include "editor_drag.h"
92
#include "editor_group_tabs.h"
93
#include "editor_locations.h"
94
#include "editor_regions.h"
95
#include "editor_route_groups.h"
96
#include "editor_routes.h"
97
#include "editor_snapshots.h"
98
#include "editor_summary.h"
99
#include "global_port_matrix.h"
100
#include "gui_object.h"
101
#include "gui_thread.h"
102
#include "keyboard.h"
104
#include "midi_time_axis.h"
105
#include "mixer_strip.h"
106
#include "mixer_ui.h"
107
#include "mouse_cursors.h"
108
#include "playlist_selector.h"
109
#include "public_editor.h"
110
#include "region_layering_order_editor.h"
111
#include "rgb_macros.h"
112
#include "rhythm_ferret.h"
113
#include "selection.h"
115
#include "simpleline.h"
116
#include "tempo_lines.h"
117
#include "time_axis_view.h"
123
using namespace ARDOUR;
126
using namespace Glib;
127
using namespace Gtkmm2ext;
128
using namespace Editing;
130
using PBD::internationalize;
132
using Gtkmm2ext::Keyboard;
134
const double Editor::timebar_height = 15.0;
136
static const gchar *_snap_type_strings[] = {
138
N_("Timecode Frames"),
139
N_("Timecode Seconds"),
140
N_("Timecode Minutes"),
170
static const gchar *_snap_mode_strings[] = {
177
static const gchar *_edit_point_strings[] = {
184
static const gchar *_zoom_focus_strings[] = {
194
#ifdef USE_RUBBERBAND
195
static const gchar *_rb_opt_strings[] = {
198
N_("Balanced multitimbral mixture"),
199
N_("Unpitched percussion with stable notes"),
200
N_("Crisp monophonic instrumental"),
201
N_("Unpitched solo percussion"),
202
N_("Resample without preserving pitch"),
208
pane_size_watcher (Paned* pane)
210
/* if the handle of a pane vanishes into (at least) the tabs of a notebook,
214
Quartz: impossible to access
216
so stop that by preventing it from ever getting too narrow. 35
217
pixels is basically a rough guess at the tab width.
222
int max_width_of_lhs = GTK_WIDGET(pane->gobj())->allocation.width - 35;
224
gint pos = pane->get_position ();
226
if (pos > max_width_of_lhs) {
227
pane->set_position (max_width_of_lhs);
232
: _join_object_range_state (JOIN_OBJECT_RANGE_NONE)
234
/* time display buttons */
235
, minsec_label (_("Mins:Secs"))
236
, bbt_label (_("Bars:Beats"))
237
, timecode_label (_("Timecode"))
238
, samples_label (_("Samples"))
239
, tempo_label (_("Tempo"))
240
, meter_label (_("Meter"))
241
, mark_label (_("Location Markers"))
242
, range_mark_label (_("Range Markers"))
243
, transport_mark_label (_("Loop/Punch Ranges"))
244
, cd_mark_label (_("CD Markers"))
245
, videotl_label (_("Video Timeline"))
246
, edit_packer (4, 4, true)
248
/* the values here don't matter: layout widgets
249
reset them as needed.
252
, vertical_adjustment (0.0, 0.0, 10.0, 400.0)
254
/* tool bar related */
256
, zoom_range_clock (new AudioClock (X_("zoomrange"), false, X_("zoom range"), true, false, true))
258
, toolbar_selection_clock_table (2,3)
260
, automation_mode_button (_("mode"))
262
, _toolbar_viewport (*manage (new Gtk::Adjustment (0, 0, 1e10)), *manage (new Gtk::Adjustment (0, 0, 1e10)))
266
, nudge_clock (new AudioClock (X_("nudge"), false, X_("nudge"), true, false, true))
267
, meters_running(false)
268
, _pending_locate_request (false)
269
, _pending_initial_locate (false)
270
, _last_cut_copy_source_track (0)
272
, _region_selection_change_updates_region_list (true)
273
, _following_mixer_selection (false)
274
, _control_point_toggled_on_press (false)
275
, _stepping_axis_view (0)
279
/* we are a singleton */
281
PublicEditor::_instance = this;
285
selection = new Selection (this);
286
cut_buffer = new Selection (this);
288
clicked_regionview = 0;
289
clicked_axisview = 0;
290
clicked_routeview = 0;
291
clicked_control_point = 0;
292
last_update_frame = 0;
293
pre_press_cursor = 0;
294
_drags = new DragManager (this);
295
current_mixer_strip = 0;
298
snap_type_strings = I18N (_snap_type_strings);
299
snap_mode_strings = I18N (_snap_mode_strings);
300
zoom_focus_strings = I18N (_zoom_focus_strings);
301
edit_point_strings = I18N (_edit_point_strings);
302
#ifdef USE_RUBBERBAND
303
rb_opt_strings = I18N (_rb_opt_strings);
307
snap_threshold = 5.0;
308
bbt_beat_subdivision = 4;
311
last_autoscroll_x = 0;
312
last_autoscroll_y = 0;
313
autoscroll_active = false;
314
autoscroll_timeout_tag = -1;
319
current_interthread_info = 0;
320
_show_measures = true;
322
show_gain_after_trim = false;
324
have_pending_keyboard_selection = false;
325
_follow_playhead = true;
326
_stationary_playhead = false;
327
editor_ruler_menu = 0;
328
no_ruler_shown_update = false;
330
range_marker_menu = 0;
331
marker_menu_item = 0;
332
tempo_or_meter_marker_menu = 0;
333
transport_marker_menu = 0;
334
new_transport_marker_menu = 0;
335
editor_mixer_strip_width = Wide;
336
show_editor_mixer_when_tracks_arrive = false;
337
region_edit_menu_split_multichannel_item = 0;
338
region_edit_menu_split_item = 0;
341
current_stepping_trackview = 0;
343
entered_regionview = 0;
345
clear_entered_track = false;
348
button_release_can_deselect = true;
349
_dragging_playhead = false;
350
_dragging_edit_point = false;
351
select_new_marker = false;
353
layering_order_editor = 0;
354
no_save_visual = false;
356
within_track_canvas = false;
358
scrubbing_direction = 0;
362
location_marker_color = ARDOUR_UI::config()->canvasvar_LocationMarker.get();
363
location_range_color = ARDOUR_UI::config()->canvasvar_LocationRange.get();
364
location_cd_marker_color = ARDOUR_UI::config()->canvasvar_LocationCDMarker.get();
365
location_loop_color = ARDOUR_UI::config()->canvasvar_LocationLoop.get();
366
location_punch_color = ARDOUR_UI::config()->canvasvar_LocationPunch.get();
368
_edit_point = EditAtMouse;
369
_internal_editing = false;
370
current_canvas_cursor = 0;
372
frames_per_unit = 2048; /* too early to use reset_zoom () */
374
_scroll_callbacks = 0;
376
zoom_focus = ZoomFocusLeft;
377
set_zoom_focus (ZoomFocusLeft);
378
zoom_range_clock->ValueChanged.connect (sigc::mem_fun(*this, &Editor::zoom_adjustment_changed));
380
bbt_label.set_name ("EditorRulerLabel");
381
bbt_label.set_size_request (-1, (int)timebar_height);
382
bbt_label.set_alignment (1.0, 0.5);
383
bbt_label.set_padding (5,0);
385
bbt_label.set_no_show_all();
386
minsec_label.set_name ("EditorRulerLabel");
387
minsec_label.set_size_request (-1, (int)timebar_height);
388
minsec_label.set_alignment (1.0, 0.5);
389
minsec_label.set_padding (5,0);
390
minsec_label.hide ();
391
minsec_label.set_no_show_all();
392
timecode_label.set_name ("EditorRulerLabel");
393
timecode_label.set_size_request (-1, (int)timebar_height);
394
timecode_label.set_alignment (1.0, 0.5);
395
timecode_label.set_padding (5,0);
396
timecode_label.hide ();
397
timecode_label.set_no_show_all();
398
samples_label.set_name ("EditorRulerLabel");
399
samples_label.set_size_request (-1, (int)timebar_height);
400
samples_label.set_alignment (1.0, 0.5);
401
samples_label.set_padding (5,0);
402
samples_label.hide ();
403
samples_label.set_no_show_all();
405
tempo_label.set_name ("EditorRulerLabel");
406
tempo_label.set_size_request (-1, (int)timebar_height);
407
tempo_label.set_alignment (1.0, 0.5);
408
tempo_label.set_padding (5,0);
410
tempo_label.set_no_show_all();
412
meter_label.set_name ("EditorRulerLabel");
413
meter_label.set_size_request (-1, (int)timebar_height);
414
meter_label.set_alignment (1.0, 0.5);
415
meter_label.set_padding (5,0);
417
meter_label.set_no_show_all();
419
mark_label.set_name ("EditorRulerLabel");
420
mark_label.set_size_request (-1, (int)timebar_height);
421
mark_label.set_alignment (1.0, 0.5);
422
mark_label.set_padding (5,0);
424
mark_label.set_no_show_all();
426
cd_mark_label.set_name ("EditorRulerLabel");
427
cd_mark_label.set_size_request (-1, (int)timebar_height);
428
cd_mark_label.set_alignment (1.0, 0.5);
429
cd_mark_label.set_padding (5,0);
430
cd_mark_label.hide();
431
cd_mark_label.set_no_show_all();
433
videotl_bar_height = 4;
434
videotl_label.set_name ("EditorRulerLabel");
435
videotl_label.set_size_request (-1, (int)timebar_height * videotl_bar_height);
436
videotl_label.set_alignment (1.0, 0.5);
437
videotl_label.set_padding (5,0);
438
videotl_label.hide();
439
videotl_label.set_no_show_all();
441
range_mark_label.set_name ("EditorRulerLabel");
442
range_mark_label.set_size_request (-1, (int)timebar_height);
443
range_mark_label.set_alignment (1.0, 0.5);
444
range_mark_label.set_padding (5,0);
445
range_mark_label.hide();
446
range_mark_label.set_no_show_all();
448
transport_mark_label.set_name ("EditorRulerLabel");
449
transport_mark_label.set_size_request (-1, (int)timebar_height);
450
transport_mark_label.set_alignment (1.0, 0.5);
451
transport_mark_label.set_padding (5,0);
452
transport_mark_label.hide();
453
transport_mark_label.set_no_show_all();
455
initialize_rulers ();
456
initialize_canvas ();
458
_summary = new EditorSummary (this);
460
selection->TimeChanged.connect (sigc::mem_fun(*this, &Editor::time_selection_changed));
461
selection->TracksChanged.connect (sigc::mem_fun(*this, &Editor::track_selection_changed));
463
editor_regions_selection_changed_connection = selection->RegionsChanged.connect (sigc::mem_fun(*this, &Editor::region_selection_changed));
465
selection->PointsChanged.connect (sigc::mem_fun(*this, &Editor::point_selection_changed));
466
selection->MarkersChanged.connect (sigc::mem_fun(*this, &Editor::marker_selection_changed));
468
edit_controls_vbox.set_spacing (0);
469
vertical_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &Editor::tie_vertical_scrolling), true);
470
track_canvas->signal_map_event().connect (sigc::mem_fun (*this, &Editor::track_canvas_map_handler));
472
HBox* h = manage (new HBox);
473
_group_tabs = new EditorGroupTabs (this);
474
h->pack_start (*_group_tabs, PACK_SHRINK);
475
h->pack_start (edit_controls_vbox);
476
controls_layout.add (*h);
478
controls_layout.set_name ("EditControlsBase");
479
controls_layout.add_events (Gdk::SCROLL_MASK);
480
controls_layout.signal_scroll_event().connect (sigc::mem_fun(*this, &Editor::control_layout_scroll), false);
482
controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
483
controls_layout.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::edit_controls_button_release));
485
_cursors = new MouseCursors;
487
ArdourCanvas::Canvas* time_pad = manage(new ArdourCanvas::Canvas());
488
ArdourCanvas::SimpleLine* pad_line_1 = manage(new ArdourCanvas::SimpleLine(*time_pad->root(),
489
0.0, 1.0, 100.0, 1.0));
491
pad_line_1->property_color_rgba() = 0xFF0000FF;
496
time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars) + 2);
497
time_canvas_vbox.set_size_request (-1, -1);
499
ruler_label_event_box.add (ruler_label_vbox);
500
ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
501
ruler_label_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
503
time_button_event_box.add (time_button_vbox);
504
time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
505
time_button_event_box.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::ruler_label_button_release));
507
/* these enable us to have a dedicated window (for cursor setting, etc.)
508
for the canvas areas.
511
track_canvas_event_box.add (*track_canvas);
513
time_canvas_event_box.add (time_canvas_vbox);
514
time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
516
edit_packer.set_col_spacings (0);
517
edit_packer.set_row_spacings (0);
518
edit_packer.set_homogeneous (false);
519
edit_packer.set_border_width (0);
520
edit_packer.set_name ("EditorWindow");
522
/* labels for the rulers */
523
edit_packer.attach (ruler_label_event_box, 1, 2, 0, 1, FILL, SHRINK, 0, 0);
524
/* labels for the marker "tracks" */
525
edit_packer.attach (time_button_event_box, 1, 2, 1, 2, FILL, SHRINK, 0, 0);
527
edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0);
529
edit_packer.attach (controls_layout, 0, 2, 2, 3, FILL, FILL|EXPAND, 0, 0);
531
edit_packer.attach (track_canvas_event_box, 2, 3, 1, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
533
bottom_hbox.set_border_width (2);
534
bottom_hbox.set_spacing (3);
536
_route_groups = new EditorRouteGroups (this);
537
_routes = new EditorRoutes (this);
538
_regions = new EditorRegions (this);
539
_snapshots = new EditorSnapshots (this);
540
_locations = new EditorLocations (this);
542
add_notebook_page (_("Regions"), _regions->widget ());
543
add_notebook_page (_("Tracks & Busses"), _routes->widget ());
544
add_notebook_page (_("Snapshots"), _snapshots->widget ());
545
add_notebook_page (_("Track & Bus Groups"), _route_groups->widget ());
546
add_notebook_page (_("Ranges & Marks"), _locations->widget ());
548
_the_notebook.set_show_tabs (true);
549
_the_notebook.set_scrollable (true);
550
_the_notebook.popup_disable ();
551
_the_notebook.set_tab_pos (Gtk::POS_RIGHT);
552
_the_notebook.show_all ();
554
_notebook_shrunk = false;
556
editor_summary_pane.pack1(edit_packer);
558
Button* summary_arrows_left_left = manage (new Button);
559
summary_arrows_left_left->add (*manage (new Arrow (ARROW_LEFT, SHADOW_NONE)));
560
summary_arrows_left_left->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), LEFT)));
561
summary_arrows_left_left->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
563
Button* summary_arrows_left_right = manage (new Button);
564
summary_arrows_left_right->add (*manage (new Arrow (ARROW_RIGHT, SHADOW_NONE)));
565
summary_arrows_left_right->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), RIGHT)));
566
summary_arrows_left_right->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
568
VBox* summary_arrows_left = manage (new VBox);
569
summary_arrows_left->pack_start (*summary_arrows_left_left);
570
summary_arrows_left->pack_start (*summary_arrows_left_right);
572
Button* summary_arrows_right_up = manage (new Button);
573
summary_arrows_right_up->add (*manage (new Arrow (ARROW_UP, SHADOW_NONE)));
574
summary_arrows_right_up->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), UP)));
575
summary_arrows_right_up->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
577
Button* summary_arrows_right_down = manage (new Button);
578
summary_arrows_right_down->add (*manage (new Arrow (ARROW_DOWN, SHADOW_NONE)));
579
summary_arrows_right_down->signal_pressed().connect (sigc::hide_return (sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), DOWN)));
580
summary_arrows_right_down->signal_released().connect (sigc::mem_fun (*this, &Editor::scroll_release));
582
VBox* summary_arrows_right = manage (new VBox);
583
summary_arrows_right->pack_start (*summary_arrows_right_up);
584
summary_arrows_right->pack_start (*summary_arrows_right_down);
586
Frame* summary_frame = manage (new Frame);
587
summary_frame->set_shadow_type (Gtk::SHADOW_ETCHED_IN);
589
summary_frame->add (*_summary);
590
summary_frame->show ();
592
_summary_hbox.pack_start (*summary_arrows_left, false, false);
593
_summary_hbox.pack_start (*summary_frame, true, true);
594
_summary_hbox.pack_start (*summary_arrows_right, false, false);
596
editor_summary_pane.pack2 (_summary_hbox);
598
edit_pane.pack1 (editor_summary_pane, true, true);
599
edit_pane.pack2 (_the_notebook, false, true);
601
editor_summary_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun (*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&editor_summary_pane)));
603
/* XXX: editor_summary_pane might need similar to the edit_pane */
605
edit_pane.signal_size_allocate().connect (sigc::bind (sigc::mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
607
Glib::PropertyProxy<int> proxy = edit_pane.property_position();
608
proxy.signal_changed().connect (bind (sigc::ptr_fun (pane_size_watcher), static_cast<Paned*> (&edit_pane)));
610
top_hbox.pack_start (toolbar_frame);
612
HBox *hbox = manage (new HBox);
613
hbox->pack_start (edit_pane, true, true);
615
global_vpacker.pack_start (top_hbox, false, false);
616
global_vpacker.pack_start (*hbox, true, true);
618
global_hpacker.pack_start (global_vpacker, true, true);
620
set_name ("EditorWindow");
621
add_accel_group (ActionManager::ui_manager->get_accel_group());
623
status_bar_hpacker.show ();
625
vpacker.pack_end (status_bar_hpacker, false, false);
626
vpacker.pack_end (global_hpacker, true, true);
628
/* register actions now so that set_state() can find them and set toggles/checks etc */
631
/* when we start using our own keybinding system for the editor, this
632
* will be uncommented
638
_snap_type = SnapToBeat;
639
set_snap_to (_snap_type);
640
_snap_mode = SnapOff;
641
set_snap_mode (_snap_mode);
642
set_mouse_mode (MouseObject, true);
643
pre_internal_mouse_mode = MouseObject;
644
pre_internal_snap_type = _snap_type;
645
pre_internal_snap_mode = _snap_mode;
646
internal_snap_type = _snap_type;
647
internal_snap_mode = _snap_mode;
648
set_edit_point_preference (EditAtMouse, true);
650
_playlist_selector = new PlaylistSelector();
651
_playlist_selector->signal_delete_event().connect (sigc::bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
653
RegionView::RegionViewGoingAway.connect (*this, invalidator (*this), boost::bind (&Editor::catch_vanishing_regionview, this, _1), gui_context());
657
nudge_forward_button.set_name ("zoom button");
658
nudge_forward_button.add_elements (ArdourButton::FlatFace);
659
nudge_forward_button.set_image(::get_icon("nudge_right"));
661
nudge_backward_button.set_name ("zoom button");
662
nudge_backward_button.add_elements (ArdourButton::FlatFace);
663
nudge_backward_button.set_image(::get_icon("nudge_left"));
665
fade_context_menu.set_name ("ArdourContextMenu");
667
/* icons, titles, WM stuff */
669
list<Glib::RefPtr<Gdk::Pixbuf> > window_icons;
670
Glib::RefPtr<Gdk::Pixbuf> icon;
672
if ((icon = ::get_icon ("ardour_icon_16px")) != 0) {
673
window_icons.push_back (icon);
675
if ((icon = ::get_icon ("ardour_icon_22px")) != 0) {
676
window_icons.push_back (icon);
678
if ((icon = ::get_icon ("ardour_icon_32px")) != 0) {
679
window_icons.push_back (icon);
681
if ((icon = ::get_icon ("ardour_icon_48px")) != 0) {
682
window_icons.push_back (icon);
684
if (!window_icons.empty()) {
685
// set_icon_list (window_icons);
686
set_default_icon_list (window_icons);
689
WindowTitle title(Glib::get_application_name());
690
title += _("Editor");
691
set_title (title.get_string());
692
set_wmclass (X_("ardour_editor"), PROGRAM_NAME);
695
add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
697
signal_configure_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
698
signal_delete_event().connect (sigc::mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
700
Gtkmm2ext::Keyboard::the_keyboard().ZoomVerticalModifierReleased.connect (sigc::mem_fun (*this, &Editor::zoom_vertical_modifier_released));
702
/* allow external control surfaces/protocols to do various things */
704
ControlProtocol::ZoomToSession.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_session, this), gui_context());
705
ControlProtocol::ZoomIn.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, false), gui_context());
706
ControlProtocol::ZoomOut.connect (*this, invalidator (*this), boost::bind (&Editor::temporal_zoom_step, this, true), gui_context());
707
ControlProtocol::Undo.connect (*this, invalidator (*this), boost::bind (&Editor::undo, this, true), gui_context());
708
ControlProtocol::Redo.connect (*this, invalidator (*this), boost::bind (&Editor::redo, this, true), gui_context());
709
ControlProtocol::ScrollTimeline.connect (*this, invalidator (*this), boost::bind (&Editor::control_scroll, this, _1), gui_context());
710
ControlProtocol::StepTracksUp.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_up, this), gui_context());
711
ControlProtocol::StepTracksDown.connect (*this, invalidator (*this), boost::bind (&Editor::control_step_tracks_down, this), gui_context());
712
ControlProtocol::GotoView.connect (*this, invalidator (*this), boost::bind (&Editor::control_view, this, _1), gui_context());
713
ControlProtocol::CloseDialog.connect (*this, invalidator (*this), Keyboard::close_current_dialog, gui_context());
714
ControlProtocol::VerticalZoomInAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_all, this), gui_context());
715
ControlProtocol::VerticalZoomOutAll.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_all, this), gui_context());
716
ControlProtocol::VerticalZoomInSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_in_selected, this), gui_context());
717
ControlProtocol::VerticalZoomOutSelected.connect (*this, invalidator (*this), boost::bind (&Editor::control_vertical_zoom_out_selected, this), gui_context());
719
ControlProtocol::AddRouteToSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Add), gui_context());
720
ControlProtocol::RemoveRouteFromSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
721
ControlProtocol::SetRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Set), gui_context());
722
ControlProtocol::ToggleRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_select, this, _1, Selection::Toggle), gui_context());
723
ControlProtocol::ClearRouteSelection.connect (*this, invalidator (*this), boost::bind (&Editor::control_unselect, this), gui_context());
725
BasicUI::AccessAction.connect (*this, invalidator (*this), boost::bind (&Editor::access_action, this, _1, _2), gui_context());
727
/* problematic: has to return a value and thus cannot be x-thread */
729
Session::AskAboutPlaylistDeletion.connect_same_thread (*this, boost::bind (&Editor::playlist_deletion_dialog, this, _1));
731
Config->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
733
TimeAxisView::CatchDeletion.connect (*this, invalidator (*this), boost::bind (&Editor::timeaxisview_deleted, this, _1), gui_context());
735
_ignore_region_action = false;
736
_last_region_menu_was_main = false;
737
_popup_region_menu_item = 0;
739
_show_marker_lines = false;
740
_over_region_trim_target = false;
742
/* Button bindings */
744
button_bindings = new Bindings;
746
XMLNode* node = button_settings();
748
for (XMLNodeList::const_iterator i = node->children().begin(); i != node->children().end(); ++i) {
749
button_bindings->load (**i);
756
setup_fade_images ();
761
delete button_bindings;
763
delete _route_groups;
769
Editor::button_settings () const
771
XMLNode* settings = ARDOUR_UI::instance()->editor_settings();
772
XMLNode* node = find_named_node (*settings, X_("Buttons"));
775
node = new XMLNode (X_("Buttons"));
782
Editor::add_toplevel_controls (Container& cont)
784
vpacker.pack_start (cont, false, false);
789
Editor::get_smart_mode () const
791
return ( (current_mouse_mode() == Editing::MouseObject) && smart_mode_action->get_active() );
795
Editor::catch_vanishing_regionview (RegionView *rv)
797
/* note: the selection will take care of the vanishing
798
audioregionview by itself.
801
if (_drags->active() && _drags->have_item (rv->get_canvas_group()) && !_drags->ending()) {
805
if (clicked_regionview == rv) {
806
clicked_regionview = 0;
809
if (entered_regionview == rv) {
810
set_entered_regionview (0);
813
if (!_all_region_actions_sensitized) {
814
sensitize_all_region_actions (true);
817
_over_region_trim_target = false;
821
Editor::set_entered_regionview (RegionView* rv)
823
if (rv == entered_regionview) {
827
if (entered_regionview) {
828
entered_regionview->exited ();
831
if ((entered_regionview = rv) != 0) {
832
entered_regionview->entered (internal_editing ());
835
if (!_all_region_actions_sensitized && _last_region_menu_was_main) {
836
/* This RegionView entry might have changed what region actions
837
are allowed, so sensitize them all in case a key is pressed.
839
sensitize_all_region_actions (true);
844
Editor::set_entered_track (TimeAxisView* tav)
847
entered_track->exited ();
850
if ((entered_track = tav) != 0) {
851
entered_track->entered ();
856
Editor::show_window ()
858
if (!is_visible ()) {
861
/* XXX: this is a bit unfortunate; it would probably
862
be nicer if we could just call show () above rather
863
than needing the show_all ()
866
/* re-hide stuff if necessary */
867
editor_list_button_toggled ();
868
parameter_changed ("show-summary");
869
parameter_changed ("show-group-tabs");
870
parameter_changed ("show-zoom-tools");
872
/* now reset all audio_time_axis heights, because widgets might need
878
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
879
tv = (static_cast<TimeAxisView*>(*i));
883
if (current_mixer_strip) {
884
current_mixer_strip->hide_things ();
885
current_mixer_strip->parameter_changed ("mixer-strip-visibility");
893
Editor::instant_save ()
895
if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
900
_session->add_instant_xml(get_state());
902
Config->add_instant_xml(get_state());
907
Editor::zoom_adjustment_changed ()
913
double fpu = zoom_range_clock->current_duration() / _canvas_width;
914
bool clamped = clamp_frames_per_unit (fpu);
917
zoom_range_clock->set ((framepos_t) floor (fpu * _canvas_width));
924
Editor::control_vertical_zoom_in_all ()
926
tav_zoom_smooth (false, true);
930
Editor::control_vertical_zoom_out_all ()
932
tav_zoom_smooth (true, true);
936
Editor::control_vertical_zoom_in_selected ()
938
tav_zoom_smooth (false, false);
942
Editor::control_vertical_zoom_out_selected ()
944
tav_zoom_smooth (true, false);
948
Editor::control_view (uint32_t view)
950
goto_visual_state (view);
954
Editor::control_unselect ()
956
selection->clear_tracks ();
960
Editor::control_select (uint32_t rid, Selection::Operation op)
962
/* handles the (static) signal from the ControlProtocol class that
963
* requests setting the selected track to a given RID
970
boost::shared_ptr<Route> r = _session->route_by_remote_id (rid);
976
TimeAxisView* tav = axis_view_from_route (r);
981
selection->add (tav);
983
case Selection::Toggle:
984
selection->toggle (tav);
986
case Selection::Extend:
989
selection->set (tav);
993
selection->clear_tracks ();
998
Editor::control_step_tracks_up ()
1000
scroll_tracks_up_line ();
1004
Editor::control_step_tracks_down ()
1006
scroll_tracks_down_line ();
1010
Editor::control_scroll (float fraction)
1012
ENSURE_GUI_THREAD (*this, &Editor::control_scroll, fraction)
1018
double step = fraction * current_page_frames();
1021
_control_scroll_target is an optional<T>
1023
it acts like a pointer to an framepos_t, with
1024
a operator conversion to boolean to check
1025
that it has a value could possibly use
1026
playhead_cursor->current_frame to store the
1027
value and a boolean in the class to know
1028
when it's out of date
1031
if (!_control_scroll_target) {
1032
_control_scroll_target = _session->transport_frame();
1033
_dragging_playhead = true;
1036
if ((fraction < 0.0f) && (*_control_scroll_target < (framepos_t) fabs(step))) {
1037
*_control_scroll_target = 0;
1038
} else if ((fraction > 0.0f) && (max_framepos - *_control_scroll_target < step)) {
1039
*_control_scroll_target = max_framepos - (current_page_frames()*2); // allow room for slop in where the PH is on the screen
1041
*_control_scroll_target += (framepos_t) floor (step);
1044
/* move visuals, we'll catch up with it later */
1046
playhead_cursor->set_position (*_control_scroll_target);
1047
UpdateAllTransportClocks (*_control_scroll_target);
1049
if (*_control_scroll_target > (current_page_frames() / 2)) {
1050
/* try to center PH in window */
1051
reset_x_origin (*_control_scroll_target - (current_page_frames()/2));
1057
Now we do a timeout to actually bring the session to the right place
1058
according to the playhead. This is to avoid reading disk buffers on every
1059
call to control_scroll, which is driven by ScrollTimeline and therefore
1060
probably by a control surface wheel which can generate lots of events.
1062
/* cancel the existing timeout */
1064
control_scroll_connection.disconnect ();
1066
/* add the next timeout */
1068
control_scroll_connection = Glib::signal_timeout().connect (sigc::bind (sigc::mem_fun (*this, &Editor::deferred_control_scroll), *_control_scroll_target), 250);
1072
Editor::deferred_control_scroll (framepos_t /*target*/)
1074
_session->request_locate (*_control_scroll_target, _session->transport_rolling());
1075
// reset for next stream
1076
_control_scroll_target = boost::none;
1077
_dragging_playhead = false;
1082
Editor::access_action (std::string action_group, std::string action_item)
1088
ENSURE_GUI_THREAD (*this, &Editor::access_action, action_group, action_item)
1091
act = ActionManager::get_action( action_group.c_str(), action_item.c_str() );
1099
Editor::on_realize ()
1101
Window::on_realize ();
1106
Editor::map_position_change (framepos_t frame)
1108
ENSURE_GUI_THREAD (*this, &Editor::map_position_change, frame)
1110
if (_session == 0) {
1114
if (_follow_playhead) {
1115
center_screen (frame);
1118
playhead_cursor->set_position (frame);
1122
Editor::center_screen (framepos_t frame)
1124
double page = _canvas_width * frames_per_unit;
1126
/* if we're off the page, then scroll.
1129
if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1130
center_screen_internal (frame, page);
1135
Editor::center_screen_internal (framepos_t frame, float page)
1140
frame -= (framepos_t) page;
1145
reset_x_origin (frame);
1150
Editor::update_title ()
1152
ENSURE_GUI_THREAD (*this, &Editor::update_title)
1155
bool dirty = _session->dirty();
1157
string session_name;
1159
if (_session->snap_name() != _session->name()) {
1160
session_name = _session->snap_name();
1162
session_name = _session->name();
1166
session_name = "*" + session_name;
1169
WindowTitle title(session_name);
1170
title += Glib::get_application_name();
1171
set_title (title.get_string());
1173
/* ::session_going_away() will have taken care of it */
1178
Editor::set_session (Session *t)
1180
SessionHandlePtr::set_session (t);
1186
zoom_range_clock->set_session (_session);
1187
_playlist_selector->set_session (_session);
1188
nudge_clock->set_session (_session);
1189
_summary->set_session (_session);
1190
_group_tabs->set_session (_session);
1191
_route_groups->set_session (_session);
1192
_regions->set_session (_session);
1193
_snapshots->set_session (_session);
1194
_routes->set_session (_session);
1195
_locations->set_session (_session);
1197
if (rhythm_ferret) {
1198
rhythm_ferret->set_session (_session);
1201
if (analysis_window) {
1202
analysis_window->set_session (_session);
1206
sfbrowser->set_session (_session);
1209
compute_fixed_ruler_scale ();
1211
/* Make sure we have auto loop and auto punch ranges */
1213
Location* loc = _session->locations()->auto_loop_location();
1215
loc = new Location (*_session, 0, _session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1217
if (loc->start() == loc->end()) {
1218
loc->set_end (loc->start() + 1);
1221
_session->locations()->add (loc, false);
1222
_session->set_auto_loop_location (loc);
1225
loc->set_name (_("Loop"));
1228
loc = _session->locations()->auto_punch_location();
1231
loc = new Location (*_session, 0, _session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1233
if (loc->start() == loc->end()) {
1234
loc->set_end (loc->start() + 1);
1237
_session->locations()->add (loc, false);
1238
_session->set_auto_punch_location (loc);
1241
loc->set_name (_("Punch"));
1244
refresh_location_display ();
1246
/* This must happen after refresh_location_display(), as (amongst other things) we restore
1247
the selected Marker; this needs the LocationMarker list to be available.
1249
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1250
set_state (*node, Stateful::loading_state_version);
1252
/* catch up with the playhead */
1254
_session->request_locate (playhead_cursor->current_frame);
1255
_pending_initial_locate = true;
1259
/* These signals can all be emitted by a non-GUI thread. Therefore the
1260
handlers for them must not attempt to directly interact with the GUI,
1261
but use Gtkmm2ext::UI::instance()->call_slot();
1264
_session->StepEditStatusChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::step_edit_status_change, this, _1), gui_context());
1265
_session->TransportStateChange.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_transport_state, this), gui_context());
1266
_session->PositionChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::map_position_change, this, _1), gui_context());
1267
_session->RouteAdded.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_routes, this, _1), gui_context());
1268
_session->DirtyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::update_title, this), gui_context());
1269
_session->tempo_map().PropertyChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::tempo_map_changed, this, _1), gui_context());
1270
_session->Located.connect (_session_connections, invalidator (*this), boost::bind (&Editor::located, this), gui_context());
1271
_session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::parameter_changed, this, _1), gui_context());
1272
_session->StateSaved.connect (_session_connections, invalidator (*this), boost::bind (&Editor::session_state_saved, this, _1), gui_context());
1273
_session->locations()->added.connect (_session_connections, invalidator (*this), boost::bind (&Editor::add_new_location, this, _1), gui_context());
1274
_session->locations()->removed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::location_gone, this, _1), gui_context());
1275
_session->locations()->changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1276
_session->locations()->StateChanged.connect (_session_connections, invalidator (*this), boost::bind (&Editor::refresh_location_display, this), gui_context());
1277
_session->history().Changed.connect (_session_connections, invalidator (*this), boost::bind (&Editor::history_changed, this), gui_context());
1279
playhead_cursor->canvas_item.show ();
1281
boost::function<void (string)> pc (boost::bind (&Editor::parameter_changed, this, _1));
1282
Config->map_parameters (pc);
1283
_session->config.map_parameters (pc);
1285
restore_ruler_visibility ();
1286
//tempo_map_changed (PropertyChange (0));
1287
_session->tempo_map().apply_with_metrics (*this, &Editor::draw_metric_marks);
1289
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1290
(static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1293
super_rapid_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (
1294
sigc::mem_fun (*this, &Editor::super_rapid_screen_update)
1297
switch (_snap_type) {
1298
case SnapToRegionStart:
1299
case SnapToRegionEnd:
1300
case SnapToRegionSync:
1301
case SnapToRegionBoundary:
1302
build_region_boundary_cache ();
1309
/* register for undo history */
1310
_session->register_with_memento_command_factory(id(), this);
1312
ActionManager::ui_manager->signal_pre_activate().connect (sigc::mem_fun (*this, &Editor::action_pre_activated));
1314
start_updating_meters ();
1318
Editor::action_pre_activated (Glib::RefPtr<Action> const & a)
1320
if (a->get_name() == "RegionMenu") {
1321
/* When the main menu's region menu is opened, we setup the actions so that they look right
1322
in the menu. I can't find a way of getting a signal when this menu is subsequently closed,
1323
so we resensitize all region actions when the entered regionview or the region selection
1324
changes. HOWEVER we can't always resensitize on entered_regionview change because that
1325
happens after the region context menu is opened. So we set a flag here, too.
1329
sensitize_the_right_region_actions ();
1330
_last_region_menu_was_main = true;
1335
Editor::fill_xfade_menu (Menu_Helpers::MenuList& items, bool start)
1337
using namespace Menu_Helpers;
1339
void (Editor::*emf)(FadeShape);
1340
std::map<ARDOUR::FadeShape,Gtk::Image*>* images;
1343
images = &_xfade_in_images;
1344
emf = &Editor::set_fade_in_shape;
1346
images = &_xfade_out_images;
1347
emf = &Editor::set_fade_out_shape;
1352
_("Linear (for highly correlated material)"),
1353
*(*images)[FadeLinear],
1354
sigc::bind (sigc::mem_fun (*this, emf), FadeLinear)
1358
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1362
_("Constant power"),
1363
*(*images)[FadeConstantPower],
1364
sigc::bind (sigc::mem_fun (*this, emf), FadeConstantPower)
1367
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1372
*(*images)[FadeSymmetric],
1373
sigc::bind (sigc::mem_fun (*this, emf), FadeSymmetric)
1377
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1382
*(*images)[FadeSlow],
1383
sigc::bind (sigc::mem_fun (*this, emf), FadeSlow)
1386
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1391
*(*images)[FadeFast],
1392
sigc::bind (sigc::mem_fun (*this, emf), FadeFast)
1395
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1398
/** Pop up a context menu for when the user clicks on a start crossfade */
1400
Editor::popup_xfade_in_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/)
1402
using namespace Menu_Helpers;
1404
MenuList& items (xfade_in_context_menu.items());
1406
if (items.empty()) {
1407
fill_xfade_menu (items, true);
1410
xfade_in_context_menu.popup (button, time);
1413
/** Pop up a context menu for when the user clicks on an end crossfade */
1415
Editor::popup_xfade_out_context_menu (int button, int32_t time, ArdourCanvas::Item* /*item*/, ItemType /*item_type*/)
1417
using namespace Menu_Helpers;
1419
MenuList& items (xfade_out_context_menu.items());
1421
if (items.empty()) {
1422
fill_xfade_menu (items, false);
1425
xfade_out_context_menu.popup (button, time);
1429
/** Pop up a context menu for when the user clicks on a fade in or fade out */
1431
Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1433
using namespace Menu_Helpers;
1434
AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1437
fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1441
MenuList& items (fade_context_menu.items());
1444
switch (item_type) {
1446
case FadeInHandleItem:
1447
if (arv->audio_region()->fade_in_active()) {
1448
items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), false)));
1450
items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_active), true)));
1453
items.push_back (SeparatorElem());
1455
if (Profile->get_sae()) {
1457
items.push_back (MenuElem (_("Linear"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeLinear)));
1458
items.push_back (MenuElem (_("Slowest"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeFast)));
1465
*_fade_in_images[FadeLinear],
1466
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeLinear)
1470
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1475
*_fade_in_images[FadeSlow],
1476
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSlow)
1479
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1484
*_fade_in_images[FadeFast],
1485
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeFast)
1488
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1493
*_fade_in_images[FadeSymmetric],
1494
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeSymmetric)
1499
_("Constant power"),
1500
*_fade_in_images[FadeConstantPower],
1501
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_in_shape), FadeConstantPower)
1504
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1510
case FadeOutHandleItem:
1511
if (arv->audio_region()->fade_out_active()) {
1512
items.push_back (MenuElem (_("Deactivate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), false)));
1514
items.push_back (MenuElem (_("Activate"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_active), true)));
1517
items.push_back (SeparatorElem());
1519
if (Profile->get_sae()) {
1520
items.push_back (MenuElem (_("Linear"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeLinear)));
1521
items.push_back (MenuElem (_("Slowest"), sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSlow)));
1527
*_fade_out_images[FadeLinear],
1528
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeLinear)
1532
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1537
*_fade_out_images[FadeSlow],
1538
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSlow)
1541
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1546
*_fade_out_images[FadeFast],
1547
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeFast)
1550
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1555
*_fade_out_images[FadeSymmetric],
1556
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeSymmetric)
1561
_("Constant power"),
1562
*_fade_out_images[FadeConstantPower],
1563
sigc::bind (sigc::mem_fun (*this, &Editor::set_fade_out_shape), FadeConstantPower)
1566
dynamic_cast<ImageMenuItem*>(&items.back())->set_always_show_image ();
1572
fatal << _("programming error: ")
1573
<< X_("non-fade canvas item passed to popup_fade_context_menu()")
1578
fade_context_menu.popup (button, time);
1582
Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection)
1584
using namespace Menu_Helpers;
1585
Menu* (Editor::*build_menu_function)();
1588
switch (item_type) {
1590
case RegionViewName:
1591
case RegionViewNameHighlight:
1592
case LeftFrameHandle:
1593
case RightFrameHandle:
1594
if (with_selection) {
1595
build_menu_function = &Editor::build_track_selection_context_menu;
1597
build_menu_function = &Editor::build_track_region_context_menu;
1602
if (with_selection) {
1603
build_menu_function = &Editor::build_track_selection_context_menu;
1605
build_menu_function = &Editor::build_track_context_menu;
1610
if (clicked_routeview->track()) {
1611
build_menu_function = &Editor::build_track_context_menu;
1613
build_menu_function = &Editor::build_track_bus_context_menu;
1618
/* probably shouldn't happen but if it does, we don't care */
1622
menu = (this->*build_menu_function)();
1623
menu->set_name ("ArdourContextMenu");
1625
/* now handle specific situations */
1627
switch (item_type) {
1629
case RegionViewName:
1630
case RegionViewNameHighlight:
1631
case LeftFrameHandle:
1632
case RightFrameHandle:
1633
if (!with_selection) {
1634
if (region_edit_menu_split_item) {
1635
if (clicked_regionview && clicked_regionview->region()->covers (get_preferred_edit_position())) {
1636
ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, true);
1638
ActionManager::set_sensitive (ActionManager::edit_point_in_region_sensitive_actions, false);
1641
if (region_edit_menu_split_multichannel_item) {
1642
if (clicked_regionview && clicked_regionview->region()->n_channels() > 1) {
1643
region_edit_menu_split_multichannel_item->set_sensitive (true);
1645
region_edit_menu_split_multichannel_item->set_sensitive (false);
1658
/* probably shouldn't happen but if it does, we don't care */
1662
if (item_type != SelectionItem && clicked_routeview && clicked_routeview->audio_track()) {
1664
/* Bounce to disk */
1666
using namespace Menu_Helpers;
1667
MenuList& edit_items = menu->items();
1669
edit_items.push_back (SeparatorElem());
1671
switch (clicked_routeview->audio_track()->freeze_state()) {
1672
case AudioTrack::NoFreeze:
1673
edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1676
case AudioTrack::Frozen:
1677
edit_items.push_back (MenuElem (_("Unfreeze"), sigc::mem_fun(*this, &Editor::unfreeze_route)));
1680
case AudioTrack::UnFrozen:
1681
edit_items.push_back (MenuElem (_("Freeze"), sigc::mem_fun(*this, &Editor::freeze_route)));
1687
if (item_type == StreamItem && clicked_routeview) {
1688
clicked_routeview->build_underlay_menu(menu);
1691
/* When the region menu is opened, we setup the actions so that they look right
1694
sensitize_the_right_region_actions ();
1695
_last_region_menu_was_main = false;
1697
menu->signal_hide().connect (sigc::bind (sigc::mem_fun (*this, &Editor::sensitize_all_region_actions), true));
1698
menu->popup (button, time);
1702
Editor::build_track_context_menu ()
1704
using namespace Menu_Helpers;
1706
MenuList& edit_items = track_context_menu.items();
1709
add_dstream_context_items (edit_items);
1710
return &track_context_menu;
1714
Editor::build_track_bus_context_menu ()
1716
using namespace Menu_Helpers;
1718
MenuList& edit_items = track_context_menu.items();
1721
add_bus_context_items (edit_items);
1722
return &track_context_menu;
1726
Editor::build_track_region_context_menu ()
1728
using namespace Menu_Helpers;
1729
MenuList& edit_items = track_region_context_menu.items();
1732
/* we've just cleared the track region context menu, so the menu that these
1733
two items were on will have disappeared; stop them dangling.
1735
region_edit_menu_split_item = 0;
1736
region_edit_menu_split_multichannel_item = 0;
1738
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (clicked_axisview);
1741
boost::shared_ptr<Track> tr;
1742
boost::shared_ptr<Playlist> pl;
1744
if ((tr = rtv->track())) {
1745
add_region_context_items (edit_items, tr);
1749
add_dstream_context_items (edit_items);
1751
return &track_region_context_menu;
1755
Editor::analyze_region_selection ()
1757
if (analysis_window == 0) {
1758
analysis_window = new AnalysisWindow();
1761
analysis_window->set_session(_session);
1763
analysis_window->show_all();
1766
analysis_window->set_regionmode();
1767
analysis_window->analyze();
1769
analysis_window->present();
1773
Editor::analyze_range_selection()
1775
if (analysis_window == 0) {
1776
analysis_window = new AnalysisWindow();
1779
analysis_window->set_session(_session);
1781
analysis_window->show_all();
1784
analysis_window->set_rangemode();
1785
analysis_window->analyze();
1787
analysis_window->present();
1791
Editor::build_track_selection_context_menu ()
1793
using namespace Menu_Helpers;
1794
MenuList& edit_items = track_selection_context_menu.items();
1795
edit_items.clear ();
1797
add_selection_context_items (edit_items);
1798
// edit_items.push_back (SeparatorElem());
1799
// add_dstream_context_items (edit_items);
1801
return &track_selection_context_menu;
1805
Editor::add_region_context_items (Menu_Helpers::MenuList& edit_items, boost::shared_ptr<Track> track)
1807
using namespace Menu_Helpers;
1809
/* OK, stick the region submenu at the top of the list, and then add
1813
RegionSelection rs = get_regions_from_selection_and_entered ();
1815
string::size_type pos = 0;
1816
string menu_item_name = (rs.size() == 1) ? rs.front()->region()->name() : _("Selected Regions");
1818
/* we have to hack up the region name because "_" has a special
1819
meaning for menu titles.
1822
while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1823
menu_item_name.replace (pos, 1, "__");
1827
if (_popup_region_menu_item == 0) {
1828
_popup_region_menu_item = new MenuItem (menu_item_name);
1829
_popup_region_menu_item->set_submenu (*dynamic_cast<Menu*> (ActionManager::get_widget (X_("/PopupRegionMenu"))));
1830
_popup_region_menu_item->show ();
1832
_popup_region_menu_item->set_label (menu_item_name);
1835
const framepos_t position = get_preferred_edit_position (false, true);
1837
edit_items.push_back (*_popup_region_menu_item);
1838
if (track->playlist()->count_regions_at (position) > 1 && (layering_order_editor == 0 || !layering_order_editor->is_visible ())) {
1839
edit_items.push_back (*manage (_region_actions->get_action ("choose-top-region-context-menu")->create_menu_item ()));
1841
edit_items.push_back (SeparatorElem());
1844
/** Add context menu items relevant to selection ranges.
1845
* @param edit_items List to add the items to.
1848
Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1850
using namespace Menu_Helpers;
1852
edit_items.push_back (MenuElem (_("Play Range"), sigc::mem_fun(*this, &Editor::play_selection)));
1853
edit_items.push_back (MenuElem (_("Loop Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), true)));
1855
edit_items.push_back (SeparatorElem());
1856
edit_items.push_back (MenuElem (_("Spectral Analysis"), sigc::mem_fun(*this, &Editor::analyze_range_selection)));
1858
edit_items.push_back (SeparatorElem());
1860
edit_items.push_back (
1862
_("Move Range Start to Previous Region Boundary"),
1863
sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, false)
1867
edit_items.push_back (
1869
_("Move Range Start to Next Region Boundary"),
1870
sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), false, true)
1874
edit_items.push_back (
1876
_("Move Range End to Previous Region Boundary"),
1877
sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, false)
1881
edit_items.push_back (
1883
_("Move Range End to Next Region Boundary"),
1884
sigc::bind (sigc::mem_fun (*this, &Editor::move_range_selection_start_or_end_to_region_boundary), true, true)
1888
edit_items.push_back (SeparatorElem());
1889
edit_items.push_back (MenuElem (_("Convert to Region In-Place"), mem_fun(*this, &Editor::separate_region_from_selection)));
1890
edit_items.push_back (MenuElem (_("Convert to Region in Region List"), sigc::mem_fun(*this, &Editor::new_region_from_selection)));
1892
edit_items.push_back (SeparatorElem());
1893
edit_items.push_back (MenuElem (_("Select All in Range"), sigc::mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
1895
edit_items.push_back (SeparatorElem());
1896
edit_items.push_back (MenuElem (_("Set Loop from Range"), sigc::bind (sigc::mem_fun(*this, &Editor::set_loop_from_selection), false)));
1897
edit_items.push_back (MenuElem (_("Set Punch from Range"), sigc::mem_fun(*this, &Editor::set_punch_from_selection)));
1899
edit_items.push_back (SeparatorElem());
1900
edit_items.push_back (MenuElem (_("Add Range Markers"), sigc::mem_fun (*this, &Editor::add_location_from_selection)));
1902
edit_items.push_back (SeparatorElem());
1903
edit_items.push_back (MenuElem (_("Crop Region to Range"), sigc::mem_fun(*this, &Editor::crop_region_to_selection)));
1904
edit_items.push_back (MenuElem (_("Fill Range with Region"), sigc::mem_fun(*this, &Editor::region_fill_selection)));
1905
edit_items.push_back (MenuElem (_("Duplicate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::duplicate_range), false)));
1907
edit_items.push_back (SeparatorElem());
1908
edit_items.push_back (MenuElem (_("Consolidate Range"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, false)));
1909
edit_items.push_back (MenuElem (_("Consolidate Range With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), true, true)));
1910
edit_items.push_back (MenuElem (_("Bounce Range to Region List"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, false)));
1911
edit_items.push_back (MenuElem (_("Bounce Range to Region List With Processing"), sigc::bind (sigc::mem_fun(*this, &Editor::bounce_range_selection), false, true)));
1912
edit_items.push_back (MenuElem (_("Export Range..."), sigc::mem_fun(*this, &Editor::export_selection)));
1917
Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1919
using namespace Menu_Helpers;
1923
Menu *play_menu = manage (new Menu);
1924
MenuList& play_items = play_menu->items();
1925
play_menu->set_name ("ArdourContextMenu");
1927
play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
1928
play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
1929
play_items.push_back (MenuElem (_("Play Region"), sigc::mem_fun(*this, &Editor::play_selected_region)));
1930
play_items.push_back (SeparatorElem());
1931
play_items.push_back (MenuElem (_("Loop Region"), sigc::bind (sigc::mem_fun (*this, &Editor::set_loop_from_region), true)));
1933
edit_items.push_back (MenuElem (_("Play"), *play_menu));
1937
Menu *select_menu = manage (new Menu);
1938
MenuList& select_items = select_menu->items();
1939
select_menu->set_name ("ArdourContextMenu");
1941
select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
1942
select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
1943
select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
1944
select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
1945
select_items.push_back (SeparatorElem());
1946
select_items.push_back (MenuElem (_("Set Range to Loop Range"), sigc::mem_fun(*this, &Editor::set_selection_from_loop)));
1947
select_items.push_back (MenuElem (_("Set Range to Punch Range"), sigc::mem_fun(*this, &Editor::set_selection_from_punch)));
1948
select_items.push_back (SeparatorElem());
1949
select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
1950
select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
1951
select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
1952
select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
1953
select_items.push_back (MenuElem (_("Select All Between Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), false)));
1954
select_items.push_back (MenuElem (_("Select All Within Playhead and Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_between), true)));
1955
select_items.push_back (MenuElem (_("Select Range Between Playhead and Edit Point"), sigc::mem_fun(*this, &Editor::select_range_between)));
1957
edit_items.push_back (MenuElem (_("Select"), *select_menu));
1961
Menu *cutnpaste_menu = manage (new Menu);
1962
MenuList& cutnpaste_items = cutnpaste_menu->items();
1963
cutnpaste_menu->set_name ("ArdourContextMenu");
1965
cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
1966
cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
1967
cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
1969
cutnpaste_items.push_back (SeparatorElem());
1971
cutnpaste_items.push_back (MenuElem (_("Align"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions), ARDOUR::SyncPoint)));
1972
cutnpaste_items.push_back (MenuElem (_("Align Relative"), sigc::bind (sigc::mem_fun (*this, &Editor::align_regions_relative), ARDOUR::SyncPoint)));
1974
edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1976
/* Adding new material */
1978
edit_items.push_back (SeparatorElem());
1979
edit_items.push_back (MenuElem (_("Insert Selected Region"), sigc::bind (sigc::mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1980
edit_items.push_back (MenuElem (_("Insert Existing Media"), sigc::bind (sigc::mem_fun(*this, &Editor::add_external_audio_action), ImportToTrack)));
1984
Menu *nudge_menu = manage (new Menu());
1985
MenuList& nudge_items = nudge_menu->items();
1986
nudge_menu->set_name ("ArdourContextMenu");
1988
edit_items.push_back (SeparatorElem());
1989
nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
1990
nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
1991
nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
1992
nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
1994
edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1998
Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
2000
using namespace Menu_Helpers;
2004
Menu *play_menu = manage (new Menu);
2005
MenuList& play_items = play_menu->items();
2006
play_menu->set_name ("ArdourContextMenu");
2008
play_items.push_back (MenuElem (_("Play From Edit Point"), sigc::mem_fun(*this, &Editor::play_from_edit_point)));
2009
play_items.push_back (MenuElem (_("Play From Start"), sigc::mem_fun(*this, &Editor::play_from_start)));
2010
edit_items.push_back (MenuElem (_("Play"), *play_menu));
2014
Menu *select_menu = manage (new Menu);
2015
MenuList& select_items = select_menu->items();
2016
select_menu->set_name ("ArdourContextMenu");
2018
select_items.push_back (MenuElem (_("Select All in Track"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_in_track), Selection::Set)));
2019
select_items.push_back (MenuElem (_("Select All"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all), Selection::Set)));
2020
select_items.push_back (MenuElem (_("Invert Selection in Track"), sigc::mem_fun(*this, &Editor::invert_selection_in_track)));
2021
select_items.push_back (MenuElem (_("Invert Selection"), sigc::mem_fun(*this, &Editor::invert_selection)));
2022
select_items.push_back (SeparatorElem());
2023
select_items.push_back (MenuElem (_("Select All After Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), true)));
2024
select_items.push_back (MenuElem (_("Select All Before Edit Point"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_edit), false)));
2025
select_items.push_back (MenuElem (_("Select All After Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, true)));
2026
select_items.push_back (MenuElem (_("Select All Before Playhead"), sigc::bind (sigc::mem_fun(*this, &Editor::select_all_selectables_using_cursor), playhead_cursor, false)));
2028
edit_items.push_back (MenuElem (_("Select"), *select_menu));
2032
Menu *cutnpaste_menu = manage (new Menu);
2033
MenuList& cutnpaste_items = cutnpaste_menu->items();
2034
cutnpaste_menu->set_name ("ArdourContextMenu");
2036
cutnpaste_items.push_back (MenuElem (_("Cut"), sigc::mem_fun(*this, &Editor::cut)));
2037
cutnpaste_items.push_back (MenuElem (_("Copy"), sigc::mem_fun(*this, &Editor::copy)));
2038
cutnpaste_items.push_back (MenuElem (_("Paste"), sigc::bind (sigc::mem_fun(*this, &Editor::paste), 1.0f, true)));
2040
Menu *nudge_menu = manage (new Menu());
2041
MenuList& nudge_items = nudge_menu->items();
2042
nudge_menu->set_name ("ArdourContextMenu");
2044
edit_items.push_back (SeparatorElem());
2045
nudge_items.push_back (MenuElem (_("Nudge Entire Track Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, true))));
2046
nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Later"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, true))));
2047
nudge_items.push_back (MenuElem (_("Nudge Entire Track Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), false, false))));
2048
nudge_items.push_back (MenuElem (_("Nudge Track After Edit Point Earlier"), (sigc::bind (sigc::mem_fun(*this, &Editor::nudge_track), true, false))));
2050
edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
2054
Editor::snap_type() const
2060
Editor::snap_mode() const
2066
Editor::set_snap_to (SnapType st)
2068
unsigned int snap_ind = (unsigned int)st;
2072
if (snap_ind > snap_type_strings.size() - 1) {
2074
_snap_type = (SnapType)snap_ind;
2077
string str = snap_type_strings[snap_ind];
2079
if (str != snap_type_selector.get_active_text()) {
2080
snap_type_selector.set_active_text (str);
2085
switch (_snap_type) {
2086
case SnapToBeatDiv128:
2087
case SnapToBeatDiv64:
2088
case SnapToBeatDiv32:
2089
case SnapToBeatDiv28:
2090
case SnapToBeatDiv24:
2091
case SnapToBeatDiv20:
2092
case SnapToBeatDiv16:
2093
case SnapToBeatDiv14:
2094
case SnapToBeatDiv12:
2095
case SnapToBeatDiv10:
2096
case SnapToBeatDiv8:
2097
case SnapToBeatDiv7:
2098
case SnapToBeatDiv6:
2099
case SnapToBeatDiv5:
2100
case SnapToBeatDiv4:
2101
case SnapToBeatDiv3:
2102
case SnapToBeatDiv2: {
2103
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
2104
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
2106
compute_current_bbt_points (leftmost_frame, leftmost_frame + current_page_frames(),
2107
current_bbt_points_begin, current_bbt_points_end);
2108
compute_bbt_ruler_scale (leftmost_frame, leftmost_frame + current_page_frames(),
2109
current_bbt_points_begin, current_bbt_points_end);
2110
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
2114
case SnapToRegionStart:
2115
case SnapToRegionEnd:
2116
case SnapToRegionSync:
2117
case SnapToRegionBoundary:
2118
build_region_boundary_cache ();
2126
SnapChanged (); /* EMIT SIGNAL */
2130
Editor::set_snap_mode (SnapMode mode)
2132
string str = snap_mode_strings[(int)mode];
2134
if (_internal_editing) {
2135
internal_snap_mode = mode;
2137
pre_internal_snap_mode = mode;
2142
if (str != snap_mode_selector.get_active_text ()) {
2143
snap_mode_selector.set_active_text (str);
2149
Editor::set_edit_point_preference (EditPoint ep, bool force)
2151
bool changed = (_edit_point != ep);
2154
string str = edit_point_strings[(int)ep];
2156
if (str != edit_point_selector.get_active_text ()) {
2157
edit_point_selector.set_active_text (str);
2160
set_canvas_cursor ();
2162
if (!force && !changed) {
2166
const char* action=NULL;
2168
switch (_edit_point) {
2169
case EditAtPlayhead:
2170
action = "edit-at-playhead";
2172
case EditAtSelectedMarker:
2173
action = "edit-at-marker";
2176
action = "edit-at-mouse";
2180
Glib::RefPtr<Action> act = ActionManager::get_action ("Editor", action);
2182
Glib::RefPtr<RadioAction>::cast_dynamic(act)->set_active (true);
2186
bool in_track_canvas;
2188
if (!mouse_frame (foo, in_track_canvas)) {
2189
in_track_canvas = false;
2192
reset_canvas_action_sensitivity (in_track_canvas);
2198
Editor::set_state (const XMLNode& node, int /*version*/)
2200
const XMLProperty* prop;
2207
g.base_width = default_width;
2208
g.base_height = default_height;
2212
if ((geometry = find_named_node (node, "geometry")) != 0) {
2216
if ((prop = geometry->property("x_size")) == 0) {
2217
prop = geometry->property ("x-size");
2220
g.base_width = atoi(prop->value());
2222
if ((prop = geometry->property("y_size")) == 0) {
2223
prop = geometry->property ("y-size");
2226
g.base_height = atoi(prop->value());
2229
if ((prop = geometry->property ("x_pos")) == 0) {
2230
prop = geometry->property ("x-pos");
2233
x = atoi (prop->value());
2236
if ((prop = geometry->property ("y_pos")) == 0) {
2237
prop = geometry->property ("y-pos");
2240
y = atoi (prop->value());
2244
set_default_size (g.base_width, g.base_height);
2247
if (_session && (prop = node.property ("playhead"))) {
2249
sscanf (prop->value().c_str(), "%" PRIi64, &pos);
2250
playhead_cursor->set_position (pos);
2252
playhead_cursor->set_position (0);
2255
if ((prop = node.property ("mixer-width"))) {
2256
editor_mixer_strip_width = Width (string_2_enum (prop->value(), editor_mixer_strip_width));
2259
if ((prop = node.property ("zoom-focus"))) {
2260
set_zoom_focus ((ZoomFocus) string_2_enum (prop->value(), zoom_focus));
2263
if ((prop = node.property ("zoom"))) {
2264
reset_zoom (PBD::atof (prop->value()));
2266
reset_zoom (frames_per_unit);
2269
if ((prop = node.property ("snap-to"))) {
2270
set_snap_to ((SnapType) string_2_enum (prop->value(), _snap_type));
2273
if ((prop = node.property ("snap-mode"))) {
2274
set_snap_mode ((SnapMode) string_2_enum (prop->value(), _snap_mode));
2277
if ((prop = node.property ("internal-snap-to"))) {
2278
internal_snap_type = (SnapType) string_2_enum (prop->value(), internal_snap_type);
2281
if ((prop = node.property ("internal-snap-mode"))) {
2282
internal_snap_mode = (SnapMode) string_2_enum (prop->value(), internal_snap_mode);
2285
if ((prop = node.property ("pre-internal-snap-to"))) {
2286
pre_internal_snap_type = (SnapType) string_2_enum (prop->value(), pre_internal_snap_type);
2290
if ((prop = node.property ("pre-internal-snap-mode"))) {
2291
pre_internal_snap_mode = (SnapMode) string_2_enum (prop->value(), pre_internal_snap_mode);
2294
if ((prop = node.property ("mouse-mode"))) {
2295
MouseMode m = str2mousemode(prop->value());
2296
set_mouse_mode (m, true);
2298
set_mouse_mode (MouseObject, true);
2301
if ((prop = node.property ("left-frame")) != 0) {
2303
if (sscanf (prop->value().c_str(), "%" PRId64, &pos) == 1) {
2307
reset_x_origin (pos);
2311
if ((prop = node.property ("y-origin")) != 0) {
2312
reset_y_origin (atof (prop->value ()));
2315
if ((prop = node.property ("internal-edit"))) {
2316
bool yn = string_is_affirmative (prop->value());
2317
RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("toggle-internal-edit"));
2319
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2320
tact->set_active (!yn);
2321
tact->set_active (yn);
2325
if ((prop = node.property ("join-object-range"))) {
2326
RefPtr<Action> act = ActionManager::get_action (X_("MouseMode"), X_("set-mouse-mode-object-range"));
2327
bool yn = string_is_affirmative (prop->value());
2329
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2330
tact->set_active (!yn);
2331
tact->set_active (yn);
2333
set_mouse_mode(mouse_mode, true);
2336
if ((prop = node.property ("edit-point"))) {
2337
set_edit_point_preference ((EditPoint) string_2_enum (prop->value(), _edit_point), true);
2340
if ((prop = node.property ("show-measures"))) {
2341
bool yn = string_is_affirmative (prop->value());
2342
_show_measures = yn;
2343
RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2345
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2346
/* do it twice to force the change */
2347
tact->set_active (!yn);
2348
tact->set_active (yn);
2352
if ((prop = node.property ("follow-playhead"))) {
2353
bool yn = string_is_affirmative (prop->value());
2354
set_follow_playhead (yn);
2355
RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
2357
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2358
if (tact->get_active() != yn) {
2359
tact->set_active (yn);
2364
if ((prop = node.property ("stationary-playhead"))) {
2365
bool yn = string_is_affirmative (prop->value());
2366
set_stationary_playhead (yn);
2367
RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
2369
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2370
if (tact->get_active() != yn) {
2371
tact->set_active (yn);
2376
if ((prop = node.property ("region-list-sort-type"))) {
2377
RegionListSortType st;
2378
_regions->reset_sort_type ((RegionListSortType) string_2_enum (prop->value(), st), true);
2381
if ((prop = node.property ("show-editor-mixer"))) {
2383
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2386
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2387
bool yn = string_is_affirmative (prop->value());
2389
/* do it twice to force the change */
2391
tact->set_active (!yn);
2392
tact->set_active (yn);
2395
if ((prop = node.property ("show-editor-list"))) {
2397
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2400
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2401
bool yn = string_is_affirmative (prop->value());
2403
/* do it twice to force the change */
2405
tact->set_active (!yn);
2406
tact->set_active (yn);
2409
if ((prop = node.property (X_("editor-list-page")))) {
2410
_the_notebook.set_current_page (atoi (prop->value ()));
2413
if ((prop = node.property (X_("show-marker-lines")))) {
2414
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-marker-lines"));
2416
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic (act);
2417
bool yn = string_is_affirmative (prop->value ());
2419
tact->set_active (!yn);
2420
tact->set_active (yn);
2423
XMLNodeList children = node.children ();
2424
for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
2425
selection->set_state (**i, Stateful::current_state_version);
2426
_regions->set_state (**i);
2429
if ((prop = node.property ("maximised"))) {
2430
bool yn = string_is_affirmative (prop->value());
2432
ActionManager::do_action ("Common", "ToggleMaximalEditor");
2436
if ((prop = node.property ("nudge-clock-value"))) {
2438
sscanf (prop->value().c_str(), "%" PRId64, &f);
2439
nudge_clock->set (f);
2441
nudge_clock->set_mode (AudioClock::Timecode);
2442
nudge_clock->set (_session->frame_rate() * 5, true);
2449
Editor::get_state ()
2451
XMLNode* node = new XMLNode ("Editor");
2454
id().print (buf, sizeof (buf));
2455
node->add_property ("id", buf);
2457
if (is_realized()) {
2458
Glib::RefPtr<Gdk::Window> win = get_window();
2460
int x, y, width, height;
2461
win->get_root_origin(x, y);
2462
win->get_size(width, height);
2464
XMLNode* geometry = new XMLNode ("geometry");
2466
snprintf(buf, sizeof(buf), "%d", width);
2467
geometry->add_property("x-size", string(buf));
2468
snprintf(buf, sizeof(buf), "%d", height);
2469
geometry->add_property("y-size", string(buf));
2470
snprintf(buf, sizeof(buf), "%d", x);
2471
geometry->add_property("x-pos", string(buf));
2472
snprintf(buf, sizeof(buf), "%d", y);
2473
geometry->add_property("y-pos", string(buf));
2474
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2475
geometry->add_property("edit-horizontal-pane-pos", string(buf));
2476
geometry->add_property("notebook-shrunk", _notebook_shrunk ? "1" : "0");
2477
snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&editor_summary_pane)->gobj()));
2478
geometry->add_property("edit-vertical-pane-pos", string(buf));
2480
node->add_child_nocopy (*geometry);
2483
maybe_add_mixer_strip_width (*node);
2485
node->add_property ("zoom-focus", enum_2_string (zoom_focus));
2486
snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2487
node->add_property ("zoom", buf);
2488
node->add_property ("snap-to", enum_2_string (_snap_type));
2489
node->add_property ("snap-mode", enum_2_string (_snap_mode));
2490
node->add_property ("internal-snap-to", enum_2_string (internal_snap_type));
2491
node->add_property ("internal-snap-mode", enum_2_string (internal_snap_mode));
2492
node->add_property ("pre-internal-snap-to", enum_2_string (pre_internal_snap_type));
2493
node->add_property ("pre-internal-snap-mode", enum_2_string (pre_internal_snap_mode));
2494
node->add_property ("edit-point", enum_2_string (_edit_point));
2496
snprintf (buf, sizeof (buf), "%" PRIi64, playhead_cursor->current_frame);
2497
node->add_property ("playhead", buf);
2498
snprintf (buf, sizeof (buf), "%" PRIi64, leftmost_frame);
2499
node->add_property ("left-frame", buf);
2500
snprintf (buf, sizeof (buf), "%f", vertical_adjustment.get_value ());
2501
node->add_property ("y-origin", buf);
2503
node->add_property ("show-measures", _show_measures ? "yes" : "no");
2504
node->add_property ("maximised", _maximised ? "yes" : "no");
2505
node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2506
node->add_property ("stationary-playhead", _stationary_playhead ? "yes" : "no");
2507
node->add_property ("region-list-sort-type", enum_2_string (_regions->sort_type ()));
2508
node->add_property ("mouse-mode", enum2str(mouse_mode));
2509
node->add_property ("internal-edit", _internal_editing ? "yes" : "no");
2510
node->add_property ("join-object-range", smart_mode_action->get_active () ? "yes" : "no");
2512
Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2514
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2515
node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2518
act = ActionManager::get_action (X_("Editor"), X_("show-editor-list"));
2520
Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2521
node->add_property (X_("show-editor-list"), tact->get_active() ? "yes" : "no");
2524
snprintf (buf, sizeof (buf), "%d", _the_notebook.get_current_page ());
2525
node->add_property (X_("editor-list-page"), buf);
2527
if (button_bindings) {
2528
XMLNode* bb = new XMLNode (X_("Buttons"));
2529
button_bindings->save (*bb);
2530
node->add_child_nocopy (*bb);
2533
node->add_property (X_("show-marker-lines"), _show_marker_lines ? "yes" : "no");
2535
node->add_child_nocopy (selection->get_state ());
2536
node->add_child_nocopy (_regions->get_state ());
2538
snprintf (buf, sizeof (buf), "%" PRId64, nudge_clock->current_duration());
2539
node->add_property ("nudge-clock-value", buf);
2546
/** @param y y offset from the top of all trackviews.
2547
* @return pair: TimeAxisView that y is over, layer index.
2548
* TimeAxisView may be 0. Layer index is the layer number if the TimeAxisView is valid and is
2549
* in stacked or expanded region display mode, otherwise 0.
2551
std::pair<TimeAxisView *, double>
2552
Editor::trackview_by_y_position (double y)
2554
for (TrackViewList::iterator iter = track_views.begin(); iter != track_views.end(); ++iter) {
2556
std::pair<TimeAxisView*, double> const r = (*iter)->covers_y_position (y);
2562
return std::make_pair ( (TimeAxisView *) 0, 0);
2565
/** Snap a position to the grid, if appropriate, taking into account current
2566
* grid settings and also the state of any snap modifier keys that may be pressed.
2567
* @param start Position to snap.
2568
* @param event Event to get current key modifier information from, or 0.
2571
Editor::snap_to_with_modifier (framepos_t& start, GdkEvent const * event, int32_t direction, bool for_mark)
2573
if (!_session || !event) {
2577
if (Keyboard::modifier_state_contains (event->button.state, Keyboard::snap_modifier())) {
2578
if (_snap_mode == SnapOff) {
2579
snap_to_internal (start, direction, for_mark);
2582
if (_snap_mode != SnapOff) {
2583
snap_to_internal (start, direction, for_mark);
2589
Editor::snap_to (framepos_t& start, int32_t direction, bool for_mark)
2591
if (!_session || _snap_mode == SnapOff) {
2595
snap_to_internal (start, direction, for_mark);
2599
Editor::timecode_snap_to_internal (framepos_t& start, int32_t direction, bool /*for_mark*/)
2601
const framepos_t one_timecode_second = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame());
2602
framepos_t one_timecode_minute = (framepos_t)(rint(_session->timecode_frames_per_second()) * _session->frames_per_timecode_frame() * 60);
2604
switch (_snap_type) {
2605
case SnapToTimecodeFrame:
2606
if (((direction == 0) && (fmod((double)start, (double)_session->frames_per_timecode_frame()) > (_session->frames_per_timecode_frame() / 2))) || (direction > 0)) {
2607
start = (framepos_t) (ceil ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2609
start = (framepos_t) (floor ((double) start / _session->frames_per_timecode_frame()) * _session->frames_per_timecode_frame());
2613
case SnapToTimecodeSeconds:
2614
if (_session->config.get_timecode_offset_negative()) {
2615
start += _session->config.get_timecode_offset ();
2617
start -= _session->config.get_timecode_offset ();
2619
if (((direction == 0) && (start % one_timecode_second > one_timecode_second / 2)) || direction > 0) {
2620
start = (framepos_t) ceil ((double) start / one_timecode_second) * one_timecode_second;
2622
start = (framepos_t) floor ((double) start / one_timecode_second) * one_timecode_second;
2625
if (_session->config.get_timecode_offset_negative()) {
2626
start -= _session->config.get_timecode_offset ();
2628
start += _session->config.get_timecode_offset ();
2632
case SnapToTimecodeMinutes:
2633
if (_session->config.get_timecode_offset_negative()) {
2634
start += _session->config.get_timecode_offset ();
2636
start -= _session->config.get_timecode_offset ();
2638
if (((direction == 0) && (start % one_timecode_minute > one_timecode_minute / 2)) || direction > 0) {
2639
start = (framepos_t) ceil ((double) start / one_timecode_minute) * one_timecode_minute;
2641
start = (framepos_t) floor ((double) start / one_timecode_minute) * one_timecode_minute;
2643
if (_session->config.get_timecode_offset_negative()) {
2644
start -= _session->config.get_timecode_offset ();
2646
start += _session->config.get_timecode_offset ();
2650
fatal << "Editor::smpte_snap_to_internal() called with non-timecode snap type!" << endmsg;
2656
Editor::snap_to_internal (framepos_t& start, int32_t direction, bool for_mark)
2658
const framepos_t one_second = _session->frame_rate();
2659
const framepos_t one_minute = _session->frame_rate() * 60;
2660
framepos_t presnap = start;
2664
switch (_snap_type) {
2665
case SnapToTimecodeFrame:
2666
case SnapToTimecodeSeconds:
2667
case SnapToTimecodeMinutes:
2668
return timecode_snap_to_internal (start, direction, for_mark);
2671
if (((direction == 0) && (start % (one_second/75) > (one_second/75) / 2)) || (direction > 0)) {
2672
start = (framepos_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2674
start = (framepos_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2679
if (((direction == 0) && (start % one_second > one_second / 2)) || (direction > 0)) {
2680
start = (framepos_t) ceil ((double) start / one_second) * one_second;
2682
start = (framepos_t) floor ((double) start / one_second) * one_second;
2687
if (((direction == 0) && (start % one_minute > one_minute / 2)) || (direction > 0)) {
2688
start = (framepos_t) ceil ((double) start / one_minute) * one_minute;
2690
start = (framepos_t) floor ((double) start / one_minute) * one_minute;
2695
start = _session->tempo_map().round_to_bar (start, direction);
2699
start = _session->tempo_map().round_to_beat (start, direction);
2702
case SnapToBeatDiv128:
2703
start = _session->tempo_map().round_to_beat_subdivision (start, 128, direction);
2705
case SnapToBeatDiv64:
2706
start = _session->tempo_map().round_to_beat_subdivision (start, 64, direction);
2708
case SnapToBeatDiv32:
2709
start = _session->tempo_map().round_to_beat_subdivision (start, 32, direction);
2711
case SnapToBeatDiv28:
2712
start = _session->tempo_map().round_to_beat_subdivision (start, 28, direction);
2714
case SnapToBeatDiv24:
2715
start = _session->tempo_map().round_to_beat_subdivision (start, 24, direction);
2717
case SnapToBeatDiv20:
2718
start = _session->tempo_map().round_to_beat_subdivision (start, 20, direction);
2720
case SnapToBeatDiv16:
2721
start = _session->tempo_map().round_to_beat_subdivision (start, 16, direction);
2723
case SnapToBeatDiv14:
2724
start = _session->tempo_map().round_to_beat_subdivision (start, 14, direction);
2726
case SnapToBeatDiv12:
2727
start = _session->tempo_map().round_to_beat_subdivision (start, 12, direction);
2729
case SnapToBeatDiv10:
2730
start = _session->tempo_map().round_to_beat_subdivision (start, 10, direction);
2732
case SnapToBeatDiv8:
2733
start = _session->tempo_map().round_to_beat_subdivision (start, 8, direction);
2735
case SnapToBeatDiv7:
2736
start = _session->tempo_map().round_to_beat_subdivision (start, 7, direction);
2738
case SnapToBeatDiv6:
2739
start = _session->tempo_map().round_to_beat_subdivision (start, 6, direction);
2741
case SnapToBeatDiv5:
2742
start = _session->tempo_map().round_to_beat_subdivision (start, 5, direction);
2744
case SnapToBeatDiv4:
2745
start = _session->tempo_map().round_to_beat_subdivision (start, 4, direction);
2747
case SnapToBeatDiv3:
2748
start = _session->tempo_map().round_to_beat_subdivision (start, 3, direction);
2750
case SnapToBeatDiv2:
2751
start = _session->tempo_map().round_to_beat_subdivision (start, 2, direction);
2759
_session->locations()->marks_either_side (start, before, after);
2761
if (before == max_framepos && after == max_framepos) {
2762
/* No marks to snap to, so just don't snap */
2764
} else if (before == max_framepos) {
2766
} else if (after == max_framepos) {
2768
} else if (before != max_framepos && after != max_framepos) {
2769
/* have before and after */
2770
if ((start - before) < (after - start)) {
2779
case SnapToRegionStart:
2780
case SnapToRegionEnd:
2781
case SnapToRegionSync:
2782
case SnapToRegionBoundary:
2783
if (!region_boundary_cache.empty()) {
2785
vector<framepos_t>::iterator prev = region_boundary_cache.end ();
2786
vector<framepos_t>::iterator next = region_boundary_cache.end ();
2788
if (direction > 0) {
2789
next = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2791
next = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2794
if (next != region_boundary_cache.begin ()) {
2799
framepos_t const p = (prev == region_boundary_cache.end()) ? region_boundary_cache.front () : *prev;
2800
framepos_t const n = (next == region_boundary_cache.end()) ? region_boundary_cache.back () : *next;
2802
if (start > (p + n) / 2) {
2811
switch (_snap_mode) {
2817
if (presnap > start) {
2818
if (presnap > (start + unit_to_frame(snap_threshold))) {
2822
} else if (presnap < start) {
2823
if (presnap < (start - unit_to_frame(snap_threshold))) {
2829
/* handled at entry */
2837
Editor::setup_toolbar ()
2839
HBox* mode_box = manage(new HBox);
2840
mode_box->set_border_width (2);
2841
mode_box->set_spacing(4);
2843
HBox* mouse_mode_box = manage (new HBox);
2844
HBox* mouse_mode_hbox = manage (new HBox);
2845
VBox* mouse_mode_vbox = manage (new VBox);
2846
Alignment* mouse_mode_align = manage (new Alignment);
2848
Glib::RefPtr<SizeGroup> mouse_mode_size_group = SizeGroup::create (SIZE_GROUP_BOTH);
2849
// mouse_mode_size_group->add_widget (smart_mode_button);
2850
mouse_mode_size_group->add_widget (mouse_move_button);
2851
mouse_mode_size_group->add_widget (mouse_select_button);
2852
mouse_mode_size_group->add_widget (mouse_zoom_button);
2853
mouse_mode_size_group->add_widget (mouse_gain_button);
2854
mouse_mode_size_group->add_widget (mouse_timefx_button);
2855
mouse_mode_size_group->add_widget (mouse_audition_button);
2856
mouse_mode_size_group->add_widget (mouse_draw_button);
2857
mouse_mode_size_group->add_widget (internal_edit_button);
2859
/* make them just a bit bigger */
2860
mouse_move_button.set_size_request (-1, 30);
2862
mouse_mode_hbox->set_spacing (2);
2864
mouse_mode_hbox->pack_start (smart_mode_button, false, false);
2865
mouse_mode_hbox->pack_start (mouse_move_button, false, false);
2866
mouse_mode_hbox->pack_start (mouse_select_button, false, false);
2867
mouse_mode_hbox->pack_start (mouse_zoom_button, false, false);
2868
mouse_mode_hbox->pack_start (mouse_gain_button, false, false);
2869
mouse_mode_hbox->pack_start (mouse_timefx_button, false, false);
2870
mouse_mode_hbox->pack_start (mouse_audition_button, false, false);
2871
mouse_mode_hbox->pack_start (mouse_draw_button, false, false);
2872
mouse_mode_hbox->pack_start (internal_edit_button, false, false, 8);
2874
mouse_mode_vbox->pack_start (*mouse_mode_hbox);
2876
mouse_mode_align->add (*mouse_mode_vbox);
2877
mouse_mode_align->set (0.5, 1.0, 0.0, 0.0);
2879
mouse_mode_box->pack_start (*mouse_mode_align, false, false);
2881
edit_mode_strings.push_back (edit_mode_to_string (Slide));
2882
if (!Profile->get_sae()) {
2883
edit_mode_strings.push_back (edit_mode_to_string (Splice));
2885
edit_mode_strings.push_back (edit_mode_to_string (Lock));
2887
edit_mode_selector.set_name ("EditModeSelector");
2888
set_popdown_strings (edit_mode_selector, edit_mode_strings);
2889
edit_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_mode_selection_done));
2891
mode_box->pack_start (edit_mode_selector, false, false);
2892
mode_box->pack_start (*mouse_mode_box, false, false);
2894
_mouse_mode_tearoff = manage (new TearOff (*mode_box));
2895
_mouse_mode_tearoff->set_name ("MouseModeBase");
2896
_mouse_mode_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_mouse_mode_tearoff->tearoff_window()), false);
2898
if (Profile->get_sae()) {
2899
_mouse_mode_tearoff->set_can_be_torn_off (false);
2902
_mouse_mode_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2903
&_mouse_mode_tearoff->tearoff_window()));
2904
_mouse_mode_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2905
&_mouse_mode_tearoff->tearoff_window(), 1));
2906
_mouse_mode_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2907
&_mouse_mode_tearoff->tearoff_window()));
2908
_mouse_mode_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2909
&_mouse_mode_tearoff->tearoff_window(), 1));
2913
_zoom_box.set_spacing (2);
2914
_zoom_box.set_border_width (2);
2918
zoom_in_button.set_name ("zoom button");
2919
zoom_in_button.add_elements ( ArdourButton::FlatFace );
2920
zoom_in_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2921
zoom_in_button.set_image(::get_icon ("zoom_in"));
2922
act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-in"));
2923
zoom_in_button.set_related_action (act);
2925
zoom_out_button.set_name ("zoom button");
2926
zoom_out_button.add_elements ( ArdourButton::FlatFace );
2927
zoom_out_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2928
zoom_out_button.set_image(::get_icon ("zoom_out"));
2929
act = ActionManager::get_action (X_("Editor"), X_("temporal-zoom-out"));
2930
zoom_out_button.set_related_action (act);
2932
zoom_out_full_button.set_name ("zoom button");
2933
zoom_out_full_button.add_elements ( ArdourButton::FlatFace );
2934
zoom_out_full_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2935
zoom_out_full_button.set_image(::get_icon ("zoom_full"));
2936
act = ActionManager::get_action (X_("Editor"), X_("zoom-to-session"));
2937
zoom_out_full_button.set_related_action (act);
2939
zoom_focus_selector.set_name ("ZoomFocusSelector");
2940
set_popdown_strings (zoom_focus_selector, zoom_focus_strings);
2941
zoom_focus_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::zoom_focus_selection_done));
2943
_zoom_box.pack_start (zoom_out_button, false, false);
2944
_zoom_box.pack_start (zoom_in_button, false, false);
2945
_zoom_box.pack_start (zoom_out_full_button, false, false);
2947
_zoom_box.pack_start (zoom_focus_selector, false, false);
2949
/* Track zoom buttons */
2950
tav_expand_button.set_name ("zoom button");
2951
tav_expand_button.add_elements ( ArdourButton::FlatFace );
2952
tav_expand_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2953
tav_expand_button.set_size_request (-1, 20);
2954
tav_expand_button.set_image(::get_icon ("tav_exp"));
2955
act = ActionManager::get_action (X_("Editor"), X_("expand-tracks"));
2956
tav_expand_button.set_related_action (act);
2958
tav_shrink_button.set_name ("zoom button");
2959
tav_shrink_button.add_elements ( ArdourButton::FlatFace );
2960
tav_shrink_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
2961
tav_shrink_button.set_size_request (-1, 20);
2962
tav_shrink_button.set_image(::get_icon ("tav_shrink"));
2963
act = ActionManager::get_action (X_("Editor"), X_("shrink-tracks"));
2964
tav_shrink_button.set_related_action (act);
2966
_zoom_box.pack_start (tav_shrink_button);
2967
_zoom_box.pack_start (tav_expand_button);
2969
_zoom_tearoff = manage (new TearOff (_zoom_box));
2971
_zoom_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2972
&_zoom_tearoff->tearoff_window()));
2973
_zoom_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2974
&_zoom_tearoff->tearoff_window(), 0));
2975
_zoom_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2976
&_zoom_tearoff->tearoff_window()));
2977
_zoom_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2978
&_zoom_tearoff->tearoff_window(), 0));
2980
snap_box.set_spacing (2);
2981
snap_box.set_border_width (2);
2983
snap_type_selector.set_name ("SnapTypeSelector");
2984
set_popdown_strings (snap_type_selector, snap_type_strings);
2985
snap_type_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::snap_type_selection_done));
2987
snap_mode_selector.set_name ("SnapModeSelector");
2988
set_popdown_strings (snap_mode_selector, snap_mode_strings);
2989
snap_mode_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::snap_mode_selection_done));
2991
edit_point_selector.set_name ("EditPointSelector");
2992
set_popdown_strings (edit_point_selector, edit_point_strings);
2993
edit_point_selector.signal_changed().connect (sigc::mem_fun(*this, &Editor::edit_point_selection_done));
2995
snap_box.pack_start (snap_mode_selector, false, false);
2996
snap_box.pack_start (snap_type_selector, false, false);
2997
snap_box.pack_start (edit_point_selector, false, false);
3001
HBox *nudge_box = manage (new HBox);
3002
nudge_box->set_spacing (2);
3003
nudge_box->set_border_width (2);
3005
nudge_forward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_forward_release), false);
3006
nudge_backward_button.signal_button_release_event().connect (sigc::mem_fun(*this, &Editor::nudge_backward_release), false);
3008
nudge_forward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
3009
nudge_backward_button.set_tweaks ((ArdourButton::Tweaks) (ArdourButton::ShowClick) );
3011
nudge_box->pack_start (nudge_backward_button, false, false);
3012
nudge_box->pack_start (nudge_forward_button, false, false);
3013
nudge_box->pack_start (*nudge_clock, false, false);
3016
/* Pack everything in... */
3018
HBox* hbox = manage (new HBox);
3019
hbox->set_spacing(10);
3021
_tools_tearoff = manage (new TearOff (*hbox));
3022
_tools_tearoff->set_name ("MouseModeBase");
3023
_tools_tearoff->tearoff_window().signal_key_press_event().connect (sigc::bind (sigc::ptr_fun (relay_key_press), &_tools_tearoff->tearoff_window()), false);
3025
if (Profile->get_sae()) {
3026
_tools_tearoff->set_can_be_torn_off (false);
3029
_tools_tearoff->Detach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3030
&_tools_tearoff->tearoff_window()));
3031
_tools_tearoff->Attach.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3032
&_tools_tearoff->tearoff_window(), 0));
3033
_tools_tearoff->Hidden.connect (sigc::bind (sigc::mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
3034
&_tools_tearoff->tearoff_window()));
3035
_tools_tearoff->Visible.connect (sigc::bind (sigc::mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
3036
&_tools_tearoff->tearoff_window(), 0));
3038
toolbar_hbox.set_spacing (10);
3039
toolbar_hbox.set_border_width (1);
3041
toolbar_hbox.pack_start (*_mouse_mode_tearoff, false, false);
3042
toolbar_hbox.pack_start (*_zoom_tearoff, false, false);
3043
toolbar_hbox.pack_start (*_tools_tearoff, false, false);
3045
hbox->pack_start (snap_box, false, false);
3046
if (!Profile->get_small_screen()) {
3047
hbox->pack_start (*nudge_box, false, false);
3049
ARDOUR_UI::instance()->editor_transport_box().pack_start (*nudge_box, false, false);
3051
hbox->pack_start (panic_box, false, false);
3055
toolbar_base.set_name ("ToolBarBase");
3056
toolbar_base.add (toolbar_hbox);
3058
_toolbar_viewport.add (toolbar_base);
3059
/* stick to the required height but allow width to vary if there's not enough room */
3060
_toolbar_viewport.set_size_request (1, -1);
3062
toolbar_frame.set_shadow_type (SHADOW_OUT);
3063
toolbar_frame.set_name ("BaseFrame");
3064
toolbar_frame.add (_toolbar_viewport);
3068
Editor::setup_tooltips ()
3070
ARDOUR_UI::instance()->set_tip (smart_mode_button, _("Smart Mode (add Range functions to Object mode)"));
3071
ARDOUR_UI::instance()->set_tip (mouse_move_button, _("Object Mode (select/move Objects)"));
3072
ARDOUR_UI::instance()->set_tip (mouse_select_button, _("Range Mode (select/move Ranges)"));
3073
ARDOUR_UI::instance()->set_tip (mouse_draw_button, _("Draw/Edit MIDI Notes"));
3074
ARDOUR_UI::instance()->set_tip (mouse_gain_button, _("Draw Region Gain"));
3075
ARDOUR_UI::instance()->set_tip (mouse_zoom_button, _("Select Zoom Range"));
3076
ARDOUR_UI::instance()->set_tip (mouse_timefx_button, _("Stretch/Shrink Regions and MIDI Notes"));
3077
ARDOUR_UI::instance()->set_tip (mouse_audition_button, _("Listen to Specific Regions"));
3078
ARDOUR_UI::instance()->set_tip (internal_edit_button, _("Note Level Editing"));
3079
ARDOUR_UI::instance()->set_tip (*_group_tabs, _("Groups: click to (de)activate\nContext-click for other operations"));
3080
ARDOUR_UI::instance()->set_tip (nudge_forward_button, _("Nudge Region/Selection Later"));
3081
ARDOUR_UI::instance()->set_tip (nudge_backward_button, _("Nudge Region/Selection Earlier"));
3082
ARDOUR_UI::instance()->set_tip (zoom_in_button, _("Zoom In"));
3083
ARDOUR_UI::instance()->set_tip (zoom_out_button, _("Zoom Out"));
3084
ARDOUR_UI::instance()->set_tip (zoom_out_full_button, _("Zoom to Session"));
3085
ARDOUR_UI::instance()->set_tip (zoom_focus_selector, _("Zoom focus"));
3086
ARDOUR_UI::instance()->set_tip (tav_expand_button, _("Expand Tracks"));
3087
ARDOUR_UI::instance()->set_tip (tav_shrink_button, _("Shrink Tracks"));
3088
ARDOUR_UI::instance()->set_tip (snap_type_selector, _("Snap/Grid Units"));
3089
ARDOUR_UI::instance()->set_tip (snap_mode_selector, _("Snap/Grid Mode"));
3090
ARDOUR_UI::instance()->set_tip (edit_point_selector, _("Edit point"));
3091
ARDOUR_UI::instance()->set_tip (edit_mode_selector, _("Edit Mode"));
3092
ARDOUR_UI::instance()->set_tip (nudge_clock, _("Nudge Clock\n(controls distance used to nudge regions and selections)"));
3096
Editor::convert_drop_to_paths (
3097
vector<string>& paths,
3098
const RefPtr<Gdk::DragContext>& /*context*/,
3101
const SelectionData& data,
3105
if (_session == 0) {
3109
vector<string> uris = data.get_uris();
3113
/* This is seriously fucked up. Nautilus doesn't say that its URI lists
3114
are actually URI lists. So do it by hand.
3117
if (data.get_target() != "text/plain") {
3121
/* Parse the "uri-list" format that Nautilus provides,
3122
where each pathname is delimited by \r\n.
3124
THERE MAY BE NO NULL TERMINATING CHAR!!!
3127
string txt = data.get_text();
3131
p = (char *) malloc (txt.length() + 1);
3132
txt.copy (p, txt.length(), 0);
3133
p[txt.length()] = '\0';
3139
while (g_ascii_isspace (*p))
3143
while (*q && (*q != '\n') && (*q != '\r')) {
3150
while (q > p && g_ascii_isspace (*q))
3155
uris.push_back (string (p, q - p + 1));
3159
p = strchr (p, '\n');
3171
for (vector<string>::iterator i = uris.begin(); i != uris.end(); ++i) {
3173
if ((*i).substr (0,7) == "file://") {
3175
string const p = PBD::url_decode (*i);
3177
// scan forward past three slashes
3179
string::size_type slashcnt = 0;
3180
string::size_type n = 0;
3181
string::const_iterator x = p.begin();
3183
while (slashcnt < 3 && x != p.end()) {
3186
} else if (slashcnt == 3) {
3193
if (slashcnt != 3 || x == p.end()) {
3194
error << _("malformed URL passed to drag-n-drop code") << endmsg;
3198
paths.push_back (p.substr (n - 1));
3206
Editor::new_tempo_section ()
3212
Editor::map_transport_state ()
3214
ENSURE_GUI_THREAD (*this, &Editor::map_transport_state);
3216
if (_session && _session->transport_stopped()) {
3217
have_pending_keyboard_selection = false;
3220
update_loop_range_view (true);
3226
Editor::begin_reversible_command (string name)
3229
_session->begin_reversible_command (name);
3234
Editor::begin_reversible_command (GQuark q)
3237
_session->begin_reversible_command (q);
3242
Editor::commit_reversible_command ()
3245
_session->commit_reversible_command ();
3250
Editor::history_changed ()
3254
if (undo_action && _session) {
3255
if (_session->undo_depth() == 0) {
3256
label = S_("Command|Undo");
3258
label = string_compose(S_("Command|Undo (%1)"), _session->next_undo());
3260
undo_action->property_label() = label;
3263
if (redo_action && _session) {
3264
if (_session->redo_depth() == 0) {
3267
label = string_compose(_("Redo (%1)"), _session->next_redo());
3269
redo_action->property_label() = label;
3274
Editor::duplicate_range (bool with_dialog)
3278
RegionSelection rs = get_regions_from_selection_and_entered ();
3280
if ( selection->time.length() == 0 && rs.empty()) {
3286
ArdourDialog win (_("Duplicate"));
3287
Label label (_("Number of duplications:"));
3288
Adjustment adjustment (1.0, 1.0, 1000000.0, 1.0, 5.0);
3289
SpinButton spinner (adjustment, 0.0, 1);
3292
win.get_vbox()->set_spacing (12);
3293
win.get_vbox()->pack_start (hbox);
3294
hbox.set_border_width (6);
3295
hbox.pack_start (label, PACK_EXPAND_PADDING, 12);
3297
/* dialogs have ::add_action_widget() but that puts the spinner in the wrong
3298
place, visually. so do this by hand.
3301
hbox.pack_start (spinner, PACK_EXPAND_PADDING, 12);
3302
spinner.signal_activate().connect (sigc::bind (sigc::mem_fun (win, &ArdourDialog::response), RESPONSE_ACCEPT));
3303
spinner.grab_focus();
3309
win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3310
win.add_button (_("Duplicate"), RESPONSE_ACCEPT);
3311
win.set_default_response (RESPONSE_ACCEPT);
3313
spinner.grab_focus ();
3315
switch (win.run ()) {
3316
case RESPONSE_ACCEPT:
3322
times = adjustment.get_value();
3325
if ((current_mouse_mode() == Editing::MouseRange)) {
3326
if (selection->time.length()) {
3327
duplicate_selection (times);
3329
} else if (get_smart_mode()) {
3330
if (selection->time.length()) {
3331
duplicate_selection (times);
3333
duplicate_some_regions (rs, times);
3335
duplicate_some_regions (rs, times);
3340
Editor::set_edit_mode (EditMode m)
3342
Config->set_edit_mode (m);
3346
Editor::cycle_edit_mode ()
3348
switch (Config->get_edit_mode()) {
3350
if (Profile->get_sae()) {
3351
Config->set_edit_mode (Lock);
3353
Config->set_edit_mode (Splice);
3357
Config->set_edit_mode (Lock);
3360
Config->set_edit_mode (Slide);
3366
Editor::edit_mode_selection_done ()
3368
string s = edit_mode_selector.get_active_text ();
3371
Config->set_edit_mode (string_to_edit_mode (s));
3376
Editor::snap_type_selection_done ()
3378
string choice = snap_type_selector.get_active_text();
3379
SnapType snaptype = SnapToBeat;
3381
if (choice == _("Beats/2")) {
3382
snaptype = SnapToBeatDiv2;
3383
} else if (choice == _("Beats/3")) {
3384
snaptype = SnapToBeatDiv3;
3385
} else if (choice == _("Beats/4")) {
3386
snaptype = SnapToBeatDiv4;
3387
} else if (choice == _("Beats/5")) {
3388
snaptype = SnapToBeatDiv5;
3389
} else if (choice == _("Beats/6")) {
3390
snaptype = SnapToBeatDiv6;
3391
} else if (choice == _("Beats/7")) {
3392
snaptype = SnapToBeatDiv7;
3393
} else if (choice == _("Beats/8")) {
3394
snaptype = SnapToBeatDiv8;
3395
} else if (choice == _("Beats/10")) {
3396
snaptype = SnapToBeatDiv10;
3397
} else if (choice == _("Beats/12")) {
3398
snaptype = SnapToBeatDiv12;
3399
} else if (choice == _("Beats/14")) {
3400
snaptype = SnapToBeatDiv14;
3401
} else if (choice == _("Beats/16")) {
3402
snaptype = SnapToBeatDiv16;
3403
} else if (choice == _("Beats/20")) {
3404
snaptype = SnapToBeatDiv20;
3405
} else if (choice == _("Beats/24")) {
3406
snaptype = SnapToBeatDiv24;
3407
} else if (choice == _("Beats/28")) {
3408
snaptype = SnapToBeatDiv28;
3409
} else if (choice == _("Beats/32")) {
3410
snaptype = SnapToBeatDiv32;
3411
} else if (choice == _("Beats/64")) {
3412
snaptype = SnapToBeatDiv64;
3413
} else if (choice == _("Beats/128")) {
3414
snaptype = SnapToBeatDiv128;
3415
} else if (choice == _("Beats")) {
3416
snaptype = SnapToBeat;
3417
} else if (choice == _("Bars")) {
3418
snaptype = SnapToBar;
3419
} else if (choice == _("Marks")) {
3420
snaptype = SnapToMark;
3421
} else if (choice == _("Region starts")) {
3422
snaptype = SnapToRegionStart;
3423
} else if (choice == _("Region ends")) {
3424
snaptype = SnapToRegionEnd;
3425
} else if (choice == _("Region bounds")) {
3426
snaptype = SnapToRegionBoundary;
3427
} else if (choice == _("Region syncs")) {
3428
snaptype = SnapToRegionSync;
3429
} else if (choice == _("CD Frames")) {
3430
snaptype = SnapToCDFrame;
3431
} else if (choice == _("Timecode Frames")) {
3432
snaptype = SnapToTimecodeFrame;
3433
} else if (choice == _("Timecode Seconds")) {
3434
snaptype = SnapToTimecodeSeconds;
3435
} else if (choice == _("Timecode Minutes")) {
3436
snaptype = SnapToTimecodeMinutes;
3437
} else if (choice == _("Seconds")) {
3438
snaptype = SnapToSeconds;
3439
} else if (choice == _("Minutes")) {
3440
snaptype = SnapToMinutes;
3443
RefPtr<RadioAction> ract = snap_type_action (snaptype);
3445
ract->set_active ();
3450
Editor::snap_mode_selection_done ()
3452
string choice = snap_mode_selector.get_active_text();
3453
SnapMode mode = SnapNormal;
3455
if (choice == _("No Grid")) {
3457
} else if (choice == _("Grid")) {
3459
} else if (choice == _("Magnetic")) {
3460
mode = SnapMagnetic;
3463
RefPtr<RadioAction> ract = snap_mode_action (mode);
3466
ract->set_active (true);
3471
Editor::cycle_edit_point (bool with_marker)
3473
switch (_edit_point) {
3475
set_edit_point_preference (EditAtPlayhead);
3477
case EditAtPlayhead:
3479
set_edit_point_preference (EditAtSelectedMarker);
3481
set_edit_point_preference (EditAtMouse);
3484
case EditAtSelectedMarker:
3485
set_edit_point_preference (EditAtMouse);
3491
Editor::edit_point_selection_done ()
3493
string choice = edit_point_selector.get_active_text();
3494
EditPoint ep = EditAtSelectedMarker;
3496
if (choice == _("Marker")) {
3497
set_edit_point_preference (EditAtSelectedMarker);
3498
} else if (choice == _("Playhead")) {
3499
set_edit_point_preference (EditAtPlayhead);
3501
set_edit_point_preference (EditAtMouse);
3504
RefPtr<RadioAction> ract = edit_point_action (ep);
3507
ract->set_active (true);
3512
Editor::zoom_focus_selection_done ()
3514
string choice = zoom_focus_selector.get_active_text();
3515
ZoomFocus focus_type = ZoomFocusLeft;
3517
if (choice == _("Left")) {
3518
focus_type = ZoomFocusLeft;
3519
} else if (choice == _("Right")) {
3520
focus_type = ZoomFocusRight;
3521
} else if (choice == _("Center")) {
3522
focus_type = ZoomFocusCenter;
3523
} else if (choice == _("Playhead")) {
3524
focus_type = ZoomFocusPlayhead;
3525
} else if (choice == _("Mouse")) {
3526
focus_type = ZoomFocusMouse;
3527
} else if (choice == _("Edit point")) {
3528
focus_type = ZoomFocusEdit;
3531
RefPtr<RadioAction> ract = zoom_focus_action (focus_type);
3534
ract->set_active ();
3539
Editor::edit_controls_button_release (GdkEventButton* ev)
3541
if (Keyboard::is_context_menu_event (ev)) {
3542
ARDOUR_UI::instance()->add_route (this);
3543
} else if (ev->button == 1) {
3544
selection->clear_tracks ();
3551
Editor::mouse_select_button_release (GdkEventButton* ev)
3553
/* this handles just right-clicks */
3555
if (ev->button != 3) {
3563
Editor::set_zoom_focus (ZoomFocus f)
3565
string str = zoom_focus_strings[(int)f];
3567
if (str != zoom_focus_selector.get_active_text()) {
3568
zoom_focus_selector.set_active_text (str);
3571
if (zoom_focus != f) {
3578
Editor::cycle_zoom_focus ()
3580
switch (zoom_focus) {
3582
set_zoom_focus (ZoomFocusRight);
3584
case ZoomFocusRight:
3585
set_zoom_focus (ZoomFocusCenter);
3587
case ZoomFocusCenter:
3588
set_zoom_focus (ZoomFocusPlayhead);
3590
case ZoomFocusPlayhead:
3591
set_zoom_focus (ZoomFocusMouse);
3593
case ZoomFocusMouse:
3594
set_zoom_focus (ZoomFocusEdit);
3597
set_zoom_focus (ZoomFocusLeft);
3603
Editor::ensure_float (Window& win)
3605
win.set_transient_for (*this);
3609
Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3611
/* recover or initialize pane positions. do this here rather than earlier because
3612
we don't want the positions to change the child allocations, which they seem to do.
3618
XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3627
XMLNode* geometry = find_named_node (*node, "geometry");
3629
if (which == static_cast<Paned*> (&edit_pane)) {
3631
if (done & Horizontal) {
3635
if (geometry && (prop = geometry->property ("notebook-shrunk"))) {
3636
_notebook_shrunk = string_is_affirmative (prop->value ());
3639
if (!geometry || (prop = geometry->property ("edit-horizontal-pane-pos")) == 0) {
3640
/* initial allocation is 90% to canvas, 10% to notebook */
3641
pos = (int) floor (alloc.get_width() * 0.90f);
3642
snprintf (buf, sizeof(buf), "%d", pos);
3644
pos = atoi (prop->value());
3647
if (GTK_WIDGET(edit_pane.gobj())->allocation.width > pos) {
3648
edit_pane.set_position (pos);
3651
done = (Pane) (done | Horizontal);
3653
} else if (which == static_cast<Paned*> (&editor_summary_pane)) {
3655
if (done & Vertical) {
3659
if (!geometry || (prop = geometry->property ("edit-vertical-pane-pos")) == 0) {
3660
/* initial allocation is 90% to canvas, 10% to summary */
3661
pos = (int) floor (alloc.get_height() * 0.90f);
3662
snprintf (buf, sizeof(buf), "%d", pos);
3665
pos = atoi (prop->value());
3668
if (GTK_WIDGET(editor_summary_pane.gobj())->allocation.height > pos) {
3669
editor_summary_pane.set_position (pos);
3672
done = (Pane) (done | Vertical);
3677
Editor::detach_tearoff (Box* /*b*/, Window* /*w*/)
3679
if ((_tools_tearoff->torn_off() || !_tools_tearoff->visible()) &&
3680
(_mouse_mode_tearoff->torn_off() || !_mouse_mode_tearoff->visible()) &&
3681
(_zoom_tearoff->torn_off() || !_zoom_tearoff->visible())) {
3682
top_hbox.remove (toolbar_frame);
3687
Editor::reattach_tearoff (Box* /*b*/, Window* /*w*/, int32_t /*n*/)
3689
if (toolbar_frame.get_parent() == 0) {
3690
top_hbox.pack_end (toolbar_frame);
3695
Editor::set_show_measures (bool yn)
3697
if (_show_measures != yn) {
3700
if ((_show_measures = yn) == true) {
3702
tempo_lines->show();
3704
(void) redraw_measures ();
3711
Editor::toggle_follow_playhead ()
3713
RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-follow-playhead"));
3715
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3716
set_follow_playhead (tact->get_active());
3720
/** @param yn true to follow playhead, otherwise false.
3721
* @param catch_up true to reset the editor view to show the playhead (if yn == true), otherwise false.
3724
Editor::set_follow_playhead (bool yn, bool catch_up)
3726
if (_follow_playhead != yn) {
3727
if ((_follow_playhead = yn) == true && catch_up) {
3729
reset_x_origin_to_follow_playhead ();
3736
Editor::toggle_stationary_playhead ()
3738
RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("toggle-stationary-playhead"));
3740
RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3741
set_stationary_playhead (tact->get_active());
3746
Editor::set_stationary_playhead (bool yn)
3748
if (_stationary_playhead != yn) {
3749
if ((_stationary_playhead = yn) == true) {
3751
// FIXME need a 3.0 equivalent of this 2.X call
3752
// update_current_screen ();
3759
Editor::playlist_selector () const
3761
return *_playlist_selector;
3765
Editor::get_grid_type_as_beats (bool& success, framepos_t position)
3769
switch (_snap_type) {
3774
case SnapToBeatDiv128:
3777
case SnapToBeatDiv64:
3780
case SnapToBeatDiv32:
3783
case SnapToBeatDiv28:
3786
case SnapToBeatDiv24:
3789
case SnapToBeatDiv20:
3792
case SnapToBeatDiv16:
3795
case SnapToBeatDiv14:
3798
case SnapToBeatDiv12:
3801
case SnapToBeatDiv10:
3804
case SnapToBeatDiv8:
3807
case SnapToBeatDiv7:
3810
case SnapToBeatDiv6:
3813
case SnapToBeatDiv5:
3816
case SnapToBeatDiv4:
3819
case SnapToBeatDiv3:
3822
case SnapToBeatDiv2:
3828
return _session->tempo_map().meter_at (position).divisions_per_bar();
3833
case SnapToTimecodeFrame:
3834
case SnapToTimecodeSeconds:
3835
case SnapToTimecodeMinutes:
3838
case SnapToRegionStart:
3839
case SnapToRegionEnd:
3840
case SnapToRegionSync:
3841
case SnapToRegionBoundary:
3851
Editor::get_nudge_distance (framepos_t pos, framecnt_t& next)
3855
ret = nudge_clock->current_duration (pos);
3856
next = ret + 1; /* XXXX fix me */
3862
Editor::playlist_deletion_dialog (boost::shared_ptr<Playlist> pl)
3864
ArdourDialog dialog (_("Playlist Deletion"));
3865
Label label (string_compose (_("Playlist %1 is currently unused.\n"
3866
"If it is kept, its audio files will not be cleaned.\n"
3867
"If it is deleted, audio files used by it alone will be cleaned."),
3870
dialog.set_position (WIN_POS_CENTER);
3871
dialog.get_vbox()->pack_start (label);
3875
dialog.add_button (_("Delete Playlist"), RESPONSE_ACCEPT);
3876
dialog.add_button (_("Keep Playlist"), RESPONSE_REJECT);
3877
dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3879
switch (dialog.run ()) {
3880
case RESPONSE_ACCEPT:
3881
/* delete the playlist */
3885
case RESPONSE_REJECT:
3886
/* keep the playlist */
3898
Editor::audio_region_selection_covers (framepos_t where)
3900
for (RegionSelection::iterator a = selection->regions.begin(); a != selection->regions.end(); ++a) {
3901
if ((*a)->region()->covers (where)) {
3910
Editor::prepare_for_cleanup ()
3912
cut_buffer->clear_regions ();
3913
cut_buffer->clear_playlists ();
3915
selection->clear_regions ();
3916
selection->clear_playlists ();
3918
_regions->suspend_redisplay ();
3922
Editor::finish_cleanup ()
3924
_regions->resume_redisplay ();
3928
Editor::transport_loop_location()
3931
return _session->locations()->auto_loop_location();
3938
Editor::transport_punch_location()
3941
return _session->locations()->auto_punch_location();
3948
Editor::control_layout_scroll (GdkEventScroll* ev)
3950
if (Keyboard::some_magic_widget_has_focus()) {
3954
switch (ev->direction) {
3956
scroll_tracks_up_line ();
3960
case GDK_SCROLL_DOWN:
3961
scroll_tracks_down_line ();
3965
/* no left/right handling yet */
3973
Editor::session_state_saved (string)
3976
_snapshots->redisplay ();
3980
Editor::update_tearoff_visibility()
3982
bool visible = Config->get_keep_tearoffs();
3983
_mouse_mode_tearoff->set_visible (visible);
3984
_tools_tearoff->set_visible (visible);
3985
_zoom_tearoff->set_visible (visible);
3989
Editor::maximise_editing_space ()
4001
Editor::restore_editing_space ()
4013
* Make new playlists for a given track and also any others that belong
4014
* to the same active route group with the `select' property.
4019
Editor::new_playlists (TimeAxisView* v)
4021
begin_reversible_command (_("new playlists"));
4022
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4023
_session->playlists->get (playlists);
4024
mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_new_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4025
commit_reversible_command ();
4029
* Use a copy of the current playlist for a given track and also any others that belong
4030
* to the same active route group with the `select' property.
4035
Editor::copy_playlists (TimeAxisView* v)
4037
begin_reversible_command (_("copy playlists"));
4038
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4039
_session->playlists->get (playlists);
4040
mapover_tracks (sigc::bind (sigc::mem_fun (*this, &Editor::mapped_use_copy_playlist), playlists), v, ARDOUR::Properties::select.property_id);
4041
commit_reversible_command ();
4044
/** Clear the current playlist for a given track and also any others that belong
4045
* to the same active route group with the `select' property.
4050
Editor::clear_playlists (TimeAxisView* v)
4052
begin_reversible_command (_("clear playlists"));
4053
vector<boost::shared_ptr<ARDOUR::Playlist> > playlists;
4054
_session->playlists->get (playlists);
4055
mapover_tracks (sigc::mem_fun (*this, &Editor::mapped_clear_playlist), v, ARDOUR::Properties::select.property_id);
4056
commit_reversible_command ();
4060
Editor::mapped_use_new_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4062
atv.use_new_playlist (sz > 1 ? false : true, playlists);
4066
Editor::mapped_use_copy_playlist (RouteTimeAxisView& atv, uint32_t sz, vector<boost::shared_ptr<ARDOUR::Playlist> > const & playlists)
4068
atv.use_copy_playlist (sz > 1 ? false : true, playlists);
4072
Editor::mapped_clear_playlist (RouteTimeAxisView& atv, uint32_t /*sz*/)
4074
atv.clear_playlist ();
4078
Editor::on_key_press_event (GdkEventKey* ev)
4080
return key_press_focus_accelerator_handler (*this, ev);
4084
Editor::on_key_release_event (GdkEventKey* ev)
4086
return Gtk::Window::on_key_release_event (ev);
4087
// return key_press_focus_accelerator_handler (*this, ev);
4090
/** Queue up a change to the viewport x origin.
4091
* @param frame New x origin.
4094
Editor::reset_x_origin (framepos_t frame)
4096
pending_visual_change.add (VisualChange::TimeOrigin);
4097
pending_visual_change.time_origin = frame;
4098
ensure_visual_change_idle_handler ();
4102
Editor::reset_y_origin (double y)
4104
pending_visual_change.add (VisualChange::YOrigin);
4105
pending_visual_change.y_origin = y;
4106
ensure_visual_change_idle_handler ();
4110
Editor::reset_zoom (double fpu)
4112
clamp_frames_per_unit (fpu);
4114
if (fpu == frames_per_unit) {
4118
pending_visual_change.add (VisualChange::ZoomLevel);
4119
pending_visual_change.frames_per_unit = fpu;
4120
ensure_visual_change_idle_handler ();
4124
Editor::reposition_and_zoom (framepos_t frame, double fpu)
4126
reset_x_origin (frame);
4129
if (!no_save_visual) {
4130
undo_visual_stack.push_back (current_visual_state(false));
4134
Editor::VisualState::VisualState (bool with_tracks)
4135
: gui_state (with_tracks ? new GUIObjectState : 0)
4139
Editor::VisualState::~VisualState ()
4144
Editor::VisualState*
4145
Editor::current_visual_state (bool with_tracks)
4147
VisualState* vs = new VisualState (with_tracks);
4148
vs->y_position = vertical_adjustment.get_value();
4149
vs->frames_per_unit = frames_per_unit;
4150
vs->leftmost_frame = leftmost_frame;
4151
vs->zoom_focus = zoom_focus;
4154
*vs->gui_state = *ARDOUR_UI::instance()->gui_object_state;
4161
Editor::undo_visual_state ()
4163
if (undo_visual_stack.empty()) {
4167
VisualState* vs = undo_visual_stack.back();
4168
undo_visual_stack.pop_back();
4171
redo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4173
use_visual_state (*vs);
4177
Editor::redo_visual_state ()
4179
if (redo_visual_stack.empty()) {
4183
VisualState* vs = redo_visual_stack.back();
4184
redo_visual_stack.pop_back();
4186
undo_visual_stack.push_back (current_visual_state (vs ? vs->gui_state != 0 : false));
4188
use_visual_state (*vs);
4192
Editor::swap_visual_state ()
4194
if (undo_visual_stack.empty()) {
4195
redo_visual_state ();
4197
undo_visual_state ();
4202
Editor::use_visual_state (VisualState& vs)
4204
PBD::Unwinder<bool> nsv (no_save_visual, true);
4206
_routes->suspend_redisplay ();
4208
vertical_adjustment.set_value (vs.y_position);
4210
set_zoom_focus (vs.zoom_focus);
4211
reposition_and_zoom (vs.leftmost_frame, vs.frames_per_unit);
4214
*ARDOUR_UI::instance()->gui_object_state = *vs.gui_state;
4216
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4217
(*i)->reset_visual_state ();
4221
_routes->update_visibility ();
4222
_routes->resume_redisplay ();
4225
/** This is the core function that controls the zoom level of the canvas. It is called
4226
* whenever one or more calls are made to reset_zoom(). It executes in an idle handler.
4227
* @param fpu New frames per unit; should already have been clamped so that it is sensible.
4230
Editor::set_frames_per_unit (double fpu)
4233
tempo_lines->tempo_map_changed();
4236
frames_per_unit = fpu;
4238
/* convert fpu to frame count */
4240
framepos_t frames = (framepos_t) floor (frames_per_unit * _canvas_width);
4242
if (frames_per_unit != zoom_range_clock->current_duration()) {
4243
zoom_range_clock->set (frames);
4246
bool const showing_time_selection = selection->time.length() > 0;
4248
if (showing_time_selection && selection->time.start () != selection->time.end_frame ()) {
4249
for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4250
(*i)->reshow_selection (selection->time);
4254
ZoomChanged (); /* EMIT_SIGNAL */
4256
//reset_scrolling_region ();
4258
if (playhead_cursor) {
4259
playhead_cursor->set_position (playhead_cursor->current_frame);
4262
refresh_location_display();
4263
_summary->set_overlays_dirty ();
4265
update_marker_labels ();
4271
Editor::queue_visual_videotimeline_update ()
4274
* pending_visual_change.add (VisualChange::VideoTimeline);
4275
* or maybe even more specific: which videotimeline-image
4276
* currently it calls update_video_timeline() to update
4277
* _all outdated_ images on the video-timeline.
4278
* see 'exposeimg()' in video_image_frame.cc
4280
ensure_visual_change_idle_handler ();
4284
Editor::ensure_visual_change_idle_handler ()
4286
if (pending_visual_change.idle_handler_id < 0) {
4287
pending_visual_change.idle_handler_id = g_idle_add (_idle_visual_changer, this);
4292
Editor::_idle_visual_changer (void* arg)
4294
return static_cast<Editor*>(arg)->idle_visual_changer ();
4298
Editor::idle_visual_changer ()
4300
/* set_horizontal_position() below (and maybe other calls) call
4301
gtk_main_iteration(), so it's possible that a signal will be handled
4302
half-way through this method. If this signal wants an
4303
idle_visual_changer we must schedule another one after this one, so
4304
mark the idle_handler_id as -1 here to allow that. Also make a note
4305
that we are doing the visual change, so that changes in response to
4306
super-rapid-screen-update can be dropped if we are still processing
4310
pending_visual_change.idle_handler_id = -1;
4311
pending_visual_change.being_handled = true;
4313
VisualChange::Type p = pending_visual_change.pending;
4314
pending_visual_change.pending = (VisualChange::Type) 0;
4316
double const last_time_origin = horizontal_position ();
4318
if (p & VisualChange::ZoomLevel) {
4319
set_frames_per_unit (pending_visual_change.frames_per_unit);
4321
compute_fixed_ruler_scale ();
4323
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_begin;
4324
ARDOUR::TempoMap::BBTPointList::const_iterator current_bbt_points_end;
4326
compute_current_bbt_points (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames(),
4327
current_bbt_points_begin, current_bbt_points_end);
4328
compute_bbt_ruler_scale (pending_visual_change.time_origin, pending_visual_change.time_origin + current_page_frames(),
4329
current_bbt_points_begin, current_bbt_points_end);
4330
update_tempo_based_rulers (current_bbt_points_begin, current_bbt_points_end);
4333
if (p & VisualChange::ZoomLevel) {
4334
update_video_timeline();
4337
if (p & VisualChange::TimeOrigin) {
4338
set_horizontal_position (pending_visual_change.time_origin / frames_per_unit);
4341
if (p & VisualChange::YOrigin) {
4342
vertical_adjustment.set_value (pending_visual_change.y_origin);
4345
if (last_time_origin == horizontal_position ()) {
4346
/* changed signal not emitted */
4347
update_fixed_rulers ();
4348
redisplay_tempo (true);
4351
if (!(p & VisualChange::ZoomLevel)) {
4352
update_video_timeline();
4355
_summary->set_overlays_dirty ();
4357
pending_visual_change.being_handled = false;
4358
return 0; /* this is always a one-shot call */
4361
struct EditorOrderTimeAxisSorter {
4362
bool operator() (const TimeAxisView* a, const TimeAxisView* b) const {
4363
return a->order () < b->order ();
4368
Editor::sort_track_selection (TrackViewList& sel)
4370
EditorOrderTimeAxisSorter cmp;
4375
Editor::get_preferred_edit_position (bool ignore_playhead, bool from_context_menu)
4378
framepos_t where = 0;
4379
EditPoint ep = _edit_point;
4381
if (from_context_menu && (ep == EditAtMouse)) {
4382
return event_frame (&context_click_event, 0, 0);
4385
if (entered_marker) {
4386
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use entered marker @ %1\n", entered_marker->position()));
4387
return entered_marker->position();
4390
if (ignore_playhead && ep == EditAtPlayhead) {
4391
ep = EditAtSelectedMarker;
4395
case EditAtPlayhead:
4396
where = _session->audible_frame();
4397
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use playhead @ %1\n", where));
4400
case EditAtSelectedMarker:
4401
if (!selection->markers.empty()) {
4403
Location* loc = find_location_from_marker (selection->markers.front(), is_start);
4406
where = loc->start();
4410
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use selected marker @ %1\n", where));
4418
if (!mouse_frame (where, ignored)) {
4419
/* XXX not right but what can we do ? */
4423
DEBUG_TRACE (DEBUG::CutNPaste, string_compose ("GPEP: use mouse @ %1\n", where));
4431
Editor::set_loop_range (framepos_t start, framepos_t end, string cmd)
4433
if (!_session) return;
4435
begin_reversible_command (cmd);
4439
if ((tll = transport_loop_location()) == 0) {
4440
Location* loc = new Location (*_session, start, end, _("Loop"), Location::IsAutoLoop);
4441
XMLNode &before = _session->locations()->get_state();
4442
_session->locations()->add (loc, true);
4443
_session->set_auto_loop_location (loc);
4444
XMLNode &after = _session->locations()->get_state();
4445
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4447
XMLNode &before = tll->get_state();
4448
tll->set_hidden (false, this);
4449
tll->set (start, end);
4450
XMLNode &after = tll->get_state();
4451
_session->add_command (new MementoCommand<Location>(*tll, &before, &after));
4454
commit_reversible_command ();
4458
Editor::set_punch_range (framepos_t start, framepos_t end, string cmd)
4460
if (!_session) return;
4462
begin_reversible_command (cmd);
4466
if ((tpl = transport_punch_location()) == 0) {
4467
Location* loc = new Location (*_session, start, end, _("Punch"), Location::IsAutoPunch);
4468
XMLNode &before = _session->locations()->get_state();
4469
_session->locations()->add (loc, true);
4470
_session->set_auto_loop_location (loc);
4471
XMLNode &after = _session->locations()->get_state();
4472
_session->add_command (new MementoCommand<Locations>(*(_session->locations()), &before, &after));
4475
XMLNode &before = tpl->get_state();
4476
tpl->set_hidden (false, this);
4477
tpl->set (start, end);
4478
XMLNode &after = tpl->get_state();
4479
_session->add_command (new MementoCommand<Location>(*tpl, &before, &after));
4482
commit_reversible_command ();
4485
/** Find regions which exist at a given time, and optionally on a given list of tracks.
4486
* @param rs List to which found regions are added.
4487
* @param where Time to look at.
4488
* @param ts Tracks to look on; if this is empty, all tracks are examined.
4491
Editor::get_regions_at (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4493
const TrackViewList* tracks;
4496
tracks = &track_views;
4501
for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4503
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4506
boost::shared_ptr<Track> tr;
4507
boost::shared_ptr<Playlist> pl;
4509
if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4511
boost::shared_ptr<RegionList> regions = pl->regions_at (
4512
(framepos_t) floor ( (double) where * tr->speed()));
4514
for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4515
RegionView* rv = rtv->view()->find_view (*i);
4526
Editor::get_regions_after (RegionSelection& rs, framepos_t where, const TrackViewList& ts) const
4528
const TrackViewList* tracks;
4531
tracks = &track_views;
4536
for (TrackViewList::const_iterator t = tracks->begin(); t != tracks->end(); ++t) {
4537
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*>(*t);
4539
boost::shared_ptr<Track> tr;
4540
boost::shared_ptr<Playlist> pl;
4542
if ((tr = rtv->track()) && ((pl = tr->playlist()))) {
4544
boost::shared_ptr<RegionList> regions = pl->regions_touched (
4545
(framepos_t) floor ( (double)where * tr->speed()), max_framepos);
4547
for (RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
4549
RegionView* rv = rtv->view()->find_view (*i);
4560
/** Get regions using the following method:
4562
* Make a region list using the selected regions, unless
4563
* the edit point is `mouse' and the mouse is over an unselected
4564
* region. In this case, use just that region.
4566
* If the edit point is not 'mouse', and there are no regions selected,
4567
* search the list of selected tracks and return regions that are under
4568
* the edit point on these tracks. If there are no selected tracks and
4569
* 'No Selection = All Tracks' is active, search all tracks,
4571
* The rationale here is that the mouse edit point is special in that
4572
* its position describes both a time and a track; the other edit
4573
* modes only describe a time. Hence if the edit point is `mouse' we
4574
* ignore selected tracks, as we assume the user means something by
4575
* pointing at a particular track. Also in this case we take note of
4576
* the region directly under the edit point, as there is always just one
4577
* (rather than possibly several with non-mouse edit points).
4581
Editor::get_regions_from_selection_and_edit_point ()
4583
RegionSelection regions;
4585
if (_edit_point == EditAtMouse && entered_regionview && !selection->regions.contains (entered_regionview)) {
4586
regions.add (entered_regionview);
4588
regions = selection->regions;
4592
if (regions.empty() && _edit_point != EditAtMouse) {
4593
TrackViewList tracks = selection->tracks;
4595
if (_route_groups->all_group_active_button().get_active() && tracks.empty()) {
4596
/* tracks is empty (no track selected), and 'No Selection = All Tracks'
4597
* is enabled, so consider all tracks
4599
tracks = track_views;
4602
if (!tracks.empty()) {
4603
/* no region selected or entered, but some selected tracks:
4604
* act on all regions on the selected tracks at the edit point
4606
framepos_t const where = get_preferred_edit_position ();
4607
get_regions_at(regions, where, tracks);
4613
/** Start with regions that are selected, or the entered regionview if none are selected.
4614
* Then add equivalent regions on tracks in the same active edit-enabled route group as any
4615
* of the regions that we started with.
4619
Editor::get_regions_from_selection_and_entered ()
4621
RegionSelection regions = selection->regions;
4623
if (regions.empty() && entered_regionview) {
4624
regions.add (entered_regionview);
4631
Editor::get_regions_corresponding_to (boost::shared_ptr<Region> region, vector<RegionView*>& regions, bool src_comparison)
4633
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4635
RouteTimeAxisView* tatv;
4637
if ((tatv = dynamic_cast<RouteTimeAxisView*> (*i)) != 0) {
4639
boost::shared_ptr<Playlist> pl;
4640
vector<boost::shared_ptr<Region> > results;
4642
boost::shared_ptr<Track> tr;
4644
if ((tr = tatv->track()) == 0) {
4649
if ((pl = (tr->playlist())) != 0) {
4650
if (src_comparison) {
4651
pl->get_source_equivalent_regions (region, results);
4653
pl->get_region_list_equivalent_regions (region, results);
4657
for (vector<boost::shared_ptr<Region> >::iterator ir = results.begin(); ir != results.end(); ++ir) {
4658
if ((marv = tatv->view()->find_view (*ir)) != 0) {
4659
regions.push_back (marv);
4668
Editor::show_rhythm_ferret ()
4670
if (rhythm_ferret == 0) {
4671
rhythm_ferret = new RhythmFerret(*this);
4674
rhythm_ferret->set_session (_session);
4675
rhythm_ferret->show ();
4676
rhythm_ferret->present ();
4680
Editor::first_idle ()
4682
MessageDialog* dialog = 0;
4684
if (track_views.size() > 1) {
4685
dialog = new MessageDialog (
4687
string_compose (_("Please wait while %1 loads visual data."), PROGRAM_NAME),
4691
ARDOUR_UI::instance()->flush_pending ();
4694
for (TrackViewList::iterator t = track_views.begin(); t != track_views.end(); ++t) {
4698
// first idle adds route children (automation tracks), so we need to redisplay here
4699
_routes->redisplay ();
4706
Editor::_idle_resize (gpointer arg)
4708
return ((Editor*)arg)->idle_resize ();
4712
Editor::add_to_idle_resize (TimeAxisView* view, int32_t h)
4714
if (resize_idle_id < 0) {
4715
resize_idle_id = g_idle_add (_idle_resize, this);
4716
_pending_resize_amount = 0;
4719
/* make a note of the smallest resulting height, so that we can clamp the
4720
lower limit at TimeAxisView::hSmall */
4722
int32_t min_resulting = INT32_MAX;
4724
_pending_resize_amount += h;
4725
_pending_resize_view = view;
4727
min_resulting = min (min_resulting, int32_t (_pending_resize_view->current_height()) + _pending_resize_amount);
4729
if (selection->tracks.contains (_pending_resize_view)) {
4730
for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4731
min_resulting = min (min_resulting, int32_t ((*i)->current_height()) + _pending_resize_amount);
4735
if (min_resulting < 0) {
4740
if (uint32_t (min_resulting) < TimeAxisView::preset_height (HeightSmall)) {
4741
_pending_resize_amount += TimeAxisView::preset_height (HeightSmall) - min_resulting;
4745
/** Handle pending resizing of tracks */
4747
Editor::idle_resize ()
4749
_pending_resize_view->idle_resize (_pending_resize_view->current_height() + _pending_resize_amount);
4751
if (dynamic_cast<AutomationTimeAxisView*> (_pending_resize_view) == 0 &&
4752
selection->tracks.contains (_pending_resize_view)) {
4754
for (TrackViewList::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
4755
if (*i != _pending_resize_view) {
4756
(*i)->idle_resize ((*i)->current_height() + _pending_resize_amount);
4761
_pending_resize_amount = 0;
4763
_group_tabs->set_dirty ();
4764
resize_idle_id = -1;
4772
ENSURE_GUI_THREAD (*this, &Editor::located);
4775
playhead_cursor->set_position (_session->audible_frame ());
4776
if (_follow_playhead && !_pending_initial_locate) {
4777
reset_x_origin_to_follow_playhead ();
4781
_pending_locate_request = false;
4782
_pending_initial_locate = false;
4786
Editor::region_view_added (RegionView *)
4788
_summary->set_dirty ();
4792
Editor::region_view_removed ()
4794
_summary->set_dirty ();
4798
Editor::axis_view_from_route (boost::shared_ptr<Route> r) const
4800
TrackViewList::const_iterator j = track_views.begin ();
4801
while (j != track_views.end()) {
4802
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (*j);
4803
if (rtv && rtv->route() == r) {
4814
Editor::axis_views_from_routes (boost::shared_ptr<RouteList> r) const
4818
for (RouteList::const_iterator i = r->begin(); i != r->end(); ++i) {
4819
TimeAxisView* tv = axis_view_from_route (*i);
4829
Editor::add_routes (RouteList& routes)
4831
ENSURE_GUI_THREAD (*this, &Editor::handle_new_route, routes)
4833
RouteTimeAxisView *rtv;
4834
list<RouteTimeAxisView*> new_views;
4836
for (RouteList::iterator x = routes.begin(); x != routes.end(); ++x) {
4837
boost::shared_ptr<Route> route = (*x);
4839
if (route->is_auditioner() || route->is_monitor()) {
4843
DataType dt = route->input()->default_type();
4845
if (dt == ARDOUR::DataType::AUDIO) {
4846
rtv = new AudioTimeAxisView (*this, _session, *track_canvas);
4847
rtv->set_route (route);
4848
} else if (dt == ARDOUR::DataType::MIDI) {
4849
rtv = new MidiTimeAxisView (*this, _session, *track_canvas);
4850
rtv->set_route (route);
4852
throw unknown_type();
4855
new_views.push_back (rtv);
4856
track_views.push_back (rtv);
4858
rtv->effective_gain_display ();
4860
if (internal_editing()) {
4861
rtv->enter_internal_edit_mode ();
4863
rtv->leave_internal_edit_mode ();
4866
rtv->view()->RegionViewAdded.connect (sigc::mem_fun (*this, &Editor::region_view_added));
4867
rtv->view()->RegionViewRemoved.connect (sigc::mem_fun (*this, &Editor::region_view_removed));
4870
_routes->routes_added (new_views);
4871
_summary->routes_added (new_views);
4873
if (show_editor_mixer_when_tracks_arrive) {
4874
show_editor_mixer (true);
4877
editor_list_button.set_sensitive (true);
4881
Editor::timeaxisview_deleted (TimeAxisView *tv)
4883
if (_session && _session->deletion_in_progress()) {
4884
/* the situation is under control */
4888
ENSURE_GUI_THREAD (*this, &Editor::timeaxisview_deleted, tv);
4890
RouteTimeAxisView* rtav = dynamic_cast<RouteTimeAxisView*> (tv);
4892
_routes->route_removed (tv);
4894
if (tv == entered_track) {
4898
TimeAxisView::Children c = tv->get_child_list ();
4899
for (TimeAxisView::Children::const_iterator i = c.begin(); i != c.end(); ++i) {
4900
if (entered_track == i->get()) {
4905
/* remove it from the list of track views */
4907
TrackViewList::iterator i;
4909
if ((i = find (track_views.begin(), track_views.end(), tv)) != track_views.end()) {
4910
i = track_views.erase (i);
4913
/* update whatever the current mixer strip is displaying, if revelant */
4915
boost::shared_ptr<Route> route;
4918
route = rtav->route ();
4921
if (current_mixer_strip && current_mixer_strip->route() == route) {
4923
TimeAxisView* next_tv;
4925
if (track_views.empty()) {
4927
} else if (i == track_views.end()) {
4928
next_tv = track_views.front();
4935
set_selected_mixer_strip (*next_tv);
4937
/* make the editor mixer strip go away setting the
4938
* button to inactive (which also unticks the menu option)
4941
ActionManager::uncheck_toggleaction ("<Actions>/Editor/show-editor-mixer");
4947
Editor::hide_track_in_display (TimeAxisView* tv, bool apply_to_selection)
4949
if (apply_to_selection) {
4950
for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ) {
4952
TrackSelection::iterator j = i;
4955
hide_track_in_display (*i, false);
4960
RouteTimeAxisView* rtv = dynamic_cast<RouteTimeAxisView*> (tv);
4962
if (rtv && current_mixer_strip && (rtv->route() == current_mixer_strip->route())) {
4963
// this will hide the mixer strip
4964
set_selected_mixer_strip (*tv);
4967
_routes->hide_track_in_display (*tv);
4972
Editor::sync_track_view_list_and_routes ()
4974
track_views = TrackViewList (_routes->views ());
4976
_summary->set_dirty ();
4977
_group_tabs->set_dirty ();
4979
return false; // do not call again (until needed)
4983
Editor::foreach_time_axis_view (sigc::slot<void,TimeAxisView&> theslot)
4985
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
4990
/** Find a RouteTimeAxisView by the ID of its route */
4992
Editor::get_route_view_by_route_id (const PBD::ID& id) const
4994
RouteTimeAxisView* v;
4996
for (TrackViewList::const_iterator i = track_views.begin(); i != track_views.end(); ++i) {
4997
if((v = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
4998
if(v->route()->id() == id) {
5008
Editor::fit_route_group (RouteGroup *g)
5010
TrackViewList ts = axis_views_from_routes (g->route_list ());
5015
Editor::consider_auditioning (boost::shared_ptr<Region> region)
5017
boost::shared_ptr<AudioRegion> r = boost::dynamic_pointer_cast<AudioRegion> (region);
5020
_session->cancel_audition ();
5024
if (_session->is_auditioning()) {
5025
_session->cancel_audition ();
5026
if (r == last_audition_region) {
5031
_session->audition_region (r);
5032
last_audition_region = r;
5037
Editor::hide_a_region (boost::shared_ptr<Region> r)
5039
r->set_hidden (true);
5043
Editor::show_a_region (boost::shared_ptr<Region> r)
5045
r->set_hidden (false);
5049
Editor::audition_region_from_region_list ()
5051
_regions->selection_mapover (sigc::mem_fun (*this, &Editor::consider_auditioning));
5055
Editor::hide_region_from_region_list ()
5057
_regions->selection_mapover (sigc::mem_fun (*this, &Editor::hide_a_region));
5061
Editor::show_region_in_region_list ()
5063
_regions->selection_mapover (sigc::mem_fun (*this, &Editor::show_a_region));
5067
Editor::step_edit_status_change (bool yn)
5070
start_step_editing ();
5072
stop_step_editing ();
5077
Editor::start_step_editing ()
5079
step_edit_connection = Glib::signal_timeout().connect (sigc::mem_fun (*this, &Editor::check_step_edit), 20);
5083
Editor::stop_step_editing ()
5085
step_edit_connection.disconnect ();
5089
Editor::check_step_edit ()
5091
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5092
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*> (*i);
5094
mtv->check_step_edit ();
5098
return true; // do it again, till we stop
5102
Editor::scroll_press (Direction dir)
5104
++_scroll_callbacks;
5106
if (_scroll_connection.connected() && _scroll_callbacks < 5) {
5107
/* delay the first auto-repeat */
5113
scroll_backward (1);
5121
scroll_tracks_up_line ();
5125
scroll_tracks_down_line ();
5129
/* do hacky auto-repeat */
5130
if (!_scroll_connection.connected ()) {
5132
_scroll_connection = Glib::signal_timeout().connect (
5133
sigc::bind (sigc::mem_fun (*this, &Editor::scroll_press), dir), 100
5136
_scroll_callbacks = 0;
5143
Editor::scroll_release ()
5145
_scroll_connection.disconnect ();
5148
/** Queue a change for the Editor viewport x origin to follow the playhead */
5150
Editor::reset_x_origin_to_follow_playhead ()
5152
framepos_t const frame = playhead_cursor->current_frame;
5154
if (frame < leftmost_frame || frame > leftmost_frame + current_page_frames()) {
5156
if (_session->transport_speed() < 0) {
5158
if (frame > (current_page_frames() / 2)) {
5159
center_screen (frame-(current_page_frames()/2));
5161
center_screen (current_page_frames()/2);
5168
if (frame < leftmost_frame) {
5170
if (_session->transport_rolling()) {
5171
/* rolling; end up with the playhead at the right of the page */
5172
l = frame - current_page_frames ();
5174
/* not rolling: end up with the playhead 1/4 of the way along the page */
5175
l = frame - current_page_frames() / 4;
5179
if (_session->transport_rolling()) {
5180
/* rolling: end up with the playhead on the left of the page */
5183
/* not rolling: end up with the playhead 3/4 of the way along the page */
5184
l = frame - 3 * current_page_frames() / 4;
5192
center_screen_internal (l + (current_page_frames() / 2), current_page_frames ());
5198
Editor::super_rapid_screen_update ()
5200
if (!_session || !_session->engine().running()) {
5204
/* METERING / MIXER STRIPS */
5206
/* update track meters, if required */
5207
if (is_mapped() && meters_running) {
5208
RouteTimeAxisView* rtv;
5209
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5210
if ((rtv = dynamic_cast<RouteTimeAxisView*>(*i)) != 0) {
5211
rtv->fast_update ();
5216
/* and any current mixer strip */
5217
if (current_mixer_strip) {
5218
current_mixer_strip->fast_update ();
5221
/* PLAYHEAD AND VIEWPORT */
5223
framepos_t const frame = _session->audible_frame();
5225
/* There are a few reasons why we might not update the playhead / viewport stuff:
5227
* 1. we don't update things when there's a pending locate request, otherwise
5228
* when the editor requests a locate there is a chance that this method
5229
* will move the playhead before the locate request is processed, causing
5231
* 2. if we're not rolling, there's nothing to do here (locates are handled elsewhere).
5232
* 3. if we're still at the same frame that we were last time, there's nothing to do.
5235
if (!_pending_locate_request && _session->transport_speed() != 0 && frame != last_update_frame) {
5237
last_update_frame = frame;
5239
if (!_dragging_playhead) {
5240
playhead_cursor->set_position (frame);
5243
if (!_stationary_playhead) {
5245
if (!_dragging_playhead && _follow_playhead && _session->requested_return_frame() < 0 && !pending_visual_change.being_handled) {
5246
/* We only do this if we aren't already
5247
handling a visual change (ie if
5248
pending_visual_change.being_handled is
5249
false) so that these requests don't stack
5250
up there are too many of them to handle in
5253
reset_x_origin_to_follow_playhead ();
5258
/* don't do continuous scroll till the new position is in the rightmost quarter of the
5262
// FIXME DO SOMETHING THAT WORKS HERE - this is 2.X code
5263
double target = ((double)frame - (double)current_page_frames()/2.0) / frames_per_unit;
5264
if (target <= 0.0) {
5267
if (fabs(target - current) < current_page_frames() / frames_per_unit) {
5268
target = (target * 0.15) + (current * 0.85);
5274
set_horizontal_position (current);
5283
Editor::session_going_away ()
5285
_have_idled = false;
5287
_session_connections.drop_connections ();
5289
super_rapid_screen_update_connection.disconnect ();
5291
selection->clear ();
5292
cut_buffer->clear ();
5294
clicked_regionview = 0;
5295
clicked_axisview = 0;
5296
clicked_routeview = 0;
5297
entered_regionview = 0;
5299
last_update_frame = 0;
5302
playhead_cursor->canvas_item.hide ();
5304
/* rip everything out of the list displays */
5308
_route_groups->clear ();
5310
/* do this first so that deleting a track doesn't reset cms to null
5311
and thus cause a leak.
5314
if (current_mixer_strip) {
5315
if (current_mixer_strip->get_parent() != 0) {
5316
global_hpacker.remove (*current_mixer_strip);
5318
delete current_mixer_strip;
5319
current_mixer_strip = 0;
5322
/* delete all trackviews */
5324
for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
5327
track_views.clear ();
5329
zoom_range_clock->set_session (0);
5330
nudge_clock->set_session (0);
5332
editor_list_button.set_active(false);
5333
editor_list_button.set_sensitive(false);
5335
/* clear tempo/meter rulers */
5336
remove_metric_marks ();
5338
clear_marker_display ();
5340
stop_step_editing ();
5342
/* get rid of any existing editor mixer strip */
5344
WindowTitle title(Glib::get_application_name());
5345
title += _("Editor");
5347
set_title (title.get_string());
5349
SessionHandlePtr::session_going_away ();
5354
Editor::show_editor_list (bool yn)
5357
_the_notebook.show ();
5359
_the_notebook.hide ();
5364
Editor::change_region_layering_order (bool from_context_menu)
5366
const framepos_t position = get_preferred_edit_position (false, from_context_menu);
5368
if (!clicked_routeview) {
5369
if (layering_order_editor) {
5370
layering_order_editor->hide ();
5375
boost::shared_ptr<Track> track = boost::dynamic_pointer_cast<Track> (clicked_routeview->route());
5381
boost::shared_ptr<Playlist> pl = track->playlist();
5387
if (layering_order_editor == 0) {
5388
layering_order_editor = new RegionLayeringOrderEditor (*this);
5391
layering_order_editor->set_context (clicked_routeview->name(), _session, clicked_routeview, pl, position);
5392
layering_order_editor->maybe_present ();
5396
Editor::update_region_layering_order_editor ()
5398
if (layering_order_editor && layering_order_editor->is_visible ()) {
5399
change_region_layering_order (true);
5404
Editor::setup_fade_images ()
5406
_fade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadein-linear")));
5407
_fade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadein-short-cut")));
5408
_fade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadein-slow-cut")));
5409
_fade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadein-fast-cut")));
5410
_fade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadein-long-cut")));
5412
_fade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5413
_fade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
5414
_fade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5415
_fade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5416
_fade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
5418
_xfade_in_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5419
_xfade_in_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
5420
_xfade_in_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5421
_xfade_in_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5422
_xfade_in_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
5424
_xfade_out_images[FadeLinear] = new Gtk::Image (get_icon_path (X_("fadeout-linear")));
5425
_xfade_out_images[FadeSymmetric] = new Gtk::Image (get_icon_path (X_("fadeout-short-cut")));
5426
_xfade_out_images[FadeFast] = new Gtk::Image (get_icon_path (X_("fadeout-slow-cut")));
5427
_xfade_out_images[FadeSlow] = new Gtk::Image (get_icon_path (X_("fadeout-fast-cut")));
5428
_xfade_out_images[FadeConstantPower] = new Gtk::Image (get_icon_path (X_("fadeout-long-cut")));
5432
/** @return Gtk::manage()d menu item for a given action from `editor_actions' */
5434
Editor::action_menu_item (std::string const & name)
5436
Glib::RefPtr<Action> a = editor_actions->get_action (name);
5439
return *manage (a->create_menu_item ());
5443
Editor::add_notebook_page (string const & name, Gtk::Widget& widget)
5445
EventBox* b = manage (new EventBox);
5446
b->signal_button_press_event().connect (sigc::bind (sigc::mem_fun (*this, &Editor::notebook_tab_clicked), &widget));
5447
Label* l = manage (new Label (name));
5451
_the_notebook.append_page (widget, *b);
5455
Editor::notebook_tab_clicked (GdkEventButton* ev, Gtk::Widget* page)
5457
if (ev->type == GDK_BUTTON_PRESS || ev->type == GDK_2BUTTON_PRESS) {
5458
_the_notebook.set_current_page (_the_notebook.page_num (*page));
5461
if (ev->type == GDK_2BUTTON_PRESS) {
5463
/* double-click on a notebook tab shrinks or expands the notebook */
5465
if (_notebook_shrunk) {
5466
if (pre_notebook_shrink_pane_width) {
5467
edit_pane.set_position (*pre_notebook_shrink_pane_width);
5469
_notebook_shrunk = false;
5471
pre_notebook_shrink_pane_width = edit_pane.get_position();
5473
/* this expands the LHS of the edit pane to cover the notebook
5474
PAGE but leaves the tabs visible.
5476
edit_pane.set_position (edit_pane.get_position() + page->get_width());
5477
_notebook_shrunk = true;
5485
Editor::popup_control_point_context_menu (ArdourCanvas::Item* item, GdkEvent* event)
5487
using namespace Menu_Helpers;
5489
MenuList& items = _control_point_context_menu.items ();
5492
items.push_back (MenuElem (_("Edit..."), sigc::bind (sigc::mem_fun (*this, &Editor::edit_control_point), item)));
5493
items.push_back (MenuElem (_("Delete"), sigc::bind (sigc::mem_fun (*this, &Editor::remove_control_point), item)));
5494
if (!can_remove_control_point (item)) {
5495
items.back().set_sensitive (false);
5498
_control_point_context_menu.popup (event->button.button, event->button.time);
5502
Editor::zoom_vertical_modifier_released()
5504
_stepping_axis_view = 0;