2 Copyright (C) 2000-2006 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.
27 #include <sigc++/bind.h>
29 #include <pbd/error.h>
31 #include <gtkmm/image.h>
32 #include <gdkmm/color.h>
33 #include <gdkmm/bitmap.h>
35 #include <gtkmm2ext/gtk_ui.h>
36 #include <gtkmm2ext/tearoff.h>
37 #include <gtkmm2ext/utils.h>
39 #include <ardour/audio_track.h>
40 #include <ardour/diskstream.h>
41 #include <ardour/plugin_manager.h>
42 #include <ardour/location.h>
43 #include <ardour/audioplaylist.h>
44 #include <ardour/audioregion.h>
45 #include <ardour/region.h>
46 #include <ardour/session_route.h>
47 #include <ardour/tempo.h>
48 #include <ardour/utils.h>
50 #include "ardour_ui.h"
52 #include "grouped_buttons.h"
55 #include "playlist_selector.h"
56 #include "regionview.h"
57 #include "rgb_macros.h"
58 #include "selection.h"
59 #include "streamview.h"
60 #include "time_axis_view.h"
62 #include "crossfade_view.h"
64 #include "public_editor.h"
65 #include "crossfade_edit.h"
66 #include "audio_time_axis.h"
67 #include "canvas_impl.h"
69 #include "gui_thread.h"
74 #include "imageframe_socket_handler.h"
75 /* </CMT Additions> */
79 using namespace ARDOUR;
82 using namespace Gtkmm2ext;
83 using namespace Editing;
85 const double Editor::timebar_height = 15.0;
87 #include "editor_xpms"
89 static const int32_t slide_index = 0;
90 static const int32_t splice_index = 1;
92 static const gchar *edit_mode_strings[] = {
98 static const gchar *snap_type_strings[] = {
122 static const gchar *snap_mode_strings[] = {
128 static const gchar *zoom_focus_strings[] = {
137 /* Soundfile drag-n-drop */
139 Gdk::Cursor* Editor::cross_hair_cursor = 0;
140 Gdk::Cursor* Editor::selector_cursor = 0;
141 Gdk::Cursor* Editor::trimmer_cursor = 0;
142 Gdk::Cursor* Editor::grabber_cursor = 0;
143 Gdk::Cursor* Editor::zoom_cursor = 0;
144 Gdk::Cursor* Editor::time_fx_cursor = 0;
145 Gdk::Cursor* Editor::fader_cursor = 0;
146 Gdk::Cursor* Editor::speaker_cursor = 0;
147 Gdk::Cursor* Editor::wait_cursor = 0;
148 Gdk::Cursor* Editor::timebar_cursor = 0;
151 Editor::on_key_press_event (GdkEventKey* ev)
153 GtkWindow* win = gobj();
155 /* This exists to allow us to override the way GTK handles
156 key events. The normal sequence is:
158 a) event is delivered to a GtkWindow
159 b) accelerators/mnemonics are activated
160 c) if (b) didn't handle the event, propagate to
161 the focus widget and/or focus chain
163 The problem with this is that if the accelerators include
164 keys without modifiers, such as the space bar or the
165 letter "e", then pressing the key while typing into
166 a text entry widget results in the accelerator being
167 activated, instead of the desired letter appearing
170 There is no good way of fixing this, but this
171 represents a compromise. The idea is that
172 key events involving modifiers (not Shift)
173 get routed into the activation pathway first, then
174 get propagated to the focus widget if necessary.
176 If the key event doesn't involve modifiers,
177 we deliver to the focus widget first, thus allowing
178 it to get "normal text" without interference
181 Of course, this can also be problematic: if there
182 is a widget with focus, then it will swallow
183 all "normal text" accelerators.
186 if (ev->state & ~Gdk::SHIFT_MASK) {
187 /* modifiers in effect, accelerate first */
188 if (!gtk_window_activate_key (win, ev)) {
189 return gtk_window_propagate_key_event (win, ev);
195 /* no modifiers, propagate first */
197 if (!gtk_window_propagate_key_event (win, ev)) {
198 return gtk_window_activate_key (win, ev);
206 show_me_the_size (Requisition* r, const char* what)
208 cerr << "size of " << what << " = " << r->width << " x " << r->height << endl;
211 Editor::Editor (AudioEngine& eng)
214 /* time display buttons */
216 minsec_label (_("Mins:Secs")),
217 bbt_label (_("Bars:Beats")),
218 smpte_label (_("SMPTE")),
219 frame_label (_("Frames")),
220 tempo_label (_("Tempo")),
221 meter_label (_("Meter")),
222 mark_label (_("Location Markers")),
223 range_mark_label (_("Range Markers")),
224 transport_mark_label (_("Loop/Punch Ranges")),
226 edit_packer (3, 3, false),
228 /* the values here don't matter: layout widgets
229 reset them as needed.
232 vertical_adjustment (0.0, 0.0, 400.0, 10),
233 horizontal_adjustment (0.0, 0.0, 1200.0, 20),
235 /* tool bar related */
237 selection_start_clock (X_("SelectionStartClock"), true),
238 selection_end_clock (X_("SelectionEndClock"), true),
239 edit_cursor_clock (X_("EditCursorClock"), true),
240 zoom_range_clock (X_("ZoomRangeClock"), true, true),
242 toolbar_selection_clock_table (2,3),
244 mouse_mode_button_table (2, 3),
246 mouse_select_button (_("range")),
247 mouse_move_button (_("object")),
248 mouse_gain_button (_("gain")),
249 mouse_zoom_button (_("zoom")),
250 mouse_timefx_button (_("timefx")),
251 mouse_audition_button (_("listen")),
253 automation_mode_button (_("mode")),
254 global_automation_button (_("automation")),
256 edit_mode_label (_("Edit Mode")),
257 snap_type_label (_("Snap To")),
258 snap_mode_label(_("Snap Mode")),
259 zoom_focus_label (_("Zoom Focus")),
261 /* <CMT Additions> */
262 image_socket_listener(0),
263 /* </CMT Additions> */
267 nudge_label (_("Nudge")),
268 nudge_clock (X_("NudgeClock"), true, true)
273 /* we are a singleton */
275 PublicEditor::_instance = this;
281 selection = new Selection;
282 cut_buffer = new Selection;
284 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
285 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
286 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
287 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
289 clicked_regionview = 0;
290 clicked_trackview = 0;
291 clicked_audio_trackview = 0;
292 clicked_crossfadeview = 0;
293 clicked_control_point = 0;
294 latest_regionview = 0;
295 last_update_frame = 0;
297 last_audition_region = 0;
298 current_mixer_strip = 0;
299 current_bbt_points = 0;
301 snap_type = SnapToFrame;
302 set_snap_to (snap_type);
303 snap_mode = SnapNormal;
304 set_snap_mode (snap_mode);
305 snap_threshold = 5.0;
306 bbt_beat_subdivision = 4;
309 autoscroll_timeout_tag = -1;
310 interthread_progress_window = 0;
311 current_interthread_info = 0;
312 _show_measures = true;
313 _show_waveforms = true;
314 _show_waveforms_recording = true;
315 first_action_message = 0;
317 show_gain_after_trim = false;
318 no_zoom_repos_update = false;
319 ignore_route_list_reorder = false;
320 no_route_list_redisplay = false;
321 verbose_cursor_on = true;
322 route_removal = false;
324 show_automatic_regions_in_region_list = true;
325 region_list_sort_type = (Editing::RegionListSortType) 0;
326 have_pending_keyboard_selection = false;
327 _follow_playhead = true;
328 _xfade_visibility = true;
329 editor_ruler_menu = 0;
330 no_ruler_shown_update = false;
331 edit_hscroll_dragging = false;
332 edit_group_list_menu = 0;
334 region_list_menu = 0;
336 marker_menu_item = 0;
338 transport_marker_menu = 0;
339 new_transport_marker_menu = 0;
340 editor_mixer_strip_width = Wide;
341 repos_zoom_queued = false;
342 region_edit_menu_split_item = 0;
344 region_edit_menu_split_multichannel_item = 0;
346 ignore_mouse_mode_toggle = false;
347 current_stepping_trackview = 0;
349 entered_regionview = 0;
350 clear_entered_track = false;
351 _new_regionviews_show_envelope = false;
352 current_timestretch = 0;
357 location_marker_color = color_map[cLocationMarker];
358 location_range_color = color_map[cLocationRange];
359 location_cd_marker_color = color_map[cLocationCDMarker];
360 location_loop_color = color_map[cLocationLoop];
361 location_punch_color = color_map[cLocationPunch];
363 range_marker_drag_rect = 0;
364 marker_drag_line = 0;
366 set_mouse_mode (MouseObject, true);
368 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
369 zoom_focus = ZoomFocusLeft;
370 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
372 initialize_rulers ();
373 initialize_canvas ();
375 edit_controls_vbox.set_spacing (0);
376 horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
377 vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
379 track_canvas.set_hadjustment (horizontal_adjustment);
380 track_canvas.set_vadjustment (vertical_adjustment);
381 time_canvas.set_hadjustment (horizontal_adjustment);
383 track_canvas.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
384 time_canvas.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
386 controls_layout.add (edit_controls_vbox);
387 controls_layout.set_name ("EditControlsBase");
388 controls_layout.add_events (Gdk::SCROLL_MASK);
389 controls_layout.signal_scroll_event().connect (mem_fun(*this, &Editor::control_layout_scroll), false);
391 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
392 controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
393 controls_layout.signal_size_request().connect (mem_fun (*this, &Editor::controls_layout_size_request));
395 edit_vscrollbar.set_adjustment (vertical_adjustment);
396 edit_hscrollbar.set_adjustment (horizontal_adjustment);
398 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscrollbar_button_press));
399 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release));
400 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate));
405 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
407 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
408 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
409 time_canvas_vbox.pack_start (*frames_ruler, false, false);
410 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
411 time_canvas_vbox.pack_start (time_canvas, true, true);
412 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
414 bbt_label.set_name ("EditorTimeButton");
415 bbt_label.set_size_request (-1, (int)timebar_height);
416 bbt_label.set_alignment (1.0, 0.5);
417 bbt_label.set_padding (5,0);
418 minsec_label.set_name ("EditorTimeButton");
419 minsec_label.set_size_request (-1, (int)timebar_height);
420 minsec_label.set_alignment (1.0, 0.5);
421 minsec_label.set_padding (5,0);
422 smpte_label.set_name ("EditorTimeButton");
423 smpte_label.set_size_request (-1, (int)timebar_height);
424 smpte_label.set_alignment (1.0, 0.5);
425 smpte_label.set_padding (5,0);
426 frame_label.set_name ("EditorTimeButton");
427 frame_label.set_size_request (-1, (int)timebar_height);
428 frame_label.set_alignment (1.0, 0.5);
429 frame_label.set_padding (5,0);
430 tempo_label.set_name ("EditorTimeButton");
431 tempo_label.set_size_request (-1, (int)timebar_height);
432 tempo_label.set_alignment (1.0, 0.5);
433 tempo_label.set_padding (5,0);
434 meter_label.set_name ("EditorTimeButton");
435 meter_label.set_size_request (-1, (int)timebar_height);
436 meter_label.set_alignment (1.0, 0.5);
437 meter_label.set_padding (5,0);
438 mark_label.set_name ("EditorTimeButton");
439 mark_label.set_size_request (-1, (int)timebar_height);
440 mark_label.set_alignment (1.0, 0.5);
441 mark_label.set_padding (5,0);
442 range_mark_label.set_name ("EditorTimeButton");
443 range_mark_label.set_size_request (-1, (int)timebar_height);
444 range_mark_label.set_alignment (1.0, 0.5);
445 range_mark_label.set_padding (5,0);
446 transport_mark_label.set_name ("EditorTimeButton");
447 transport_mark_label.set_size_request (-1, (int)timebar_height);
448 transport_mark_label.set_alignment (1.0, 0.5);
449 transport_mark_label.set_padding (5,0);
451 time_button_vbox.pack_start (minsec_label, false, false);
452 time_button_vbox.pack_start (smpte_label, false, false);
453 time_button_vbox.pack_start (frame_label, false, false);
454 time_button_vbox.pack_start (bbt_label, false, false);
455 time_button_vbox.pack_start (meter_label, false, false);
456 time_button_vbox.pack_start (tempo_label, false, false);
457 time_button_vbox.pack_start (mark_label, false, false);
459 time_button_event_box.add (time_button_vbox);
461 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
462 time_button_event_box.set_name ("TimebarLabelBase");
463 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
465 /* these enable us to have a dedicated window (for cursor setting, etc.)
466 for the canvas areas.
469 track_canvas_event_box.add (track_canvas);
471 time_canvas_event_box.add (time_canvas_vbox);
472 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
474 edit_packer.set_col_spacings (0);
475 edit_packer.set_row_spacings (0);
476 edit_packer.set_homogeneous (false);
477 edit_packer.set_name ("EditorWindow");
479 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
481 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
482 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
484 edit_packer.attach (controls_layout, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
485 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
486 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
488 edit_frame.set_name ("BaseFrame");
489 edit_frame.set_shadow_type (SHADOW_IN);
490 edit_frame.add (edit_packer);
492 zoom_in_button.set_name ("EditorTimeButton");
493 zoom_out_button.set_name ("EditorTimeButton");
494 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
495 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
497 zoom_out_full_button.set_name ("EditorTimeButton");
498 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
500 zoom_in_button.add (*(manage (new Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
501 zoom_out_button.add (*(manage (new Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
502 zoom_out_full_button.add (*(manage (new Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
504 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
505 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
506 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
508 zoom_indicator_box.pack_start (zoom_out_button, false, false);
509 zoom_indicator_box.pack_start (zoom_in_button, false, false);
510 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
511 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
513 zoom_indicator_label.set_text (_("Zoom Span"));
514 zoom_indicator_label.set_name ("ToolBarLabel");
516 zoom_indicator_vbox.set_spacing (3);
517 zoom_indicator_vbox.set_border_width (3);
518 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
519 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
521 bottom_hbox.set_border_width (3);
522 bottom_hbox.set_spacing (3);
524 route_display_model = ListStore::create(route_display_columns);
525 route_list_display.set_model (route_display_model);
526 route_list_display.append_column (_("Visible"), route_display_columns.visible);
527 route_list_display.append_column (_("Name"), route_display_columns.text);
528 route_list_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
529 route_list_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
530 route_list_display.set_headers_visible (true);
531 route_list_display.set_name ("TrackListDisplay");
532 route_list_display.get_selection()->set_mode (SELECTION_NONE);
533 route_list_display.set_reorderable (true);
534 route_list_display.set_size_request (100,-1);
536 CellRendererToggle* route_list_visible_cell = dynamic_cast<CellRendererToggle*>(route_list_display.get_column_cell_renderer (0));
537 route_list_visible_cell->property_activatable() = true;
538 route_list_visible_cell->property_radio() = false;
540 route_display_model->signal_row_deleted().connect (mem_fun (*this, &Editor::route_list_delete));
541 route_display_model->signal_row_changed().connect (mem_fun (*this, &Editor::route_list_change));
543 route_list_display.signal_button_press_event().connect (mem_fun (*this, &Editor::route_list_display_button_press), false);
545 route_list_scroller.add (route_list_display);
546 route_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
548 group_model = ListStore::create(group_columns);
549 edit_group_display.set_model (group_model);
550 edit_group_display.append_column (_("Active"), group_columns.is_active);
551 edit_group_display.append_column (_("Visible"), group_columns.is_visible);
552 edit_group_display.append_column (_("Name"), group_columns.text);
553 edit_group_display.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
554 edit_group_display.get_column (1)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
555 edit_group_display.get_column (2)->set_data (X_("colnum"), GUINT_TO_POINTER(2));
556 edit_group_display.set_headers_visible (true);
558 /* use checkbox for the active + visible columns */
560 CellRendererToggle* active_cell = dynamic_cast<CellRendererToggle*>(edit_group_display.get_column_cell_renderer (0));
561 active_cell->property_activatable() = true;
562 active_cell->property_radio() = false;
564 active_cell = dynamic_cast<CellRendererToggle*>(edit_group_display.get_column_cell_renderer (1));
565 active_cell->property_activatable() = true;
566 active_cell->property_radio() = false;
568 edit_group_display.set_name ("EditGroupList");
570 group_model->signal_row_changed().connect (mem_fun (*this, &Editor::edit_group_row_change));
572 edit_group_display.set_name ("EditGroupList");
573 edit_group_display.get_selection()->set_mode (SELECTION_NONE);
574 edit_group_display.set_reorderable (false);
576 edit_group_display.set_size_request (75, -1);
578 edit_group_display_scroller.add (edit_group_display);
579 edit_group_display_scroller.set_policy (POLICY_AUTOMATIC, POLICY_AUTOMATIC);
581 edit_group_display.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event), false);
585 row = *(group_model->append());
586 row[group_columns.is_active] = false;
587 row[group_columns.is_visible] = true;
588 row[group_columns.text] = (_("-all-"));
589 row[group_columns.routegroup] = 0;
592 region_list_display.set_size_request (100, -1);
593 region_list_display.set_name ("RegionListDisplay");
595 region_list_model = TreeStore::create (region_list_columns);
596 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
597 region_list_model->set_sort_column (0, SORT_ASCENDING);
599 region_list_display.set_model (region_list_model);
600 region_list_display.append_column (_("Regions"), region_list_columns.name);
601 region_list_display.set_headers_visible (false);
603 region_list_display.get_selection()->set_select_function (mem_fun (*this, &Editor::region_list_selection_filter));
605 TreeViewColumn* tv_col = region_list_display.get_column(0);
606 CellRendererText* renderer = dynamic_cast<CellRendererText*>(region_list_display.get_column_cell_renderer (0));
607 tv_col->add_attribute(renderer->property_text(), region_list_columns.name);
608 tv_col->add_attribute(renderer->property_foreground_gdk(), region_list_columns.color_);
610 region_list_display.get_selection()->set_mode (SELECTION_MULTIPLE);
611 region_list_display.add_object_drag (region_list_columns.region.index(), "regions");
613 /* setup DnD handling */
615 list<TargetEntry> region_list_target_table;
617 region_list_target_table.push_back (TargetEntry ("text/plain"));
618 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
619 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
621 region_list_display.add_drop_targets (region_list_target_table);
622 region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
624 region_list_scroller.add (region_list_display);
625 region_list_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
627 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
628 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
629 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press), false);
630 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
631 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
632 // region_list_display.signal_popup_menu().connect (bind (mem_fun (*this, &Editor::show_region_list_display_context_menu), 1, 0));
634 named_selection_scroller.add (named_selection_display);
635 named_selection_scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
637 named_selection_model = TreeStore::create (named_selection_columns);
638 named_selection_display.set_model (named_selection_model);
639 named_selection_display.append_column (_("Chunks"), named_selection_columns.text);
640 named_selection_display.set_headers_visible (false);
641 named_selection_display.set_size_request (100, -1);
642 named_selection_display.set_name ("RegionListDisplay");
644 named_selection_display.get_selection()->set_mode (SELECTION_SINGLE);
645 named_selection_display.set_size_request (100, -1);
646 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press), false);
647 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
651 snapshot_display_model = ListStore::create (snapshot_display_columns);
652 snapshot_display.set_model (snapshot_display_model);
653 snapshot_display.append_column (X_("snapshot"), snapshot_display_columns.visible_name);
654 snapshot_display.set_name ("SnapshotDisplayList");
655 snapshot_display.set_size_request (75, -1);
656 snapshot_display.set_headers_visible (false);
657 snapshot_display.set_reorderable (false);
658 snapshot_display_scroller.add (snapshot_display);
659 snapshot_display_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
661 snapshot_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::snapshot_display_selection_changed));
662 snapshot_display.signal_button_press_event().connect (mem_fun (*this, &Editor::snapshot_display_button_press), false);
664 the_notebook.append_page (region_list_scroller, _("Regions"));
665 the_notebook.append_page (route_list_scroller, _("Tracks/Busses"));
666 the_notebook.append_page (snapshot_display_scroller, _("Snapshots"));
667 the_notebook.append_page (edit_group_display_scroller, _("Edit Groups"));
668 the_notebook.append_page (named_selection_scroller, _("Chunks"));
669 the_notebook.set_show_tabs (true);
670 the_notebook.set_scrollable (true);
671 the_notebook.popup_enable ();
673 TearOff *notebook_tearoff = manage (new TearOff (the_notebook, true));
674 notebook_tearoff->tearoff_window().set_size_request (200, 400);
676 edit_pane.pack1 (edit_frame, true, true);
677 edit_pane.pack2 (*notebook_tearoff, false, true);
679 edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Paned*> (&edit_pane)));
681 top_hbox.pack_start (toolbar_frame, true, true);
683 HBox *hbox = manage (new HBox);
684 hbox->pack_start (edit_pane, true, true);
686 global_vpacker.pack_start (top_hbox, false, false);
687 global_vpacker.pack_start (*hbox, true, true);
689 global_hpacker.pack_start (global_vpacker, true, true);
691 set_name ("EditorWindow");
692 add_accel_group (ActionManager::ui_manager->get_accel_group());
694 vpacker.pack_end (global_hpacker, true, true);
696 /* register actions now so that set_state() can find them and set toggles/checks etc */
700 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
703 _playlist_selector = new PlaylistSelector();
704 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
706 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
710 nudge_forward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
711 nudge_backward_button.add (*(manage (new Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
713 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
714 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
716 nudge_forward_button.set_name ("TransportButton");
717 nudge_backward_button.set_name ("TransportButton");
719 fade_context_menu.set_name ("ArdourContextMenu");
721 set_title (_("ardour: editor"));
722 set_wmclass (_("ardour_editor"), "Ardour");
725 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
727 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
728 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
736 /* <CMT Additions> */
737 if(image_socket_listener)
739 if(image_socket_listener->is_connected())
741 image_socket_listener->close_connection() ;
744 delete image_socket_listener ;
745 image_socket_listener = 0 ;
747 /* </CMT Additions> */
751 Editor::add_toplevel_controls (Container& cont)
753 vpacker.pack_start (cont, false, false);
758 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
760 /* note: the selection will take care of the vanishing
761 audioregionview by itself.
764 if (clicked_regionview == rv) {
765 clicked_regionview = 0;
768 if (entered_regionview == rv) {
769 set_entered_regionview (0);
774 Editor::set_entered_regionview (AudioRegionView* rv)
776 if (rv == entered_regionview) {
780 if (entered_regionview) {
781 entered_regionview->exited ();
784 if ((entered_regionview = rv) != 0) {
785 entered_regionview->entered ();
790 Editor::set_entered_track (TimeAxisView* tav)
793 entered_track->exited ();
796 if ((entered_track = tav) != 0) {
797 entered_track->entered ();
802 Editor::left_track_canvas (GdkEventCrossing *ev)
804 set_entered_track (0);
805 set_entered_regionview (0);
811 Editor::show_window ()
816 /* now reset all audio_time_axis heights, because widgets might need
822 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
823 tv = (static_cast<TimeAxisView*>(*i));
829 Editor::tie_vertical_scrolling ()
831 double y1 = vertical_adjustment.get_value();
832 controls_layout.get_vadjustment()->set_value (y1);
833 playhead_cursor->set_y_axis(y1);
834 edit_cursor->set_y_axis(y1);
838 Editor::set_frames_per_unit (double fpu)
840 jack_nframes_t frames;
842 if (fpu == frames_per_unit) {
850 // convert fpu to frame count
852 frames = (jack_nframes_t) floor (fpu * canvas_width);
854 /* don't allow zooms that fit more than the maximum number
855 of frames into an 800 pixel wide space.
858 if (max_frames / fpu < 800.0) {
862 frames_per_unit = fpu;
864 if (frames != zoom_range_clock.current_duration()) {
865 zoom_range_clock.set (frames);
868 /* only update these if we not about to call reposition_x_origin,
869 which will do the same updates.
872 if (session && !no_zoom_repos_update) {
873 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
876 if (!no_zoom_repos_update) {
877 horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
878 update_fixed_rulers ();
879 tempo_map_changed (Change (0));
882 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
883 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
884 (*i)->reshow_selection (selection->time);
888 ZoomChanged (); /* EMIT_SIGNAL */
890 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
891 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
898 Editor::instant_save ()
900 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
905 session->add_instant_xml(get_state(), session->path());
907 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
912 Editor::reposition_x_origin (jack_nframes_t frame)
914 if (frame != leftmost_frame) {
915 leftmost_frame = frame;
916 double pixel = frame_to_pixel (frame);
917 if (pixel >= horizontal_adjustment.get_upper()) {
918 horizontal_adjustment.set_upper (frame_to_pixel (frame + (current_page_frames())));
920 horizontal_adjustment.set_value (frame/frames_per_unit);
921 XOriginChanged (); /* EMIT_SIGNAL */
926 Editor::edit_cursor_clock_changed()
928 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
929 edit_cursor->set_position (edit_cursor_clock.current_time());
935 Editor::zoom_adjustment_changed ()
937 if (session == 0 || no_zoom_repos_update) {
941 double fpu = zoom_range_clock.current_duration() / canvas_width;
945 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
946 } else if (fpu > session->current_end_frame() / canvas_width) {
947 fpu = session->current_end_frame() / canvas_width;
948 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
955 Editor::canvas_horizontally_scrolled ()
957 leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
959 update_fixed_rulers ();
961 if (!edit_hscroll_dragging) {
962 tempo_map_changed (Change (0));
964 update_tempo_based_rulers();
969 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
971 if (!repos_zoom_queued) {
972 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
973 repos_zoom_queued = true;
978 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
980 /* if we need to force an update to the hscroller stuff,
981 don't set no_zoom_repos_update.
984 no_zoom_repos_update = (frame != leftmost_frame);
986 set_frames_per_unit (nfpu);
987 if (no_zoom_repos_update) {
988 reposition_x_origin (frame);
990 no_zoom_repos_update = false;
991 repos_zoom_queued = false;
997 Editor::on_realize ()
999 Window::on_realize ();
1004 Editor::queue_session_control_changed (Session::ControlType t)
1006 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1010 Editor::session_control_changed (Session::ControlType t)
1012 // right now we're only tracking the loop and punch state
1015 case Session::AutoLoop:
1016 update_loop_range_view (true);
1018 case Session::PunchIn:
1019 case Session::PunchOut:
1020 update_punch_range_view (true);
1029 Editor::fake_add_edit_group (RouteGroup *group)
1031 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1035 Editor::fake_handle_new_audio_region (AudioRegion *region)
1037 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1041 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1043 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1047 Editor::fake_handle_new_duration ()
1049 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1053 Editor::start_scrolling ()
1055 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1056 (mem_fun(*this, &Editor::update_current_screen));
1058 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1059 (mem_fun(*this, &Editor::update_slower));
1063 Editor::stop_scrolling ()
1065 scroll_connection.disconnect ();
1066 slower_update_connection.disconnect ();
1070 Editor::map_position_change (jack_nframes_t frame)
1072 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1074 if (session == 0 || !_follow_playhead) {
1078 center_screen (frame);
1079 playhead_cursor->set_position (frame);
1083 Editor::center_screen (jack_nframes_t frame)
1085 double page = canvas_width * frames_per_unit;
1087 /* if we're off the page, then scroll.
1090 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1091 center_screen_internal (frame, page);
1096 Editor::center_screen_internal (jack_nframes_t frame, float page)
1101 frame -= (jack_nframes_t) page;
1106 reposition_x_origin (frame);
1110 Editor::handle_new_duration ()
1112 reset_scrolling_region ();
1115 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
1116 horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
1121 Editor::update_title_s (const string & snap_name)
1123 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1129 Editor::update_title ()
1131 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1134 bool dirty = session->dirty();
1136 string wintitle = _("ardour: editor: ");
1142 wintitle += session->name();
1144 if (session->snap_name() != session->name()) {
1146 wintitle += session->snap_name();
1153 set_title (wintitle);
1158 Editor::connect_to_session (Session *t)
1162 if (first_action_message) {
1163 first_action_message->hide();
1168 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1170 /* These signals can all be emitted by a non-GUI thread. Therefore the
1171 handlers for them must not attempt to directly interact with the GUI,
1172 but use Gtkmm2ext::UI::instance()->call_slot();
1175 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1176 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1177 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1178 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1179 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1180 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1181 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1182 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1183 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1184 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1185 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1186 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1187 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1189 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1190 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1192 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1194 session->foreach_edit_group(this, &Editor::add_edit_group);
1196 edit_cursor_clock.set_session (session);
1197 selection_start_clock.set_session (session);
1198 selection_end_clock.set_session (session);
1199 zoom_range_clock.set_session (session);
1200 _playlist_selector->set_session (session);
1201 nudge_clock.set_session (session);
1203 switch (session->get_edit_mode()) {
1205 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1209 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1213 Location* loc = session->locations()->auto_loop_location();
1215 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1216 if (loc->start() == loc->end()) {
1217 loc->set_end (loc->start() + 1);
1219 session->locations()->add (loc, false);
1220 session->set_auto_loop_location (loc);
1224 loc->set_name (_("Loop"));
1227 loc = session->locations()->auto_punch_location();
1229 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1230 if (loc->start() == loc->end()) {
1231 loc->set_end (loc->start() + 1);
1233 session->locations()->add (loc, false);
1234 session->set_auto_punch_location (loc);
1238 loc->set_name (_("Punch"));
1241 update_loop_range_view (true);
1242 update_punch_range_view (true);
1244 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1245 session->StateSaved.connect (mem_fun(*this, &Editor::session_state_saved));
1247 refresh_location_display ();
1248 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1249 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1250 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1251 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1252 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1254 reset_scrolling_region ();
1256 redisplay_regions ();
1257 redisplay_named_selections ();
1258 redisplay_snapshots ();
1260 initial_route_list_display ();
1262 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1263 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1266 /* ::reposition_x_origin() doesn't work right here, since the old
1267 position may be zero already, and it does nothing in such
1273 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
1274 horizontal_adjustment.set_value (0);
1276 restore_ruler_visibility ();
1277 tempo_map_changed (Change (0));
1279 edit_cursor->set_position (0);
1280 playhead_cursor->set_position (0);
1284 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1287 /* don't show master bus in a new session */
1289 if (ARDOUR_UI::instance()->session_is_new ()) {
1291 TreeModel::Children rows = route_display_model->children();
1292 TreeModel::Children::iterator i;
1294 no_route_list_redisplay = true;
1296 for (i = rows.begin(); i != rows.end(); ++i) {
1297 TimeAxisView *tv = (*i)[route_display_columns.tv];
1298 AudioTimeAxisView *atv;
1300 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1301 if (atv->route().master()) {
1302 route_list_display.get_selection()->unselect (i);
1307 no_route_list_redisplay = false;
1308 redisplay_route_list ();
1313 Editor::build_cursors ()
1315 using namespace Gdk;
1317 Gdk::Color mbg ("#000000" ); /* Black */
1318 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1321 RefPtr<Bitmap> source, mask;
1322 source = Bitmap::create (mag_bits, mag_width, mag_height);
1323 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1324 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1327 Gdk::Color fbg ("#ffffff" );
1328 Gdk::Color ffg ("#000000" );
1331 RefPtr<Bitmap> source, mask;
1333 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1334 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1335 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1339 RefPtr<Bitmap> source, mask;
1340 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1341 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1342 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1345 grabber_cursor = new Gdk::Cursor (HAND2);
1346 cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
1347 trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW);
1348 selector_cursor = new Gdk::Cursor (XTERM);
1349 time_fx_cursor = new Gdk::Cursor (SIZING);
1350 wait_cursor = new Gdk::Cursor (WATCH);
1351 timebar_cursor = new Gdk::Cursor(LEFT_PTR);
1355 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1357 using namespace Menu_Helpers;
1358 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1361 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1365 MenuList& items (fade_context_menu.items());
1369 switch (item_type) {
1371 case FadeInHandleItem:
1372 if (arv->region.fade_in_active()) {
1373 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1375 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1378 items.push_back (SeparatorElem());
1380 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1381 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1382 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1383 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1384 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1388 case FadeOutHandleItem:
1389 if (arv->region.fade_out_active()) {
1390 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1392 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1395 items.push_back (SeparatorElem());
1397 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1398 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1399 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1400 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1401 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1405 fatal << _("programming error: ")
1406 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1411 fade_context_menu.popup (button, time);
1415 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1417 using namespace Menu_Helpers;
1418 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1421 switch (item_type) {
1423 case AudioRegionViewName:
1424 case AudioRegionViewNameHighlight:
1425 if (with_selection) {
1426 build_menu_function = &Editor::build_track_selection_context_menu;
1428 build_menu_function = &Editor::build_track_region_context_menu;
1433 if (with_selection) {
1434 build_menu_function = &Editor::build_track_selection_context_menu;
1436 build_menu_function = &Editor::build_track_context_menu;
1440 case CrossfadeViewItem:
1441 build_menu_function = &Editor::build_track_crossfade_context_menu;
1445 if (clicked_audio_trackview->get_diskstream()) {
1446 build_menu_function = &Editor::build_track_context_menu;
1448 build_menu_function = &Editor::build_track_bus_context_menu;
1453 /* probably shouldn't happen but if it does, we don't care */
1457 menu = (this->*build_menu_function)(frame);
1458 menu->set_name ("ArdourContextMenu");
1460 /* now handle specific situations */
1462 switch (item_type) {
1464 case AudioRegionViewName:
1465 case AudioRegionViewNameHighlight:
1466 if (!with_selection) {
1467 if (region_edit_menu_split_item) {
1468 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1469 ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, true);
1471 ActionManager::set_sensitive (ActionManager::edit_cursor_in_region_sensitive_actions, false);
1474 if (region_edit_menu_split_multichannel_item) {
1475 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1476 // GTK2FIX find the action, change its sensitivity
1477 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1479 // GTK2FIX see above
1480 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1489 case CrossfadeViewItem:
1496 /* probably shouldn't happen but if it does, we don't care */
1500 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1502 /* Bounce to disk */
1504 using namespace Menu_Helpers;
1505 MenuList& edit_items = menu->items();
1507 edit_items.push_back (SeparatorElem());
1509 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1510 case AudioTrack::NoFreeze:
1511 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1514 case AudioTrack::Frozen:
1515 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1518 case AudioTrack::UnFrozen:
1519 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1525 menu->popup (button, time);
1529 Editor::build_track_context_menu (jack_nframes_t ignored)
1531 using namespace Menu_Helpers;
1533 MenuList& edit_items = track_context_menu.items();
1536 add_dstream_context_items (edit_items);
1537 return &track_context_menu;
1541 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1543 using namespace Menu_Helpers;
1545 MenuList& edit_items = track_context_menu.items();
1548 add_bus_context_items (edit_items);
1549 return &track_context_menu;
1553 Editor::build_track_region_context_menu (jack_nframes_t frame)
1555 using namespace Menu_Helpers;
1556 MenuList& edit_items = track_region_context_menu.items();
1559 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1565 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1566 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1567 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1568 add_region_context_items (atv->view, (*i), edit_items);
1574 add_dstream_context_items (edit_items);
1576 return &track_region_context_menu;
1580 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1582 using namespace Menu_Helpers;
1583 MenuList& edit_items = track_crossfade_context_menu.items();
1584 edit_items.clear ();
1586 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1593 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1595 Playlist::RegionList* regions = pl->regions_at (frame);
1596 AudioPlaylist::Crossfades xfades;
1598 apl->crossfades_at (frame, xfades);
1600 bool many = xfades.size() > 1;
1602 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1603 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1606 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1607 add_region_context_items (atv->view, (*i), edit_items);
1614 add_dstream_context_items (edit_items);
1616 return &track_crossfade_context_menu;
1620 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
1622 using namespace Menu_Helpers;
1623 MenuList& edit_items = track_selection_context_menu.items();
1624 edit_items.clear ();
1626 add_selection_context_items (edit_items);
1627 add_dstream_context_items (edit_items);
1629 return &track_selection_context_menu;
1633 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
1635 using namespace Menu_Helpers;
1636 Menu *xfade_menu = manage (new Menu);
1637 MenuList& items = xfade_menu->items();
1638 xfade_menu->set_name ("ArdourContextMenu");
1641 if (xfade->active()) {
1647 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
1648 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
1650 if (xfade->can_follow_overlap()) {
1652 if (xfade->following_overlap()) {
1653 str = _("Convert to short");
1655 str = _("Convert to full");
1658 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1662 str = xfade->out().name();
1664 str += xfade->in().name();
1666 str = _("Crossfade");
1669 edit_items.push_back (MenuElem (str, *xfade_menu));
1670 edit_items.push_back (SeparatorElem());
1674 Editor::xfade_edit_left_region ()
1676 if (clicked_crossfadeview) {
1677 clicked_crossfadeview->left_view.show_region_editor ();
1682 Editor::xfade_edit_right_region ()
1684 if (clicked_crossfadeview) {
1685 clicked_crossfadeview->right_view.show_region_editor ();
1690 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
1692 using namespace Menu_Helpers;
1693 Menu *region_menu = manage (new Menu);
1694 MenuList& items = region_menu->items();
1695 region_menu->set_name ("ArdourContextMenu");
1697 AudioRegion* ar = 0;
1700 ar = dynamic_cast<AudioRegion*> (region);
1703 /* when this particular menu pops up, make the relevant region
1707 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
1709 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1710 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1711 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1712 items.push_back (SeparatorElem());
1713 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
1714 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1715 items.push_back (SeparatorElem());
1717 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
1718 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1719 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1720 items.push_back (SeparatorElem());
1722 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
1723 might be able to figure out which overloaded member function to use in
1727 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
1729 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
1730 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
1731 items.push_back (SeparatorElem());
1733 if (region->muted()) {
1734 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
1736 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
1738 items.push_back (SeparatorElem());
1740 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1741 items.push_back (SeparatorElem());
1746 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
1747 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
1748 items.push_back (SeparatorElem());
1750 if (ar->scale_amplitude() != 1.0f) {
1751 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1753 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1756 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1757 items.push_back (SeparatorElem());
1761 Menu *nudge_menu = manage (new Menu());
1762 MenuList& nudge_items = nudge_menu->items();
1763 nudge_menu->set_name ("ArdourContextMenu");
1765 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
1766 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
1767 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1768 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1770 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1771 items.push_back (SeparatorElem());
1773 Menu *trim_menu = manage (new Menu);
1774 MenuList& trim_items = trim_menu->items();
1775 trim_menu->set_name ("ArdourContextMenu");
1777 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
1778 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
1780 items.push_back (MenuElem (_("Trim"), *trim_menu));
1781 items.push_back (SeparatorElem());
1783 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1784 region_edit_menu_split_item = &items.back();
1786 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1787 region_edit_menu_split_multichannel_item = &items.back();
1789 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1790 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1791 items.push_back (SeparatorElem());
1792 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1793 items.push_back (SeparatorElem());
1794 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
1796 /* OK, stick the region submenu at the top of the list, and then add
1800 /* we have to hack up the region name because "_" has a special
1801 meaning for menu titles.
1804 string::size_type pos = 0;
1805 string menu_item_name = region->name();
1807 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1808 menu_item_name.replace (pos, 1, "__");
1812 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1813 edit_items.push_back (SeparatorElem());
1817 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1819 using namespace Menu_Helpers;
1820 Menu *selection_menu = manage (new Menu);
1821 MenuList& items = selection_menu->items();
1822 selection_menu->set_name ("ArdourContextMenu");
1824 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1825 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
1826 items.push_back (SeparatorElem());
1827 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
1828 items.push_back (SeparatorElem());
1829 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
1830 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
1831 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1832 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1833 items.push_back (SeparatorElem());
1834 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1835 items.push_back (SeparatorElem());
1836 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
1837 items.push_back (SeparatorElem());
1838 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
1840 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
1841 edit_items.push_back (SeparatorElem());
1845 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1847 using namespace Menu_Helpers;
1851 Menu *play_menu = manage (new Menu);
1852 MenuList& play_items = play_menu->items();
1853 play_menu->set_name ("ArdourContextMenu");
1855 play_items.push_back (MenuElem (_("Play from edit cursor")));
1856 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1857 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1858 play_items.push_back (SeparatorElem());
1859 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1861 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1865 Menu *select_menu = manage (new Menu);
1866 MenuList& select_items = select_menu->items();
1867 select_menu->set_name ("ArdourContextMenu");
1869 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1870 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1871 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1872 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1873 select_items.push_back (SeparatorElem());
1874 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1875 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1876 select_items.push_back (SeparatorElem());
1877 select_items.push_back (MenuElem (_("Select all after edit cursor"), bind (mem_fun(*this, &Editor::select_all_after_cursor), edit_cursor, true)));
1878 select_items.push_back (MenuElem (_("Select all before edit cursor"), bind (mem_fun(*this, &Editor::select_all_after_cursor), edit_cursor, false)));
1879 select_items.push_back (MenuElem (_("Select all after playhead"), bind (mem_fun(*this, &Editor::select_all_after_cursor), playhead_cursor, true)));
1880 select_items.push_back (MenuElem (_("Select all before playhead"), bind (mem_fun(*this, &Editor::select_all_after_cursor), playhead_cursor, false)));
1881 select_items.push_back (SeparatorElem());
1883 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1887 Menu *cutnpaste_menu = manage (new Menu);
1888 MenuList& cutnpaste_items = cutnpaste_menu->items();
1889 cutnpaste_menu->set_name ("ArdourContextMenu");
1891 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1892 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1893 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1894 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
1896 cutnpaste_items.push_back (SeparatorElem());
1898 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
1899 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
1901 cutnpaste_items.push_back (SeparatorElem());
1903 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
1905 cutnpaste_items.push_back (SeparatorElem());
1907 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
1908 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
1910 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1912 /* Adding new material */
1914 Menu *import_menu = manage (new Menu());
1915 MenuList& import_items = import_menu->items();
1916 import_menu->set_name ("ArdourContextMenu");
1918 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1919 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
1921 edit_items.push_back (MenuElem (_("Import"), *import_menu));
1925 Menu *nudge_menu = manage (new Menu());
1926 MenuList& nudge_items = nudge_menu->items();
1927 nudge_menu->set_name ("ArdourContextMenu");
1929 edit_items.push_back (SeparatorElem());
1930 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1931 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1932 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1933 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1935 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1939 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1941 using namespace Menu_Helpers;
1945 Menu *play_menu = manage (new Menu);
1946 MenuList& play_items = play_menu->items();
1947 play_menu->set_name ("ArdourContextMenu");
1949 play_items.push_back (MenuElem (_("Play from edit cursor")));
1950 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1951 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1955 Menu *select_menu = manage (new Menu);
1956 MenuList& select_items = select_menu->items();
1957 select_menu->set_name ("ArdourContextMenu");
1959 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1960 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1961 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1962 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1963 select_items.push_back (SeparatorElem());
1964 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1965 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1966 select_items.push_back (SeparatorElem());
1967 select_items.push_back (MenuElem (_("Select all after edit cursor"), bind (mem_fun(*this, &Editor::select_all_after_cursor), edit_cursor, true)));
1968 select_items.push_back (MenuElem (_("Select all before edit cursor"), bind (mem_fun(*this, &Editor::select_all_after_cursor), edit_cursor, false)));
1969 select_items.push_back (MenuElem (_("Select all after playhead"), bind (mem_fun(*this, &Editor::select_all_after_cursor), playhead_cursor, true)));
1970 select_items.push_back (MenuElem (_("Select all before playhead"), bind (mem_fun(*this, &Editor::select_all_after_cursor), playhead_cursor, false)));
1971 select_items.push_back (SeparatorElem());
1973 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1977 Menu *cutnpaste_menu = manage (new Menu);
1978 MenuList& cutnpaste_items = cutnpaste_menu->items();
1979 cutnpaste_menu->set_name ("ArdourContextMenu");
1981 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1982 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1983 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1985 Menu *nudge_menu = manage (new Menu());
1986 MenuList& nudge_items = nudge_menu->items();
1987 nudge_menu->set_name ("ArdourContextMenu");
1989 edit_items.push_back (SeparatorElem());
1990 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1991 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1992 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1993 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1995 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1998 /* CURSOR SETTING AND MARKS AND STUFF */
2001 Editor::set_snap_to (SnapType st)
2004 vector<string> txt = internationalize (snap_type_strings);
2005 snap_type_selector.set_active_text (txt[(int)st]);
2009 switch (snap_type) {
2010 case SnapToAThirtysecondBeat:
2011 case SnapToASixteenthBeat:
2012 case SnapToAEighthBeat:
2013 case SnapToAQuarterBeat:
2014 case SnapToAThirdBeat:
2015 update_tempo_based_rulers ();
2023 Editor::set_snap_mode (SnapMode mode)
2026 vector<string> txt = internationalize (snap_mode_strings);
2027 snap_mode_selector.set_active_text (txt[(int)mode]);
2033 Editor::add_location_from_selection ()
2035 if (selection->time.empty()) {
2039 if (session == 0 || clicked_trackview == 0) {
2043 jack_nframes_t start = selection->time[clicked_selection].start;
2044 jack_nframes_t end = selection->time[clicked_selection].end;
2046 Location *location = new Location (start, end, "selection");
2048 session->begin_reversible_command (_("add marker"));
2049 session->add_undo (session->locations()->get_memento());
2050 session->locations()->add (location, true);
2051 session->add_redo_no_execute (session->locations()->get_memento());
2052 session->commit_reversible_command ();
2056 Editor::add_location_from_playhead_cursor ()
2058 jack_nframes_t where = session->audible_frame();
2060 Location *location = new Location (where, where, "mark", Location::IsMark);
2061 session->begin_reversible_command (_("add marker"));
2062 session->add_undo (session->locations()->get_memento());
2063 session->locations()->add (location, true);
2064 session->add_redo_no_execute (session->locations()->get_memento());
2065 session->commit_reversible_command ();
2070 Editor::set_state (const XMLNode& node)
2072 const XMLProperty* prop;
2074 int x, y, xoff, yoff;
2077 if ((geometry = find_named_node (node, "geometry")) == 0) {
2079 g.base_width = default_width;
2080 g.base_height = default_height;
2088 g.base_width = atoi(geometry->property("x_size")->value());
2089 g.base_height = atoi(geometry->property("y_size")->value());
2090 x = atoi(geometry->property("x_pos")->value());
2091 y = atoi(geometry->property("y_pos")->value());
2092 xoff = atoi(geometry->property("x_off")->value());
2093 yoff = atoi(geometry->property("y_off")->value());
2096 set_geometry_hints (vpacker, g, Gdk::HINT_BASE_SIZE);
2097 set_default_size (g.base_width, g.base_height);
2100 if ((prop = node.property ("zoom-focus"))) {
2101 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2104 if ((prop = node.property ("zoom"))) {
2105 set_frames_per_unit (atof (prop->value()));
2108 if ((prop = node.property ("snap-to"))) {
2109 set_snap_to ((SnapType) atoi (prop->value()));
2112 if ((prop = node.property ("snap-mode"))) {
2113 set_snap_mode ((SnapMode) atoi (prop->value()));
2116 if ((prop = node.property ("show-waveforms"))) {
2117 bool yn = (prop->value() == "yes");
2118 _show_waveforms = !yn;
2119 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformVisibility"));
2121 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2122 /* do it twice to force the change */
2123 tact->set_active (!yn);
2124 tact->set_active (yn);
2128 if ((prop = node.property ("show-waveforms-recording"))) {
2129 bool yn = (prop->value() == "yes");
2130 _show_waveforms_recording = !yn;
2131 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleWaveformsWhileRecording"));
2133 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2134 /* do it twice to force the change */
2135 tact->set_active (!yn);
2136 tact->set_active (yn);
2140 if ((prop = node.property ("show-measures"))) {
2141 bool yn = (prop->value() == "yes");
2142 _show_measures = !yn;
2143 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleMeasureVisibility"));
2145 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2146 /* do it twice to force the change */
2147 tact->set_active (!yn);
2148 tact->set_active (yn);
2152 if ((prop = node.property ("follow-playhead"))) {
2153 bool yn = (prop->value() == "yes");
2154 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleFollowPlayhead"));
2156 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
2157 /* do it twice to force the change */
2158 tact->set_active (!yn);
2159 tact->set_active (yn);
2163 if ((prop = node.property ("xfades-visible"))) {
2164 bool yn = (prop->value() == "yes");
2165 _xfade_visibility = !yn;
2166 set_xfade_visibility (yn);
2169 if ((prop = node.property ("region-list-sort-type"))) {
2170 region_list_sort_type = (Editing::RegionListSortType) -1; // force change
2171 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2174 if ((prop = node.property ("mouse-mode"))) {
2175 MouseMode m = str2mousemode(prop->value());
2176 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2177 set_mouse_mode (m, true);
2179 mouse_mode = MouseGain; /* lie, to force the mode switch */
2180 set_mouse_mode (MouseObject, true);
2183 if ((prop = node.property ("show-editor-mixer"))) {
2185 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2187 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2188 bool yn = (prop->value() == X_("yes"));
2190 /* do it twice to force the change */
2192 tact->set_active (!yn);
2193 tact->set_active (yn);
2201 Editor::get_state ()
2203 XMLNode* node = new XMLNode ("Editor");
2206 if (is_realized()) {
2207 Glib::RefPtr<Gdk::Window> win = get_window();
2209 int x, y, xoff, yoff, width, height;
2210 win->get_root_origin(x, y);
2211 win->get_position(xoff, yoff);
2212 win->get_size(width, height);
2214 XMLNode* geometry = new XMLNode ("geometry");
2216 snprintf(buf, sizeof(buf), "%d", width);
2217 geometry->add_property("x_size", string(buf));
2218 snprintf(buf, sizeof(buf), "%d", height);
2219 geometry->add_property("y_size", string(buf));
2220 snprintf(buf, sizeof(buf), "%d", x);
2221 geometry->add_property("x_pos", string(buf));
2222 snprintf(buf, sizeof(buf), "%d", y);
2223 geometry->add_property("y_pos", string(buf));
2224 snprintf(buf, sizeof(buf), "%d", xoff);
2225 geometry->add_property("x_off", string(buf));
2226 snprintf(buf, sizeof(buf), "%d", yoff);
2227 geometry->add_property("y_off", string(buf));
2228 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2229 geometry->add_property("edit_pane_pos", string(buf));
2231 node->add_child_nocopy (*geometry);
2234 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2235 node->add_property ("zoom-focus", buf);
2236 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2237 node->add_property ("zoom", buf);
2238 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2239 node->add_property ("snap-to", buf);
2240 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2241 node->add_property ("snap-mode", buf);
2243 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2244 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2245 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2246 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2247 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2248 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2249 node->add_property ("mouse-mode", enum2str(mouse_mode));
2251 Glib::RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("show-editor-mixer"));
2253 Glib::RefPtr<ToggleAction> tact = Glib::RefPtr<ToggleAction>::cast_dynamic(act);
2254 node->add_property (X_("show-editor-mixer"), tact->get_active() ? "yes" : "no");
2256 cerr << "no show editor mixer action\n";
2265 Editor::trackview_by_y_position (double y)
2267 TrackViewList::iterator iter;
2270 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2278 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2287 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2289 Location* before = 0;
2290 Location* after = 0;
2296 const jack_nframes_t one_second = session->frame_rate();
2297 const jack_nframes_t one_minute = session->frame_rate() * 60;
2299 jack_nframes_t presnap = start;
2301 switch (snap_type) {
2307 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2309 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2312 case SnapToSMPTEFrame:
2314 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2316 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2320 case SnapToSMPTESeconds:
2321 if (session->smpte_offset_negative())
2323 start += session->smpte_offset ();
2325 start -= session->smpte_offset ();
2327 if (direction > 0) {
2328 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2330 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2333 if (session->smpte_offset_negative())
2335 start -= session->smpte_offset ();
2337 start += session->smpte_offset ();
2341 case SnapToSMPTEMinutes:
2342 if (session->smpte_offset_negative())
2344 start += session->smpte_offset ();
2346 start -= session->smpte_offset ();
2349 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2351 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2353 if (session->smpte_offset_negative())
2355 start -= session->smpte_offset ();
2357 start += session->smpte_offset ();
2363 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2365 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2371 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2373 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2378 start = session->tempo_map().round_to_bar (start, direction);
2382 start = session->tempo_map().round_to_beat (start, direction);
2385 case SnapToAThirtysecondBeat:
2386 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2389 case SnapToASixteenthBeat:
2390 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2393 case SnapToAEighthBeat:
2394 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2397 case SnapToAQuarterBeat:
2398 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2401 case SnapToAThirdBeat:
2402 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2405 case SnapToEditCursor:
2406 start = edit_cursor->current_frame;
2414 before = session->locations()->first_location_before (start);
2415 after = session->locations()->first_location_after (start);
2417 if (direction < 0) {
2419 start = before->start();
2423 } else if (direction > 0) {
2425 start = after->start();
2427 start = session->current_end_frame();
2432 /* find nearest of the two */
2433 if ((start - before->start()) < (after->start() - start)) {
2434 start = before->start();
2436 start = after->start();
2439 start = before->start();
2442 start = after->start();
2449 case SnapToRegionStart:
2450 case SnapToRegionEnd:
2451 case SnapToRegionSync:
2452 case SnapToRegionBoundary:
2453 if (!region_boundary_cache.empty()) {
2454 vector<jack_nframes_t>::iterator i;
2456 if (direction > 0) {
2457 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2459 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2462 if (i != region_boundary_cache.end()) {
2465 start = region_boundary_cache.back();
2471 switch (snap_mode) {
2477 if (presnap > start) {
2478 if (presnap > (start + unit_to_frame(snap_threshold))) {
2482 } else if (presnap < start) {
2483 if (presnap < (start - unit_to_frame(snap_threshold))) {
2495 Editor::setup_toolbar ()
2498 vector<ToggleButton *> mouse_mode_buttons;
2500 mouse_mode_buttons.push_back (&mouse_move_button);
2501 mouse_mode_buttons.push_back (&mouse_select_button);
2502 mouse_mode_buttons.push_back (&mouse_gain_button);
2503 mouse_mode_buttons.push_back (&mouse_zoom_button);
2504 mouse_mode_buttons.push_back (&mouse_timefx_button);
2505 mouse_mode_buttons.push_back (&mouse_audition_button);
2506 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2508 mouse_mode_button_table.set_homogeneous (true);
2509 mouse_mode_button_table.set_col_spacings (2);
2510 mouse_mode_button_table.set_row_spacings (2);
2511 mouse_mode_button_table.set_border_width (5);
2513 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2514 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2515 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2517 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2518 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2519 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2521 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2522 mouse_mode_tearoff->set_name ("MouseModeBase");
2524 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2525 &mouse_mode_tearoff->tearoff_window()));
2526 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2527 &mouse_mode_tearoff->tearoff_window(), 1));
2528 mouse_mode_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2529 &mouse_mode_tearoff->tearoff_window()));
2530 mouse_mode_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2531 &mouse_mode_tearoff->tearoff_window(), 1));
2533 mouse_move_button.set_name ("MouseModeButton");
2534 mouse_select_button.set_name ("MouseModeButton");
2535 mouse_gain_button.set_name ("MouseModeButton");
2536 mouse_zoom_button.set_name ("MouseModeButton");
2537 mouse_timefx_button.set_name ("MouseModeButton");
2538 mouse_audition_button.set_name ("MouseModeButton");
2540 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2541 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2542 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2543 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2544 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2545 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2547 mouse_move_button.unset_flags (CAN_FOCUS);
2548 mouse_select_button.unset_flags (CAN_FOCUS);
2549 mouse_gain_button.unset_flags (CAN_FOCUS);
2550 mouse_zoom_button.unset_flags (CAN_FOCUS);
2551 mouse_timefx_button.unset_flags (CAN_FOCUS);
2552 mouse_audition_button.unset_flags (CAN_FOCUS);
2554 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2555 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2557 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2558 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2559 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2560 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2561 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2563 // mouse_move_button.set_active (true);
2565 /* automation control */
2567 global_automation_button.set_name ("MouseModeButton");
2568 automation_mode_button.set_name ("MouseModeButton");
2570 automation_box.set_spacing (2);
2571 automation_box.set_border_width (2);
2572 automation_box.pack_start (global_automation_button, false, false);
2573 automation_box.pack_start (automation_mode_button, false, false);
2577 edit_mode_label.set_name ("ToolBarLabel");
2579 edit_mode_selector.set_name ("EditModeSelector");
2581 edit_mode_box.set_spacing (3);
2582 edit_mode_box.set_border_width (3);
2584 /* XXX another disgusting hack because of the way combo boxes size themselves */
2586 const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
2587 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2+FUDGE, 10);
2588 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2589 edit_mode_box.pack_start (edit_mode_label, false, false);
2590 edit_mode_box.pack_start (edit_mode_selector, false, false);
2592 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2596 snap_type_label.set_name ("ToolBarLabel");
2598 snap_type_selector.set_name ("SnapTypeSelector");
2600 snap_type_box.set_spacing (3);
2601 snap_type_box.set_border_width (3);
2603 /* XXX another disgusting hack because of the way combo boxes size themselves */
2605 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
2606 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2608 snap_type_box.pack_start (snap_type_label, false, false);
2609 snap_type_box.pack_start (snap_type_selector, false, false);
2611 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2613 /* Snap mode, not snap type */
2615 snap_mode_label.set_name ("ToolBarLabel");
2617 snap_mode_selector.set_name ("SnapModeSelector");
2619 snap_mode_box.set_spacing (3);
2620 snap_mode_box.set_border_width (3);
2622 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2+FUDGE, 10);
2623 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2625 snap_mode_box.pack_start (snap_mode_label, false, false);
2626 snap_mode_box.pack_start (snap_mode_selector, false, false);
2628 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2630 /* Zoom focus mode */
2632 zoom_focus_label.set_name ("ToolBarLabel");
2634 zoom_focus_selector.set_name ("ZoomFocusSelector");
2636 zoom_focus_box.set_spacing (3);
2637 zoom_focus_box.set_border_width (3);
2639 /* XXX another disgusting hack because of the way combo boxes size themselves */
2641 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2+FUDGE, 10);
2642 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2644 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2645 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2647 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2649 /* selection/cursor clocks */
2651 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2652 selection_start_clock_label.set_name ("ToolBarLabel");
2653 selection_end_clock_label.set_name ("ToolBarLabel");
2654 edit_cursor_clock_label.set_name ("ToolBarLabel");
2656 selection_start_clock_label.set_text (_("Start:"));
2657 selection_end_clock_label.set_text (_("End:"));
2658 edit_cursor_clock_label.set_text (_("Edit"));
2660 /* the zoom in/out buttons are generally taller than the clocks, so
2661 put all the toolbar clocks into a size group with one of the
2662 buttons to make them all equal height.
2664 this also applies to the various toolbar combos
2667 RefPtr<SizeGroup> toolbar_clock_size_group = SizeGroup::create (SIZE_GROUP_VERTICAL);
2668 toolbar_clock_size_group->add_widget (zoom_out_button);
2669 toolbar_clock_size_group->add_widget (edit_cursor_clock);
2670 toolbar_clock_size_group->add_widget (zoom_range_clock);
2671 toolbar_clock_size_group->add_widget (nudge_clock);
2672 toolbar_clock_size_group->add_widget (edit_mode_selector);
2673 toolbar_clock_size_group->add_widget (snap_type_selector);
2674 toolbar_clock_size_group->add_widget (snap_mode_selector);
2675 toolbar_clock_size_group->add_widget (zoom_focus_selector);
2677 HBox* edit_clock_hbox = manage (new HBox());
2678 VBox* edit_clock_vbox = manage (new VBox());
2680 edit_clock_hbox->pack_start (edit_cursor_clock, false, false);
2682 edit_clock_vbox->set_spacing (3);
2683 edit_clock_vbox->set_border_width (3);
2684 edit_clock_vbox->pack_start (edit_cursor_clock_label, false, false);
2685 edit_clock_vbox->pack_start (*edit_clock_hbox, false, false);
2687 HBox* hbox = new HBox;
2689 hbox->pack_start (*edit_clock_vbox, false, false);
2690 hbox->pack_start (zoom_indicator_vbox, false, false);
2691 hbox->pack_start (zoom_focus_box, false, false);
2692 hbox->pack_start (snap_type_box, false, false);
2693 hbox->pack_start (snap_mode_box, false, false);
2694 hbox->pack_start (edit_mode_box, false, false);
2696 VBox *vbox = manage (new VBox);
2698 vbox->set_spacing (3);
2699 vbox->set_border_width (3);
2701 HBox *nbox = manage (new HBox);
2703 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
2704 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
2706 nbox->pack_start (nudge_backward_button, false, false);
2707 nbox->pack_start (nudge_forward_button, false, false);
2708 nbox->pack_start (nudge_clock, false, false, 5);
2710 nudge_label.set_name ("ToolBarLabel");
2712 vbox->pack_start (nudge_label, false, false);
2713 vbox->pack_start (*nbox, false, false);
2715 hbox->pack_start (*vbox, false, false);
2719 tools_tearoff = new TearOff (*hbox);
2720 tools_tearoff->set_name ("MouseModeBase");
2722 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2723 &tools_tearoff->tearoff_window()));
2724 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2725 &tools_tearoff->tearoff_window(), 0));
2726 tools_tearoff->Hidden.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Box*>(&toolbar_hbox),
2727 &tools_tearoff->tearoff_window()));
2728 tools_tearoff->Visible.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Box*> (&toolbar_hbox),
2729 &tools_tearoff->tearoff_window(), 0));
2731 toolbar_hbox.set_spacing (8);
2732 toolbar_hbox.set_border_width (2);
2734 toolbar_hbox.pack_start (*tools_tearoff, false, false);
2735 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2737 toolbar_base.set_name ("ToolBarBase");
2738 toolbar_base.add (toolbar_hbox);
2740 toolbar_frame.set_shadow_type (SHADOW_OUT);
2741 toolbar_frame.set_name ("BaseFrame");
2742 toolbar_frame.add (toolbar_base);
2746 Editor::_autoscroll_canvas (void *arg)
2748 return ((Editor *) arg)->autoscroll_canvas ();
2752 Editor::autoscroll_canvas ()
2754 jack_nframes_t new_frame;
2755 bool keep_calling = true;
2757 if (autoscroll_direction < 0) {
2758 if (leftmost_frame < autoscroll_distance) {
2761 new_frame = leftmost_frame - autoscroll_distance;
2764 if (leftmost_frame > max_frames - autoscroll_distance) {
2765 new_frame = max_frames;
2767 new_frame = leftmost_frame + autoscroll_distance;
2771 if (new_frame != leftmost_frame) {
2772 reposition_x_origin (new_frame);
2775 if (new_frame == 0 || new_frame == max_frames) {
2782 if (autoscroll_cnt == 1) {
2784 /* connect the timeout so that we get called repeatedly */
2786 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
2787 keep_calling = false;
2789 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
2791 /* after about a while, speed up a bit by changing the timeout interval */
2793 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
2794 keep_calling = false;
2796 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
2798 /* after about another while, speed up some more */
2800 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
2801 keep_calling = false;
2803 } else if (autoscroll_cnt >= 30) {
2805 /* we've been scrolling for a while ... crank it up */
2807 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
2810 return keep_calling;
2814 Editor::start_canvas_autoscroll (int dir)
2820 stop_canvas_autoscroll ();
2822 autoscroll_direction = dir;
2823 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
2826 /* do it right now, which will start the repeated callbacks */
2828 autoscroll_canvas ();
2832 Editor::stop_canvas_autoscroll ()
2834 if (autoscroll_timeout_tag >= 0) {
2835 gtk_timeout_remove (autoscroll_timeout_tag);
2836 autoscroll_timeout_tag = -1;
2841 Editor::convert_drop_to_paths (vector<string>& paths,
2842 const RefPtr<Gdk::DragContext>& context,
2845 const SelectionData& data,
2854 vector<ustring> uris = data.get_uris();
2858 /* This is seriously fucked up. Nautilus doesn't say that its URI lists
2859 are actually URI lists. So do it by hand.
2862 if (data.get_target() != "text/plain") {
2866 /* Parse the "uri-list" format that Nautilus provides,
2867 where each pathname is delimited by \r\n
2870 const char* p = data.get_text().c_str();
2877 while (g_ascii_isspace (*p))
2881 while (*q && (*q != '\n') && (*q != '\r'))
2887 while (q > p && g_ascii_isspace (*q))
2892 uris.push_back (ustring (p, q - p + 1));
2896 p = strchr (p, '\n');
2906 for (vector<ustring>::iterator i = uris.begin(); i != uris.end(); ++i) {
2907 if ((*i).substr (0,7) == "file://") {
2910 paths.push_back (p.substr (7));
2918 Editor::new_tempo_section ()
2924 Editor::map_transport_state ()
2926 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
2928 if (session->transport_stopped()) {
2929 have_pending_keyboard_selection = false;
2935 Editor::State::State ()
2937 selection = new Selection;
2940 Editor::State::~State ()
2946 Editor::get_memento () const
2948 State *state = new State;
2950 store_state (*state);
2951 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
2955 Editor::store_state (State& state) const
2957 *state.selection = *selection;
2961 Editor::restore_state (State *state)
2963 if (*selection == *state->selection) {
2967 *selection = *state->selection;
2968 time_selection_changed ();
2969 region_selection_changed ();
2971 /* XXX other selection change handlers? */
2975 Editor::begin_reversible_command (string name)
2978 UndoAction ua = get_memento();
2979 session->begin_reversible_command (name, &ua);
2984 Editor::commit_reversible_command ()
2987 UndoAction ua = get_memento();
2988 session->commit_reversible_command (&ua);
2993 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
2995 if (!clicked_trackview) {
3000 begin_reversible_command (_("set selected trackview"));
3005 if (selection->selected (clicked_trackview)) {
3007 selection->remove (clicked_trackview);
3010 selection->add (clicked_trackview);
3015 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3016 /* no commit necessary */
3020 selection->set (clicked_trackview);
3024 commit_reversible_command ();
3029 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3031 if (!clicked_control_point) {
3036 begin_reversible_command (_("set selected control point"));
3046 commit_reversible_command ();
3051 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3053 if (!clicked_regionview) {
3057 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3063 RouteGroup* group = atv->route().edit_group();
3064 vector<AudioRegionView*> all_equivalent_regions;
3066 if (group && group->is_active()) {
3068 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3070 AudioTimeAxisView* tatv;
3072 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3074 if (tatv->route().edit_group() != group) {
3079 vector<AudioRegion*> results;
3080 AudioRegionView* marv;
3083 if ((ds = tatv->get_diskstream()) == 0) {
3088 if ((pl = ds->playlist()) != 0) {
3089 pl->get_equivalent_regions (clicked_regionview->region,
3093 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3094 if ((marv = tatv->view->find_view (**ir)) != 0) {
3095 all_equivalent_regions.push_back (marv);
3104 all_equivalent_regions.push_back (clicked_regionview);
3108 begin_reversible_command (_("set selected regionview"));
3112 if (clicked_regionview->get_selected()) {
3113 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3114 /* reduce selection down to just the one clicked */
3115 selection->set (clicked_regionview);
3117 selection->remove (clicked_regionview);
3120 selection->add (all_equivalent_regions);
3123 set_selected_track_from_click (add, false, no_track_remove);
3127 // karsten wiese suggested these two lines to make
3128 // a selected region rise to the top. but this
3129 // leads to a mismatch between actual layering
3130 // and visual layering. resolution required ....
3132 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3133 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3135 if (clicked_regionview->get_selected()) {
3136 /* no commit necessary: we are the one selected. */
3141 selection->set (all_equivalent_regions);
3142 set_selected_track_from_click (add, false, false);
3146 commit_reversible_command () ;
3150 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3152 vector<AudioRegionView*> all_equivalent_regions;
3153 AudioRegion* region;
3155 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3159 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3161 AudioTimeAxisView* tatv;
3163 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3166 vector<AudioRegion*> results;
3167 AudioRegionView* marv;
3170 if ((ds = tatv->get_diskstream()) == 0) {
3175 if ((pl = ds->playlist()) != 0) {
3176 pl->get_region_list_equivalent_regions (*region, results);
3179 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3180 if ((marv = tatv->view->find_view (**ir)) != 0) {
3181 all_equivalent_regions.push_back (marv);
3188 begin_reversible_command (_("set selected regions"));
3192 selection->add (all_equivalent_regions);
3196 selection->set (all_equivalent_regions);
3199 commit_reversible_command () ;
3203 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3205 AudioRegionView* rv;
3208 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3212 if ((rv = sv->find_view (*ar)) == 0) {
3216 /* don't reset the selection if its something other than
3217 a single other region.
3220 if (selection->audio_regions.size() > 1) {
3224 begin_reversible_command (_("set selected regions"));
3226 selection->set (rv);
3228 commit_reversible_command () ;
3234 Editor::set_edit_group_solo (Route& route, bool yn)
3236 RouteGroup *edit_group;
3238 if ((edit_group = route.edit_group()) != 0) {
3239 edit_group->apply (&Route::set_solo, yn, this);
3241 route.set_solo (yn, this);
3246 Editor::set_edit_group_mute (Route& route, bool yn)
3248 RouteGroup *edit_group = 0;
3250 if ((edit_group == route.edit_group()) != 0) {
3251 edit_group->apply (&Route::set_mute, yn, this);
3253 route.set_mute (yn, this);
3258 Editor::set_edit_menu (Menu& menu)
3261 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3265 Editor::edit_menu_map_handler (GdkEventAny* ev)
3267 using namespace Menu_Helpers;
3268 MenuList& edit_items = edit_menu->items();
3271 /* Nuke all the old items */
3273 edit_items.clear ();
3279 if (session->undo_depth() == 0) {
3282 label = string_compose(_("Undo (%1)"), session->next_undo());
3285 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3287 if (session->undo_depth() == 0) {
3288 edit_items.back().set_sensitive (false);
3291 if (session->redo_depth() == 0) {
3294 label = string_compose(_("Redo (%1)"), session->next_redo());
3297 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3298 if (session->redo_depth() == 0) {
3299 edit_items.back().set_sensitive (false);
3302 vector<MenuItem*> mitems;
3304 edit_items.push_back (SeparatorElem());
3305 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3306 mitems.push_back (&edit_items.back());
3307 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3308 mitems.push_back (&edit_items.back());
3309 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3310 mitems.push_back (&edit_items.back());
3311 edit_items.push_back (SeparatorElem());
3312 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3313 mitems.push_back (&edit_items.back());
3314 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3315 mitems.push_back (&edit_items.back());
3316 edit_items.push_back (SeparatorElem());
3318 if (selection->empty()) {
3319 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3320 (*i)->set_sensitive (false);
3324 Menu* import_menu = manage (new Menu());
3325 import_menu->set_name ("ArdourContextMenu");
3326 MenuList& import_items = import_menu->items();
3328 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3329 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3331 Menu* embed_menu = manage (new Menu());
3332 embed_menu->set_name ("ArdourContextMenu");
3333 MenuList& embed_items = embed_menu->items();
3335 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3336 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3338 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3339 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3340 edit_items.push_back (SeparatorElem());
3342 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3343 if (!session->have_captured()) {
3344 edit_items.back().set_sensitive (false);
3351 Editor::duplicate_dialog (bool dup_region)
3354 if (clicked_regionview == 0) {
3358 if (selection->time.length() == 0) {
3363 ArdourDialog win ("duplicate dialog");
3365 Label label (_("Duplicate how many times?"));
3367 win.get_vbox()->pack_start (label);
3368 win.add_action_widget (entry, RESPONSE_ACCEPT);
3369 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3370 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3372 win.set_position (WIN_POS_MOUSE);
3374 entry.set_text ("1");
3375 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3376 entry.select_region (0, entry.get_text_length());
3377 entry.grab_focus ();
3380 switch (win.run ()) {
3381 case RESPONSE_ACCEPT:
3387 string text = entry.get_text();
3390 if (sscanf (text.c_str(), "%f", ×) == 1) {
3392 AudioRegionSelection regions;
3393 regions.add (clicked_regionview);
3394 duplicate_some_regions (regions, times);
3396 duplicate_selection (times);
3402 Editor::show_verbose_canvas_cursor ()
3404 verbose_canvas_cursor->raise_to_top();
3405 verbose_canvas_cursor->show();
3406 verbose_cursor_visible = true;
3410 Editor::hide_verbose_canvas_cursor ()
3412 verbose_canvas_cursor->hide();
3413 verbose_cursor_visible = false;
3417 Editor::set_verbose_canvas_cursor (const string & txt, double x, double y)
3419 /* XXX get origin of canvas relative to root window,
3420 add x and y and check compared to gdk_screen_{width,height}
3422 verbose_canvas_cursor->property_text() = txt.c_str();
3423 verbose_canvas_cursor->property_x() = x;
3424 verbose_canvas_cursor->property_y() = y;
3428 Editor::set_verbose_canvas_cursor_text (const string & txt)
3430 verbose_canvas_cursor->property_text() = txt.c_str();
3434 Editor::edit_mode_selection_done ()
3440 string choice = edit_mode_selector.get_active_text();
3441 EditMode mode = Slide;
3443 if (choice == _("Splice")) {
3445 } else if (choice == _("Slide")) {
3449 session->set_edit_mode (mode);
3453 Editor::snap_type_selection_done ()
3459 string choice = snap_type_selector.get_active_text();
3460 SnapType snaptype = SnapToFrame;
3462 if (choice == _("Beats/3")) {
3463 snaptype = SnapToAThirdBeat;
3464 } else if (choice == _("Beats/4")) {
3465 snaptype = SnapToAQuarterBeat;
3466 } else if (choice == _("Beats/8")) {
3467 snaptype = SnapToAEighthBeat;
3468 } else if (choice == _("Beats/16")) {
3469 snaptype = SnapToASixteenthBeat;
3470 } else if (choice == _("Beats/32")) {
3471 snaptype = SnapToAThirtysecondBeat;
3472 } else if (choice == _("Beats")) {
3473 snaptype = SnapToBeat;
3474 } else if (choice == _("Bars")) {
3475 snaptype = SnapToBar;
3476 } else if (choice == _("Marks")) {
3477 snaptype = SnapToMark;
3478 } else if (choice == _("Edit Cursor")) {
3479 snaptype = SnapToEditCursor;
3480 } else if (choice == _("Region starts")) {
3481 snaptype = SnapToRegionStart;
3482 } else if (choice == _("Region ends")) {
3483 snaptype = SnapToRegionEnd;
3484 } else if (choice == _("Region bounds")) {
3485 snaptype = SnapToRegionBoundary;
3486 } else if (choice == _("Region syncs")) {
3487 snaptype = SnapToRegionSync;
3488 } else if (choice == _("CD Frames")) {
3489 snaptype = SnapToCDFrame;
3490 } else if (choice == _("SMPTE Frames")) {
3491 snaptype = SnapToSMPTEFrame;
3492 } else if (choice == _("SMPTE Seconds")) {
3493 snaptype = SnapToSMPTESeconds;
3494 } else if (choice == _("SMPTE Minutes")) {
3495 snaptype = SnapToSMPTEMinutes;
3496 } else if (choice == _("Seconds")) {
3497 snaptype = SnapToSeconds;
3498 } else if (choice == _("Minutes")) {
3499 snaptype = SnapToMinutes;
3500 } else if (choice == _("None")) {
3501 snaptype = SnapToFrame;
3504 set_snap_to (snaptype);
3508 Editor::snap_mode_selection_done ()
3514 string choice = snap_mode_selector.get_active_text();
3515 SnapMode mode = SnapNormal;
3517 if (choice == _("Normal")) {
3519 } else if (choice == _("Magnetic")) {
3520 mode = SnapMagnetic;
3523 set_snap_mode (mode);
3527 Editor::zoom_focus_selection_done ()
3533 string choice = zoom_focus_selector.get_active_text();
3534 ZoomFocus focus_type = ZoomFocusLeft;
3536 if (choice == _("Left")) {
3537 focus_type = ZoomFocusLeft;
3538 } else if (choice == _("Right")) {
3539 focus_type = ZoomFocusRight;
3540 } else if (choice == _("Center")) {
3541 focus_type = ZoomFocusCenter;
3542 } else if (choice == _("Playhead")) {
3543 focus_type = ZoomFocusPlayhead;
3544 } else if (choice == _("Edit Cursor")) {
3545 focus_type = ZoomFocusEdit;
3548 set_zoom_focus (focus_type);
3552 Editor::edit_controls_button_release (GdkEventButton* ev)
3554 if (Keyboard::is_context_menu_event (ev)) {
3555 ARDOUR_UI::instance()->add_route ();
3561 Editor::track_selection_changed ()
3563 switch (selection->tracks.size()){
3567 set_selected_mixer_strip (*(selection->tracks.front()));
3571 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3572 (*i)->set_selected (false);
3573 if (mouse_mode == MouseRange) {
3574 (*i)->hide_selection ();
3578 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3579 (*i)->set_selected (true);
3580 if (mouse_mode == MouseRange) {
3581 (*i)->show_selection (selection->time);
3587 Editor::time_selection_changed ()
3589 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3590 (*i)->hide_selection ();
3593 if (selection->tracks.empty()) {
3594 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3595 (*i)->show_selection (selection->time);
3598 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3599 (*i)->show_selection (selection->time);
3605 Editor::region_selection_changed ()
3607 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3608 (*i)->set_selected_regionviews (selection->audio_regions);
3613 Editor::point_selection_changed ()
3615 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3616 (*i)->set_selected_points (selection->points);
3621 Editor::mouse_select_button_release (GdkEventButton* ev)
3623 /* this handles just right-clicks */
3625 if (ev->button != 3) {
3632 Editor::TrackViewList *
3633 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3636 TrackViewList::iterator i;
3638 v = new TrackViewList;
3640 if (track == 0 && group == 0) {
3644 for (i = track_views.begin(); i != track_views.end (); ++i) {
3648 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3650 /* just the view for this track
3653 v->push_back (track);
3657 /* views for all tracks in the edit group */
3659 for (i = track_views.begin(); i != track_views.end (); ++i) {
3661 if (group == 0 || (*i)->edit_group() == group) {
3671 Editor::set_zoom_focus (ZoomFocus f)
3673 if (zoom_focus != f) {
3675 vector<string> txt = internationalize (zoom_focus_strings);
3676 zoom_focus_selector.set_active_text (txt[(int)f]);
3677 ZoomFocusChanged (); /* EMIT_SIGNAL */
3684 Editor::ensure_float (Window& win)
3686 win.set_transient_for (*this);
3690 Editor::pane_allocation_handler (Allocation &alloc, Paned* which)
3692 /* recover or initialize pane positions. do this here rather than earlier because
3693 we don't want the positions to change the child allocations, which they seem to do.
3699 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3701 static int32_t done;
3704 if ((geometry = find_named_node (*node, "geometry")) == 0) {
3705 width = default_width;
3706 height = default_height;
3708 width = atoi(geometry->property("x_size")->value());
3709 height = atoi(geometry->property("y_size")->value());
3712 if (which == static_cast<Paned*> (&edit_pane)) {
3718 if (!geometry || (prop = geometry->property ("edit_pane_pos")) == 0) {
3719 /* initial allocation is 90% to canvas, 10% to notebook */
3720 pos = (int) floor (alloc.get_width() * 0.90f);
3721 snprintf (buf, sizeof(buf), "%d", pos);
3723 pos = atoi (prop->value());
3726 if ((done = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
3727 edit_pane.set_position (pos);
3728 pre_maximal_pane_position = pos;
3734 Editor::detach_tearoff (Box* b, Window* w)
3736 if (tools_tearoff->torn_off() &&
3737 mouse_mode_tearoff->torn_off()) {
3738 top_hbox.remove (toolbar_frame);
3743 Editor::reattach_tearoff (Box* b, Window* w, int32_t n)
3745 if (toolbar_frame.get_parent() == 0) {
3746 top_hbox.pack_end (toolbar_frame);
3751 Editor::set_show_measures (bool yn)
3753 if (_show_measures != yn) {
3756 if ((_show_measures = yn) == true) {
3759 DisplayControlChanged (ShowMeasures);
3765 Editor::toggle_follow_playhead ()
3767 RefPtr<Action> act = ActionManager::get_action (X_("Editor"), X_("ToggleFollowPlayhead"));
3769 RefPtr<ToggleAction> tact = RefPtr<ToggleAction>::cast_dynamic(act);
3770 set_follow_playhead (tact->get_active());
3775 Editor::set_follow_playhead (bool yn)
3777 if (_follow_playhead != yn) {
3778 if ((_follow_playhead = yn) == true) {
3780 update_current_screen ();
3782 DisplayControlChanged (FollowPlayhead);
3788 Editor::toggle_xfade_active (Crossfade* xfade)
3790 xfade->set_active (!xfade->active());
3794 Editor::toggle_xfade_length (Crossfade* xfade)
3796 xfade->set_follow_overlap (!xfade->following_overlap());
3800 Editor::edit_xfade (Crossfade* xfade)
3802 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
3806 switch (cew.run ()) {
3807 case RESPONSE_ACCEPT:
3814 xfade->StateChanged (Change (~0));
3818 Editor::playlist_selector () const
3820 return *_playlist_selector;
3824 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
3828 ret = nudge_clock.current_duration (pos);
3829 next = ret + 1; /* XXXX fix me */
3835 Editor::end_location_changed (Location* location)
3837 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
3838 horizontal_adjustment.set_upper (location->end() / frames_per_unit);
3842 Editor::playlist_deletion_dialog (Playlist* pl)
3844 ArdourDialog dialog ("playlist deletion dialog");
3845 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3846 "If left alone, no audio files used by it will be cleaned.\n"
3847 "If deleted, audio files used by it alone by will cleaned."),
3850 dialog.set_position (WIN_POS_CENTER);
3851 dialog.get_vbox()->pack_start (label);
3853 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
3854 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
3855 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3857 switch (dialog.run ()) {
3858 case RESPONSE_ACCEPT:
3859 /* delete the playlist */
3863 case RESPONSE_REJECT:
3864 /* keep the playlist */
3876 Editor::audio_region_selection_covers (jack_nframes_t where)
3878 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
3879 if ((*a)->region.covers (where)) {
3888 Editor::prepare_for_cleanup ()
3890 cut_buffer->clear_audio_regions ();
3891 cut_buffer->clear_playlists ();
3893 selection->clear_audio_regions ();
3894 selection->clear_playlists ();
3898 Editor::init_colormap ()
3900 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
3901 pair<ColorID,int> newpair;
3903 newpair.first = (ColorID) x;
3904 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
3905 color_map.insert (newpair);
3910 Editor::transport_loop_location()
3913 return session->locations()->auto_loop_location();
3920 Editor::transport_punch_location()
3923 return session->locations()->auto_punch_location();
3930 Editor::control_layout_scroll (GdkEventScroll* ev)
3932 switch (ev->direction) {
3934 scroll_tracks_up_line ();
3938 case GDK_SCROLL_DOWN:
3939 scroll_tracks_down_line ();
3943 /* no left/right handling yet */
3951 Editor::snapshot_display_selection_changed ()
3953 if (snapshot_display.get_selection()->count_selected_rows() > 0) {
3955 TreeModel::iterator i = snapshot_display.get_selection()->get_selected();
3957 Glib::ustring snap_name = (*i)[snapshot_display_columns.real_name];
3959 if (snap_name.length() == 0) {
3963 if (session->snap_name() == snap_name) {
3967 ARDOUR_UI::instance()->load_session(session->path(), string (snap_name));
3972 Editor::snapshot_display_button_press (GdkEventButton* ev)
3978 Editor::redisplay_snapshots ()
3984 vector<string*>* states;
3986 if ((states = session->possible_states()) == 0) {
3990 snapshot_display_model->clear ();
3992 for (vector<string*>::iterator i = states->begin(); i != states->end(); ++i) {
3993 string statename = *(*i);
3994 TreeModel::Row row = *(snapshot_display_model->append());
3995 row[snapshot_display_columns.visible_name] = statename;
3996 row[snapshot_display_columns.real_name] = statename;
4003 Editor::session_state_saved (string snap_name)
4005 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::session_state_saved), snap_name));
4006 redisplay_snapshots ();
4010 Editor::maximise_editing_space ()
4012 mouse_mode_tearoff->set_visible (false);
4013 tools_tearoff->set_visible (false);
4015 pre_maximal_pane_position = edit_pane.get_position();
4016 edit_pane.set_position (edit_pane.get_width());
4022 Editor::restore_editing_space ()
4024 mouse_mode_tearoff->set_visible (true);
4025 tools_tearoff->set_visible (true);
4026 edit_pane.set_position (pre_maximal_pane_position);