2 Copyright (C) 2000 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 editor_mixer_button (_("editor\nmixer")),
239 selection_start_clock (X_("SelectionStartClock"), true),
240 selection_end_clock (X_("SelectionEndClock"), true),
241 edit_cursor_clock (X_("EditCursorClock"), true),
242 zoom_range_clock (X_("ZoomRangeClock"), true, true),
244 toolbar_selection_clock_table (2,3),
246 mouse_mode_button_table (2, 3),
248 mouse_select_button (_("range")),
249 mouse_move_button (_("object")),
250 mouse_gain_button (_("gain")),
251 mouse_zoom_button (_("zoom")),
252 mouse_timefx_button (_("timefx")),
253 mouse_audition_button (_("listen")),
255 automation_mode_button (_("mode")),
256 global_automation_button (_("automation")),
258 edit_mode_label (_("Edit Mode")),
259 snap_type_label (_("Snap To")),
260 snap_mode_label(_("Snap Mode")),
261 zoom_focus_label (_("Zoom Focus")),
263 /* <CMT Additions> */
264 image_socket_listener(0),
265 /* </CMT Additions> */
269 nudge_label (_("Nudge")),
270 nudge_clock (X_("NudgeClock"), true, true)
275 /* we are a singleton */
277 PublicEditor::_instance = this;
283 selection = new Selection;
284 cut_buffer = new Selection;
286 selection->TimeChanged.connect (mem_fun(*this, &Editor::time_selection_changed));
287 selection->TracksChanged.connect (mem_fun(*this, &Editor::track_selection_changed));
288 selection->RegionsChanged.connect (mem_fun(*this, &Editor::region_selection_changed));
289 selection->PointsChanged.connect (mem_fun(*this, &Editor::point_selection_changed));
291 clicked_regionview = 0;
292 clicked_trackview = 0;
293 clicked_audio_trackview = 0;
294 clicked_crossfadeview = 0;
295 clicked_control_point = 0;
296 latest_regionview = 0;
297 last_update_frame = 0;
299 last_audition_region = 0;
300 current_mixer_strip = 0;
301 current_bbt_points = 0;
303 snap_type = SnapToFrame;
304 set_snap_to (snap_type);
305 snap_mode = SnapNormal;
306 set_snap_mode (snap_mode);
307 snap_threshold = 5.0;
308 bbt_beat_subdivision = 4;
311 autoscroll_timeout_tag = -1;
312 interthread_progress_window = 0;
313 current_interthread_info = 0;
314 _show_measures = true;
315 _show_waveforms = true;
316 _show_waveforms_recording = true;
317 first_action_message = 0;
319 show_gain_after_trim = false;
320 no_zoom_repos_update = false;
321 ignore_route_list_reorder = false;
322 verbose_cursor_on = true;
323 route_removal = false;
325 show_automatic_regions_in_region_list = true;
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 import_audio_item = 0;
343 embed_audio_item = 0;
344 region_edit_menu_split_item = 0;
346 region_edit_menu_split_multichannel_item = 0;
348 ignore_mouse_mode_toggle = false;
349 current_stepping_trackview = 0;
351 entered_regionview = 0;
352 clear_entered_track = false;
353 _new_regionviews_show_envelope = false;
354 current_timestretch = 0;
359 location_marker_color = color_map[cLocationMarker];
360 location_range_color = color_map[cLocationRange];
361 location_cd_marker_color = color_map[cLocationCDMarker];
362 location_loop_color = color_map[cLocationLoop];
363 location_punch_color = color_map[cLocationPunch];
365 range_marker_drag_rect = 0;
366 marker_drag_line = 0;
368 mouse_mode = MouseZoom; /* force change in next call */
369 set_mouse_mode (MouseObject, true);
371 frames_per_unit = 2048; /* too early to use set_frames_per_unit */
372 zoom_focus = ZoomFocusLeft;
373 zoom_range_clock.ValueChanged.connect (mem_fun(*this, &Editor::zoom_adjustment_changed));
375 initialize_rulers ();
376 initialize_canvas ();
378 edit_controls_vbox.set_spacing (track_spacing);
379 horizontal_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::canvas_horizontally_scrolled));
380 vertical_adjustment.signal_value_changed().connect (mem_fun(*this, &Editor::tie_vertical_scrolling));
382 track_canvas.set_hadjustment (horizontal_adjustment);
383 track_canvas.set_vadjustment (vertical_adjustment);
384 time_canvas.set_hadjustment (horizontal_adjustment);
386 track_canvas.signal_map_event().connect (mem_fun (*this, &Editor::track_canvas_map_handler));
387 time_canvas.signal_map_event().connect (mem_fun (*this, &Editor::time_canvas_map_handler));
389 // edit_controls_hbox.pack_start (edit_controls_vbox, true, true);
390 controls_layout.add (edit_controls_vbox);
391 controls_layout.set_name ("EditControlsBase");
392 controls_layout.signal_size_request().connect (mem_fun(*this, &Editor::set_layout_width), false);
393 controls_layout.signal_expose_event().connect (mem_fun(*this, &Editor::layout_expose), false);
395 controls_layout.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::ENTER_NOTIFY_MASK|Gdk::LEAVE_NOTIFY_MASK);
396 controls_layout.signal_button_release_event().connect (mem_fun(*this, &Editor::edit_controls_button_release));
398 edit_vscrollbar.set_adjustment (vertical_adjustment);
399 edit_hscrollbar.set_adjustment (horizontal_adjustment);
401 edit_hscrollbar.signal_button_press_event().connect (mem_fun(*this, &Editor::hscrollbar_button_press));
402 edit_hscrollbar.signal_button_release_event().connect (mem_fun(*this, &Editor::hscrollbar_button_release));
403 edit_hscrollbar.signal_size_allocate().connect (mem_fun(*this, &Editor::hscrollbar_allocate));
408 edit_cursor_clock.ValueChanged.connect (mem_fun(*this, &Editor::edit_cursor_clock_changed));
410 time_canvas_vbox.pack_start (*minsec_ruler, false, false);
411 time_canvas_vbox.pack_start (*smpte_ruler, false, false);
412 time_canvas_vbox.pack_start (*frames_ruler, false, false);
413 time_canvas_vbox.pack_start (*bbt_ruler, false, false);
414 time_canvas_vbox.pack_start (time_canvas, true, true);
415 time_canvas_vbox.set_size_request (-1, (int)(timebar_height * visible_timebars));
417 bbt_label.set_name ("EditorTimeButton");
418 bbt_label.set_size_request (-1, (int)timebar_height);
419 bbt_label.set_alignment (1.0, 0.5);
420 bbt_label.set_padding (5,0);
421 minsec_label.set_name ("EditorTimeButton");
422 minsec_label.set_size_request (-1, (int)timebar_height);
423 minsec_label.set_alignment (1.0, 0.5);
424 minsec_label.set_padding (5,0);
425 smpte_label.set_name ("EditorTimeButton");
426 smpte_label.set_size_request (-1, (int)timebar_height);
427 smpte_label.set_alignment (1.0, 0.5);
428 smpte_label.set_padding (5,0);
429 frame_label.set_name ("EditorTimeButton");
430 frame_label.set_size_request (-1, (int)timebar_height);
431 frame_label.set_alignment (1.0, 0.5);
432 frame_label.set_padding (5,0);
433 tempo_label.set_name ("EditorTimeButton");
434 tempo_label.set_size_request (-1, (int)timebar_height);
435 tempo_label.set_alignment (1.0, 0.5);
436 tempo_label.set_padding (5,0);
437 meter_label.set_name ("EditorTimeButton");
438 meter_label.set_size_request (-1, (int)timebar_height);
439 meter_label.set_alignment (1.0, 0.5);
440 meter_label.set_padding (5,0);
441 mark_label.set_name ("EditorTimeButton");
442 mark_label.set_size_request (-1, (int)timebar_height);
443 mark_label.set_alignment (1.0, 0.5);
444 mark_label.set_padding (5,0);
445 range_mark_label.set_name ("EditorTimeButton");
446 range_mark_label.set_size_request (-1, (int)timebar_height);
447 range_mark_label.set_alignment (1.0, 0.5);
448 range_mark_label.set_padding (5,0);
449 transport_mark_label.set_name ("EditorTimeButton");
450 transport_mark_label.set_size_request (-1, (int)timebar_height);
451 transport_mark_label.set_alignment (1.0, 0.5);
452 transport_mark_label.set_padding (5,0);
454 time_button_vbox.pack_start (minsec_label, false, false);
455 time_button_vbox.pack_start (smpte_label, false, false);
456 time_button_vbox.pack_start (frame_label, false, false);
457 time_button_vbox.pack_start (bbt_label, false, false);
458 time_button_vbox.pack_start (meter_label, false, false);
459 time_button_vbox.pack_start (tempo_label, false, false);
460 time_button_vbox.pack_start (mark_label, false, false);
462 time_button_event_box.add (time_button_vbox);
464 time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
465 time_button_event_box.set_name ("TimebarLabelBase");
466 time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
468 /* these enable us to have a dedicated window (for cursor setting, etc.)
469 for the canvas areas.
472 track_canvas_event_box.add (track_canvas);
474 time_canvas_event_box.add (time_canvas_vbox);
475 time_canvas_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::POINTER_MOTION_MASK);
477 edit_packer.set_col_spacings (0);
478 edit_packer.set_row_spacings (0);
479 edit_packer.set_homogeneous (false);
480 edit_packer.set_name ("EditorWindow");
482 edit_packer.attach (edit_hscrollbar, 1, 2, 0, 1, FILL|EXPAND, FILL, 0, 0);
484 edit_packer.attach (time_button_event_box, 0, 1, 1, 2, FILL, FILL, 0, 0);
485 edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
487 edit_packer.attach (controls_layout, 0, 1, 2, 3, FILL, FILL|EXPAND, 0, 0);
488 edit_packer.attach (track_canvas_event_box, 1, 2, 2, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
489 edit_packer.attach (edit_vscrollbar, 2, 3, 2, 3, FILL, FILL|EXPAND, 0, 0);
491 edit_frame.set_name ("BaseFrame");
492 edit_frame.set_shadow_type (SHADOW_IN);
493 edit_frame.add (edit_packer);
495 zoom_in_button.set_name ("EditorTimeButton");
496 zoom_out_button.set_name ("EditorTimeButton");
497 ARDOUR_UI::instance()->tooltips().set_tip (zoom_in_button, _("Zoom in"));
498 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_button, _("Zoom out"));
500 zoom_out_full_button.set_name ("EditorTimeButton");
501 ARDOUR_UI::instance()->tooltips().set_tip (zoom_out_full_button, _("Zoom to session"));
503 zoom_in_button.add (*(manage (new Gtk::Image (Stock::ZOOM_IN, ICON_SIZE_BUTTON))));
504 zoom_out_button.add (*(manage (new Gtk::Image (Stock::ZOOM_OUT, ICON_SIZE_BUTTON))));
505 zoom_out_full_button.add (*(manage (new Gtk::Image (Stock::ZOOM_FIT, ICON_SIZE_BUTTON))));
507 zoom_in_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), false));
508 zoom_out_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::temporal_zoom_step), true));
509 zoom_out_full_button.signal_clicked().connect (mem_fun(*this, &Editor::temporal_zoom_session));
511 zoom_indicator_box.pack_start (zoom_out_button, false, false);
512 zoom_indicator_box.pack_start (zoom_in_button, false, false);
513 zoom_indicator_box.pack_start (zoom_range_clock, false, false);
514 zoom_indicator_box.pack_start (zoom_out_full_button, false, false);
516 zoom_indicator_label.set_text (_("Zoom Span"));
517 zoom_indicator_label.set_name ("ToolBarLabel");
519 zoom_indicator_vbox.set_spacing (3);
520 zoom_indicator_vbox.set_border_width (3);
521 zoom_indicator_vbox.pack_start (zoom_indicator_label, false, false);
522 zoom_indicator_vbox.pack_start (zoom_indicator_box, false, false);
524 bottom_hbox.set_border_width (3);
525 bottom_hbox.set_spacing (3);
527 route_display_model = ListStore::create(route_display_columns);
528 route_list.set_model (route_display_model);
529 route_list.append_column (_("Tracks"), route_display_columns.text);
530 route_list.set_name ("TrackListDisplay");
531 route_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
532 route_list.set_reorderable (true);
534 route_list.set_size_request (75,-1);
535 route_list.set_headers_visible (true);
536 route_list.set_headers_clickable (true);
539 // route_list.signal_rows_reordered().connect (mem_fun (*this, &Editor::queue_route_list_reordered));
542 // route_display_model->set_sort_func (0, mem_fun (*this, &Editor::route_list_compare_func));
545 //route_list.set_shadow_type (Gtk::SHADOW_IN);
547 route_list_scroller.add (route_list);
548 route_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
550 route_list.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::route_display_selection_changed));
551 route_list.signal_columns_changed().connect (mem_fun(*this, &Editor::route_list_column_click));
553 edit_group_list_button_label.set_text (_("Edit Groups"));
554 edit_group_list_button_label.set_name ("EditGroupTitleButton");
555 edit_group_list_button.add (edit_group_list_button_label);
556 edit_group_list_button.set_name ("EditGroupTitleButton");
558 group_model = ListStore::create(group_columns);
559 edit_group_list.set_model (group_model);
560 edit_group_list.append_column (_("active"), group_columns.is_active);
561 edit_group_list.append_column (_("groupname"), group_columns.text);
562 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(0));
563 edit_group_list.get_column (0)->set_data (X_("colnum"), GUINT_TO_POINTER(1));
565 /* use checkbox for the active column */
567 CellRendererToggle *active_cell = dynamic_cast<CellRendererToggle*>(edit_group_list.get_column_cell_renderer (0));
568 active_cell->property_activatable() = true;
569 active_cell->property_radio() = false;
571 edit_group_list.set_name ("MixerGroupList");
572 //edit_group_list.set_shadow_type (Gtk::SHADOW_IN);
574 edit_group_list.columns_autosize ();
575 edit_group_list.get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
576 edit_group_list.set_reorderable (false);
578 edit_group_list.set_size_request (75, -1);
579 edit_group_list.set_headers_visible (true);
581 edit_group_list_scroller.add (edit_group_list);
582 edit_group_list_scroller.set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
584 edit_group_list_button.signal_clicked().connect (mem_fun(*this, &Editor::edit_group_list_button_clicked));
585 edit_group_list.signal_button_press_event().connect (mem_fun(*this, &Editor::edit_group_list_button_press_event));
586 edit_group_list.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::edit_group_selection_changed));
588 TreeModel::Row row = *(group_model->append());
589 row[group_columns.is_active] = false;
590 row[group_columns.text] = (_("-all-"));
591 edit_group_list.get_selection()->select (row);
592 /* GTK2FIX is set_data(0) setting the is_active to false here?
593 list<string> stupid_list;
595 stupid_list.push_back ("*");
596 stupid_list.push_back (_("-all-"));
598 edit_group_list.rows().push_back (stupid_list);
599 edit_group_list.rows().back().set_data (0);
600 edit_group_list.rows().back().select();
603 edit_group_vbox.pack_start (edit_group_list_button, false, false);
604 edit_group_vbox.pack_start (edit_group_list_scroller, true, true);
606 region_list_model = TreeStore::create (region_list_columns);
607 region_list_sort_model = TreeModelSort::create (region_list_model);
608 region_list_model->set_sort_func (0, mem_fun (*this, &Editor::region_list_sorter));
610 region_list_display.set_model (region_list_sort_model);
611 region_list_display.append_column (_("Regions"), region_list_columns.name);
612 region_list_display.set_reorderable (true);
613 region_list_display.set_size_request (100, -1);
614 region_list_display.set_data ("editor", this);
615 region_list_display.set_flags (Gtk::CAN_FOCUS);
616 region_list_display.set_name ("RegionListDisplay");
618 region_list_scroller.add (region_list_display);
619 region_list_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
621 list<Gtk::TargetEntry> region_list_target_table;
623 region_list_target_table.push_back (TargetEntry ("STRING"));
624 region_list_target_table.push_back (TargetEntry ("text/plain"));
625 region_list_target_table.push_back (TargetEntry ("text/uri-list"));
626 region_list_target_table.push_back (TargetEntry ("application/x-rootwin-drop"));
629 // region_list_display.drag_dest_set (region_list_target_table, DEST_DEFAULT_ALL, GdkDragAction (Gdk::ACTION_COPY|Gdk::ACTION_MOVE));
630 // region_list_display.signal_drag_data_received().connect (mem_fun(*this, &Editor::region_list_display_drag_data_received));
632 region_list_display.signal_key_press_event().connect (mem_fun(*this, &Editor::region_list_display_key_press));
633 region_list_display.signal_key_release_event().connect (mem_fun(*this, &Editor::region_list_display_key_release));
634 region_list_display.signal_button_press_event().connect (mem_fun(*this, &Editor::region_list_display_button_press));
635 region_list_display.signal_button_release_event().connect (mem_fun(*this, &Editor::region_list_display_button_release));
636 region_list_display.get_selection()->signal_changed().connect (mem_fun(*this, &Editor::region_list_selection_changed));
638 //region_list_display.unselect_row.connect (mem_fun(*this, &Editor::region_list_display_unselected));
639 //region_list_display.signal_columns_changed().connect (mem_fun(*this, &Editor::region_list_column_click));
641 named_selection_scroller.add (named_selection_display);
642 named_selection_scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
644 named_selection_model = TreeStore::create (named_selection_columns);
645 named_selection_display.set_model (named_selection_model);
646 named_selection_display.append_column (_("Chunks"), named_selection_columns.text);
647 named_selection_display.set_size_request (100, -1);
648 named_selection_display.set_name ("RegionListDisplay");
650 named_selection_display.get_selection()->set_mode (Gtk::SELECTION_SINGLE);
651 named_selection_display.set_size_request (100, -1);
652 named_selection_display.set_headers_visible (true);
653 named_selection_display.set_headers_clickable (true);
654 named_selection_display.signal_button_press_event().connect (mem_fun(*this, &Editor::named_selection_display_button_press));
655 named_selection_display.get_selection()->signal_changed().connect (mem_fun (*this, &Editor::named_selection_display_selection_changed));
657 the_notebook.append_page (region_list_scroller, _("Regions"));
658 the_notebook.append_page (route_list_scroller, _("Tracks/Busses"));
659 the_notebook.append_page (edit_group_vbox, _("Edit Groups"));
660 the_notebook.append_page (named_selection_scroller, _("Chunks"));
661 the_notebook.set_show_tabs (true);
662 the_notebook.set_scrollable (true);
663 the_notebook.popup_enable ();
665 TearOff *notebook_tearoff = manage (new TearOff (the_notebook));
667 edit_pane.pack1 (edit_frame, true, true);
668 edit_pane.pack2 (*notebook_tearoff, true, true);
670 edit_pane.signal_size_allocate().connect_notify (bind (mem_fun(*this, &Editor::pane_allocation_handler), static_cast<Gtk::Paned*> (&edit_pane)));
672 top_hbox.pack_start (toolbar_frame, true, true);
674 HBox *hbox = manage (new HBox);
675 hbox->pack_start (edit_pane, true, true);
677 global_vpacker.pack_start (top_hbox, false, false);
678 global_vpacker.pack_start (*hbox, true, true);
680 global_hpacker.pack_start (global_vpacker, true, true);
682 set_name ("EditorWindow");
683 cerr << "Adding accel group " << ActionManager::ui_manager->get_accel_group()->gobj() << endl;
684 add_accel_group (ActionManager::ui_manager->get_accel_group());
685 cerr << "... done\n";
687 vpacker.pack_end (global_hpacker, true, true);
689 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
692 _playlist_selector = new PlaylistSelector();
693 _playlist_selector->signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), static_cast<Window *> (_playlist_selector)));
695 AudioRegionView::AudioRegionViewGoingAway.connect (mem_fun(*this, &Editor::catch_vanishing_audio_regionview));
699 nudge_forward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(right_arrow_xpm)))));
700 nudge_backward_button.add (*(manage (new Gtk::Image (Gdk::Pixbuf::create_from_xpm_data(left_arrow_xpm)))));
702 ARDOUR_UI::instance()->tooltips().set_tip (nudge_forward_button, _("Nudge region/selection forwards"));
703 ARDOUR_UI::instance()->tooltips().set_tip (nudge_backward_button, _("Nudge region/selection backwards"));
705 nudge_forward_button.set_name ("TransportButton");
706 nudge_backward_button.set_name ("TransportButton");
708 fade_context_menu.set_name ("ArdourContextMenu");
710 set_title (_("ardour: editor"));
711 set_wmclass (_("ardour_editor"), "Ardour");
714 add_events (Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK);
716 signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
717 signal_delete_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::exit_on_main_window_close));
725 /* <CMT Additions> */
726 if(image_socket_listener)
728 if(image_socket_listener->is_connected())
730 image_socket_listener->close_connection() ;
733 delete image_socket_listener ;
734 image_socket_listener = 0 ;
736 /* </CMT Additions> */
740 Editor::add_toplevel_controls (Container& cont)
742 vpacker.pack_start (cont, false, false);
747 Editor::catch_vanishing_audio_regionview (AudioRegionView *rv)
749 /* note: the selection will take care of the vanishing
750 audioregionview by itself.
753 if (clicked_regionview == rv) {
754 clicked_regionview = 0;
757 if (entered_regionview == rv) {
758 set_entered_regionview (0);
763 Editor::set_entered_regionview (AudioRegionView* rv)
765 if (rv == entered_regionview) {
769 if (entered_regionview) {
770 entered_regionview->exited ();
773 if ((entered_regionview = rv) != 0) {
774 entered_regionview->entered ();
779 Editor::set_entered_track (TimeAxisView* tav)
782 entered_track->exited ();
785 if ((entered_track = tav) != 0) {
786 entered_track->entered ();
791 Editor::left_track_canvas (GdkEventCrossing *ev)
793 set_entered_track (0);
794 set_entered_regionview (0);
800 Editor::show_window ()
805 /* now reset all audio_time_axis heights, because widgets might need
811 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
812 tv = (static_cast<TimeAxisView*>(*i));
818 Editor::tie_vertical_scrolling ()
820 double y1 = vertical_adjustment.get_value();
821 controls_layout.get_vadjustment()->set_value (y1);
823 playhead_cursor->set_y_axis(y1);
824 edit_cursor->set_y_axis(y1);
828 Editor::set_frames_per_unit (double fpu)
830 jack_nframes_t frames;
832 if (fpu == frames_per_unit) {
840 // convert fpu to frame count
842 frames = (jack_nframes_t) floor (fpu * canvas_width);
844 /* don't allow zooms that fit more than the maximum number
845 of frames into an 800 pixel wide space.
848 if (max_frames / fpu < 800.0) {
852 frames_per_unit = fpu;
854 if (frames != zoom_range_clock.current_duration()) {
855 zoom_range_clock.set (frames);
858 /* only update these if we not about to call reposition_x_origin,
859 which will do the same updates.
863 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
866 if (!no_zoom_repos_update) {
867 horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
868 update_fixed_rulers ();
869 tempo_map_changed (Change (0));
872 if (mouse_mode == MouseRange && selection->time.start () != selection->time.end_frame ()) {
873 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
874 (*i)->reshow_selection (selection->time);
878 ZoomChanged (); /* EMIT_SIGNAL */
880 if (edit_cursor) edit_cursor->set_position (edit_cursor->current_frame);
881 if (playhead_cursor) playhead_cursor->set_position (playhead_cursor->current_frame);
888 Editor::instant_save ()
890 if (!constructed || !ARDOUR_UI::instance()->session_loaded) {
895 session->add_instant_xml(get_state(), session->path());
897 Config->add_instant_xml(get_state(), Config->get_user_ardour_path());
902 Editor::reposition_x_origin (jack_nframes_t frame)
904 if (frame != leftmost_frame) {
905 leftmost_frame = frame;
906 double pixel = frame_to_pixel (frame);
907 if (pixel >= horizontal_adjustment.get_upper()) {
908 horizontal_adjustment.set_upper (frame_to_pixel (frame + (current_page_frames())));
910 horizontal_adjustment.set_value (frame/frames_per_unit);
911 XOriginChanged (); /* EMIT_SIGNAL */
916 Editor::edit_cursor_clock_changed()
918 if (edit_cursor->current_frame != edit_cursor_clock.current_time()) {
919 edit_cursor->set_position (edit_cursor_clock.current_time());
925 Editor::zoom_adjustment_changed ()
927 if (session == 0 || no_zoom_repos_update) {
931 double fpu = zoom_range_clock.current_duration() / canvas_width;
935 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
936 } else if (fpu > session->current_end_frame() / canvas_width) {
937 fpu = session->current_end_frame() / canvas_width;
938 zoom_range_clock.set ((jack_nframes_t) floor (fpu * canvas_width));
945 Editor::canvas_horizontally_scrolled ()
947 leftmost_frame = (jack_nframes_t) floor (horizontal_adjustment.get_value() * frames_per_unit);
949 update_fixed_rulers ();
951 if (!edit_hscroll_dragging) {
952 tempo_map_changed (Change (0));
954 update_tempo_based_rulers();
959 Editor::reposition_and_zoom (jack_nframes_t frame, double nfpu)
961 if (!repos_zoom_queued) {
962 Glib::signal_idle().connect (bind (mem_fun(*this, &Editor::deferred_reposition_and_zoom), frame, nfpu));
963 repos_zoom_queued = true;
968 Editor::deferred_reposition_and_zoom (jack_nframes_t frame, double nfpu)
970 /* if we need to force an update to the hscroller stuff,
971 don't set no_zoom_repos_update.
974 no_zoom_repos_update = (frame != leftmost_frame);
976 set_frames_per_unit (nfpu);
977 if (no_zoom_repos_update) {
978 reposition_x_origin (frame);
980 no_zoom_repos_update = false;
981 repos_zoom_queued = false;
987 Editor::on_realize ()
989 Window::on_realize ();
994 Editor::queue_session_control_changed (Session::ControlType t)
996 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::session_control_changed), t));
1000 Editor::session_control_changed (Session::ControlType t)
1002 // right now we're only tracking the loop and punch state
1005 case Session::AutoLoop:
1006 update_loop_range_view (true);
1008 case Session::PunchIn:
1009 case Session::PunchOut:
1010 update_punch_range_view (true);
1019 Editor::fake_add_edit_group (RouteGroup *group)
1021 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::add_edit_group), group));
1025 Editor::fake_handle_new_audio_region (AudioRegion *region)
1027 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_new_audio_region), region));
1031 Editor::fake_handle_audio_region_removed (AudioRegion *region)
1033 Gtkmm2ext::UI::instance()->call_slot (bind (mem_fun(*this, &Editor::handle_audio_region_removed), region));
1037 Editor::fake_handle_new_duration ()
1039 Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &Editor::handle_new_duration));
1043 Editor::start_scrolling ()
1045 scroll_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect
1046 (mem_fun(*this, &Editor::update_current_screen));
1048 slower_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect
1049 (mem_fun(*this, &Editor::update_slower));
1053 Editor::stop_scrolling ()
1055 scroll_connection.disconnect ();
1056 slower_update_connection.disconnect ();
1060 Editor::map_position_change (jack_nframes_t frame)
1062 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::map_position_change), frame));
1064 if (session == 0 || !_follow_playhead) {
1068 center_screen (frame);
1069 playhead_cursor->set_position (frame);
1073 Editor::center_screen (jack_nframes_t frame)
1075 double page = canvas_width * frames_per_unit;
1077 /* if we're off the page, then scroll.
1080 if (frame < leftmost_frame || frame >= leftmost_frame + page) {
1081 center_screen_internal (frame, page);
1086 Editor::center_screen_internal (jack_nframes_t frame, float page)
1091 frame -= (jack_nframes_t) page;
1096 reposition_x_origin (frame);
1100 Editor::handle_new_duration ()
1102 reset_scrolling_region ();
1105 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
1106 horizontal_adjustment.set_value (leftmost_frame/frames_per_unit);
1111 Editor::update_title_s (stringcr_t snap_name)
1113 ENSURE_GUI_THREAD(bind (mem_fun(*this, &Editor::update_title_s), snap_name));
1119 Editor::update_title ()
1121 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::update_title));
1124 bool dirty = session->dirty();
1126 string wintitle = _("ardour: editor: ");
1132 wintitle += session->name();
1134 if (session->snap_name() != session->name()) {
1136 wintitle += session->snap_name();
1143 set_title (wintitle);
1148 Editor::connect_to_session (Session *t)
1152 if (first_action_message) {
1153 first_action_message->hide();
1156 flush_track_canvas();
1160 session->going_away.connect (mem_fun(*this, &Editor::session_going_away));
1162 /* These signals can all be emitted by a non-GUI thread. Therefore the
1163 handlers for them must not attempt to directly interact with the GUI,
1164 but use Gtkmm2ext::UI::instance()->call_slot();
1167 session_connections.push_back (session->TransportStateChange.connect (mem_fun(*this, &Editor::map_transport_state)));
1168 session_connections.push_back (session->PositionChanged.connect (mem_fun(*this, &Editor::map_position_change)));
1169 session_connections.push_back (session->RouteAdded.connect (mem_fun(*this, &Editor::handle_new_route_p)));
1170 session_connections.push_back (session->AudioRegionAdded.connect (mem_fun(*this, &Editor::fake_handle_new_audio_region)));
1171 session_connections.push_back (session->AudioRegionRemoved.connect (mem_fun(*this, &Editor::fake_handle_audio_region_removed)));
1172 session_connections.push_back (session->DurationChanged.connect (mem_fun(*this, &Editor::fake_handle_new_duration)));
1173 session_connections.push_back (session->edit_group_added.connect (mem_fun(*this, &Editor::fake_add_edit_group)));
1174 session_connections.push_back (session->NamedSelectionAdded.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1175 session_connections.push_back (session->NamedSelectionRemoved.connect (mem_fun(*this, &Editor::handle_new_named_selection)));
1176 session_connections.push_back (session->DirtyChanged.connect (mem_fun(*this, &Editor::update_title)));
1177 session_connections.push_back (session->StateSaved.connect (mem_fun(*this, &Editor::update_title_s)));
1178 session_connections.push_back (session->AskAboutPlaylistDeletion.connect (mem_fun(*this, &Editor::playlist_deletion_dialog)));
1179 session_connections.push_back (session->RegionHiddenChange.connect (mem_fun(*this, &Editor::region_hidden)));
1181 session_connections.push_back (session->SMPTEOffsetChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1182 session_connections.push_back (session->SMPTETypeChanged.connect (mem_fun(*this, &Editor::update_just_smpte)));
1184 session_connections.push_back (session->tempo_map().StateChanged.connect (mem_fun(*this, &Editor::tempo_map_changed)));
1186 session->foreach_edit_group(this, &Editor::add_edit_group);
1188 editor_mixer_button.signal_toggled().connect (mem_fun(*this, &Editor::editor_mixer_button_toggled));
1189 editor_mixer_button.set_name (X_("EditorMixerButton"));
1191 edit_cursor_clock.set_session (session);
1192 selection_start_clock.set_session (session);
1193 selection_end_clock.set_session (session);
1194 zoom_range_clock.set_session (session);
1195 _playlist_selector->set_session (session);
1196 nudge_clock.set_session (session);
1198 switch (session->get_edit_mode()) {
1200 edit_mode_selector.set_active_text (edit_mode_strings[splice_index]);
1204 edit_mode_selector.set_active_text (edit_mode_strings[slide_index]);
1208 Location* loc = session->locations()->auto_loop_location();
1210 loc = new Location (0, session->current_end_frame(), _("Loop"),(Location::Flags) (Location::IsAutoLoop | Location::IsHidden));
1211 if (loc->start() == loc->end()) {
1212 loc->set_end (loc->start() + 1);
1214 session->locations()->add (loc, false);
1215 session->set_auto_loop_location (loc);
1219 loc->set_name (_("Loop"));
1222 loc = session->locations()->auto_punch_location();
1224 loc = new Location (0, session->current_end_frame(), _("Punch"), (Location::Flags) (Location::IsAutoPunch | Location::IsHidden));
1225 if (loc->start() == loc->end()) {
1226 loc->set_end (loc->start() + 1);
1228 session->locations()->add (loc, false);
1229 session->set_auto_punch_location (loc);
1233 loc->set_name (_("Punch"));
1236 update_loop_range_view (true);
1237 update_punch_range_view (true);
1239 session->ControlChanged.connect (mem_fun(*this, &Editor::queue_session_control_changed));
1242 refresh_location_display ();
1243 session->locations()->added.connect (mem_fun(*this, &Editor::add_new_location));
1244 session->locations()->removed.connect (mem_fun(*this, &Editor::location_gone));
1245 session->locations()->changed.connect (mem_fun(*this, &Editor::refresh_location_display));
1246 session->locations()->StateChanged.connect (mem_fun(*this, &Editor::refresh_location_display_s));
1247 session->locations()->end_location()->changed.connect (mem_fun(*this, &Editor::end_location_changed));
1249 reset_scrolling_region ();
1251 redisplay_regions ();
1252 redisplay_named_selections ();
1254 //route_list.freeze (); GTK2FIX
1255 route_display_model->clear ();
1256 session->foreach_route (this, &Editor::handle_new_route);
1257 // route_list.select_all ();
1259 //route_list.sort ();
1260 route_list_reordered ();
1261 //route_list.thaw ();
1263 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
1264 (static_cast<TimeAxisView*>(*i))->set_samples_per_unit (frames_per_unit);
1267 /* ::reposition_x_origin() doesn't work right here, since the old
1268 position may be zero already, and it does nothing in such
1274 horizontal_adjustment.set_upper (session->current_end_frame() / frames_per_unit);
1275 horizontal_adjustment.set_value (0);
1277 restore_ruler_visibility ();
1278 tempo_map_changed (Change (0));
1280 edit_cursor->set_position (0);
1281 playhead_cursor->set_position (0);
1285 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
1288 /* don't show master bus in a new session */
1290 if (ARDOUR_UI::instance()->session_is_new ()) {
1292 TreeModel::Children rows = route_display_model->children();
1293 TreeModel::Children::iterator i;
1295 //route_list.freeze ();
1297 for (i = rows.begin(); i != rows.end(); ++i) {
1298 TimeAxisView *tv = (*i)[route_display_columns.tv];
1299 AudioTimeAxisView *atv;
1301 if ((atv = dynamic_cast<AudioTimeAxisView*>(tv)) != 0) {
1302 if (atv->route().master()) {
1303 route_list.get_selection()->unselect (i);
1304 //(*i)->unselect ();
1309 //route_list.thaw ();
1314 Editor::build_cursors ()
1316 using namespace Gdk;
1318 Gdk::Color mbg ("#000000" ); /* Black */
1319 Gdk::Color mfg ("#0000ff" ); /* Blue. */
1322 RefPtr<Bitmap> source, mask;
1323 source = Bitmap::create (mag_bits, mag_width, mag_height);
1324 mask = Bitmap::create (magmask_bits, mag_width, mag_height);
1325 zoom_cursor = new Gdk::Cursor (source, mask, mfg, mbg, mag_x_hot, mag_y_hot);
1328 Gdk::Color fbg ("#ffffff" );
1329 Gdk::Color ffg ("#000000" );
1332 RefPtr<Bitmap> source, mask;
1334 source = Bitmap::create (fader_cursor_bits, fader_cursor_width, fader_cursor_height);
1335 mask = Bitmap::create (fader_cursor_mask_bits, fader_cursor_width, fader_cursor_height);
1336 fader_cursor = new Gdk::Cursor (source, mask, ffg, fbg, fader_cursor_x_hot, fader_cursor_y_hot);
1340 RefPtr<Bitmap> source, mask;
1341 source = Bitmap::create (speaker_cursor_bits, speaker_cursor_width, speaker_cursor_height);
1342 mask = Bitmap::create (speaker_cursor_mask_bits, speaker_cursor_width, speaker_cursor_height);
1343 speaker_cursor = new Gdk::Cursor (source, mask, ffg, fbg, speaker_cursor_x_hot, speaker_cursor_y_hot);
1346 grabber_cursor = new Gdk::Cursor (HAND2);
1347 cross_hair_cursor = new Gdk::Cursor (CROSSHAIR);
1348 trimmer_cursor = new Gdk::Cursor (SB_H_DOUBLE_ARROW);
1349 selector_cursor = new Gdk::Cursor (XTERM);
1350 time_fx_cursor = new Gdk::Cursor (SIZING);
1351 wait_cursor = new Gdk::Cursor (WATCH);
1352 timebar_cursor = new Gdk::Cursor(LEFT_PTR);
1356 Editor::popup_fade_context_menu (int button, int32_t time, ArdourCanvas::Item* item, ItemType item_type)
1358 using namespace Menu_Helpers;
1359 AudioRegionView* arv = static_cast<AudioRegionView*> (item->get_data ("regionview"));
1362 fatal << _("programming error: fade in canvas item has no regionview data pointer!") << endmsg;
1366 MenuList& items (fade_context_menu.items());
1370 switch (item_type) {
1372 case FadeInHandleItem:
1373 if (arv->region.fade_in_active()) {
1374 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), false)));
1376 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_in_active), true)));
1379 items.push_back (SeparatorElem());
1381 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Linear)));
1382 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogB)));
1383 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Fast)));
1384 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::LogA)));
1385 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_in_shape), AudioRegion::Slow)));
1389 case FadeOutHandleItem:
1390 if (arv->region.fade_out_active()) {
1391 items.push_back (MenuElem (_("Deactivate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), false)));
1393 items.push_back (MenuElem (_("Activate"), bind (mem_fun (*arv, &AudioRegionView::set_fade_out_active), true)));
1396 items.push_back (SeparatorElem());
1398 items.push_back (MenuElem (_("Linear"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Linear)));
1399 items.push_back (MenuElem (_("Slowest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Fast)));
1400 items.push_back (MenuElem (_("Slow"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogB)));
1401 items.push_back (MenuElem (_("Fast"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::LogA)));
1402 items.push_back (MenuElem (_("Fastest"), bind (mem_fun (arv->region, &AudioRegion::set_fade_out_shape), AudioRegion::Slow)));
1406 fatal << _("programming error: ")
1407 << X_("non-fade canvas item passed to popup_fade_context_menu()")
1412 fade_context_menu.popup (button, time);
1416 Editor::popup_track_context_menu (int button, int32_t time, ItemType item_type, bool with_selection, jack_nframes_t frame)
1418 using namespace Menu_Helpers;
1419 Menu* (Editor::*build_menu_function)(jack_nframes_t);
1422 switch (item_type) {
1424 case AudioRegionViewName:
1425 case AudioRegionViewNameHighlight:
1426 if (with_selection) {
1427 build_menu_function = &Editor::build_track_selection_context_menu;
1429 build_menu_function = &Editor::build_track_region_context_menu;
1434 if (with_selection) {
1435 build_menu_function = &Editor::build_track_selection_context_menu;
1437 build_menu_function = &Editor::build_track_context_menu;
1441 case CrossfadeViewItem:
1442 build_menu_function = &Editor::build_track_crossfade_context_menu;
1446 if (clicked_audio_trackview->get_diskstream()) {
1447 build_menu_function = &Editor::build_track_context_menu;
1449 build_menu_function = &Editor::build_track_bus_context_menu;
1454 /* probably shouldn't happen but if it does, we don't care */
1458 menu = (this->*build_menu_function)(frame);
1459 menu->set_name ("ArdourContextMenu");
1461 /* now handle specific situations */
1463 switch (item_type) {
1465 case AudioRegionViewName:
1466 case AudioRegionViewNameHighlight:
1467 if (!with_selection) {
1468 if (region_edit_menu_split_item) {
1469 if (clicked_regionview && clicked_regionview->region.covers (edit_cursor->current_frame)) {
1470 // GTK2FIX find the action, change its sensitivity
1471 // region_edit_menu_split_item->set_sensitive (true);
1473 // GTK2FIX see above
1474 // region_edit_menu_split_item->set_sensitive (false);
1477 if (region_edit_menu_split_multichannel_item) {
1478 if (clicked_regionview && clicked_regionview->region.n_channels() > 1) {
1479 // GTK2FIX find the action, change its sensitivity
1480 // region_edit_menu_split_multichannel_item->set_sensitive (true);
1482 // GTK2FIX see above
1483 // region_edit_menu_split_multichannel_item->set_sensitive (false);
1492 case CrossfadeViewItem:
1499 /* probably shouldn't happen but if it does, we don't care */
1503 if (clicked_audio_trackview && clicked_audio_trackview->audio_track()) {
1505 /* Bounce to disk */
1507 using namespace Menu_Helpers;
1508 MenuList& edit_items = menu->items();
1510 edit_items.push_back (SeparatorElem());
1512 switch (clicked_audio_trackview->audio_track()->freeze_state()) {
1513 case AudioTrack::NoFreeze:
1514 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1517 case AudioTrack::Frozen:
1518 edit_items.push_back (MenuElem (_("Unfreeze"), mem_fun(*this, &Editor::unfreeze_route)));
1521 case AudioTrack::UnFrozen:
1522 edit_items.push_back (MenuElem (_("Freeze"), mem_fun(*this, &Editor::freeze_route)));
1528 menu->popup (button, time);
1532 Editor::build_track_context_menu (jack_nframes_t ignored)
1534 using namespace Menu_Helpers;
1536 MenuList& edit_items = track_context_menu.items();
1539 add_dstream_context_items (edit_items);
1540 return &track_context_menu;
1544 Editor::build_track_bus_context_menu (jack_nframes_t ignored)
1546 using namespace Menu_Helpers;
1548 MenuList& edit_items = track_context_menu.items();
1551 add_bus_context_items (edit_items);
1552 return &track_context_menu;
1556 Editor::build_track_region_context_menu (jack_nframes_t frame)
1558 using namespace Menu_Helpers;
1559 MenuList& edit_items = track_region_context_menu.items();
1562 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1568 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()))) {
1569 Playlist::RegionList* regions = pl->regions_at ((jack_nframes_t) floor ( (double)frame * ds->speed()));
1570 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1571 add_region_context_items (atv->view, (*i), edit_items);
1577 add_dstream_context_items (edit_items);
1579 return &track_region_context_menu;
1583 Editor::build_track_crossfade_context_menu (jack_nframes_t frame)
1585 using namespace Menu_Helpers;
1586 MenuList& edit_items = track_crossfade_context_menu.items();
1587 edit_items.clear ();
1589 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (clicked_trackview);
1596 if ((ds = atv->get_diskstream()) && ((pl = ds->playlist()) != 0) && ((apl = dynamic_cast<AudioPlaylist*> (pl)) != 0)) {
1598 Playlist::RegionList* regions = pl->regions_at (frame);
1599 AudioPlaylist::Crossfades xfades;
1601 apl->crossfades_at (frame, xfades);
1603 bool many = xfades.size() > 1;
1605 for (AudioPlaylist::Crossfades::iterator i = xfades.begin(); i != xfades.end(); ++i) {
1606 add_crossfade_context_items (atv->view, (*i), edit_items, many);
1609 for (Playlist::RegionList::iterator i = regions->begin(); i != regions->end(); ++i) {
1610 add_region_context_items (atv->view, (*i), edit_items);
1617 add_dstream_context_items (edit_items);
1619 return &track_crossfade_context_menu;
1623 Editor::build_track_selection_context_menu (jack_nframes_t ignored)
1625 using namespace Menu_Helpers;
1626 MenuList& edit_items = track_selection_context_menu.items();
1627 edit_items.clear ();
1629 add_selection_context_items (edit_items);
1630 add_dstream_context_items (edit_items);
1632 return &track_selection_context_menu;
1636 Editor::add_crossfade_context_items (StreamView* view, Crossfade* xfade, Menu_Helpers::MenuList& edit_items, bool many)
1638 using namespace Menu_Helpers;
1639 Menu *xfade_menu = manage (new Menu);
1640 MenuList& items = xfade_menu->items();
1641 xfade_menu->set_name ("ArdourContextMenu");
1644 if (xfade->active()) {
1650 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_active), xfade)));
1651 items.push_back (MenuElem (_("Edit"), bind (mem_fun(*this, &Editor::edit_xfade), xfade)));
1653 if (xfade->can_follow_overlap()) {
1655 if (xfade->following_overlap()) {
1656 str = _("Convert to short");
1658 str = _("Convert to full");
1661 items.push_back (MenuElem (str, bind (mem_fun(*this, &Editor::toggle_xfade_length), xfade)));
1665 str = xfade->out().name();
1667 str += xfade->in().name();
1669 str = _("Crossfade");
1672 edit_items.push_back (MenuElem (str, *xfade_menu));
1673 edit_items.push_back (SeparatorElem());
1677 Editor::xfade_edit_left_region ()
1679 if (clicked_crossfadeview) {
1680 clicked_crossfadeview->left_view.show_region_editor ();
1685 Editor::xfade_edit_right_region ()
1687 if (clicked_crossfadeview) {
1688 clicked_crossfadeview->right_view.show_region_editor ();
1693 Editor::add_region_context_items (StreamView* sv, Region* region, Menu_Helpers::MenuList& edit_items)
1695 using namespace Menu_Helpers;
1696 Menu *region_menu = manage (new Menu);
1697 MenuList& items = region_menu->items();
1698 region_menu->set_name ("ArdourContextMenu");
1700 AudioRegion* ar = 0;
1703 ar = dynamic_cast<AudioRegion*> (region);
1706 /* when this particular menu pops up, make the relevant region
1710 region_menu->signal_map_event().connect (bind (mem_fun(*this, &Editor::set_selected_regionview_from_map_event), sv, region));
1712 items.push_back (MenuElem (_("Popup region editor"), mem_fun(*this, &Editor::edit_region)));
1713 items.push_back (MenuElem (_("Raise to top layer"), mem_fun(*this, &Editor::raise_region_to_top)));
1714 items.push_back (MenuElem (_("Lower to bottom layer"), mem_fun (*this, &Editor::lower_region_to_bottom)));
1715 items.push_back (SeparatorElem());
1716 items.push_back (MenuElem (_("Define sync point"), mem_fun(*this, &Editor::set_region_sync_from_edit_cursor)));
1717 items.push_back (MenuElem (_("Remove sync point"), mem_fun(*this, &Editor::remove_region_sync)));
1718 items.push_back (SeparatorElem());
1720 items.push_back (MenuElem (_("Audition"), mem_fun(*this, &Editor::audition_selected_region)));
1721 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_region)));
1722 items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
1723 items.push_back (SeparatorElem());
1725 /* XXX hopefully this nonsense will go away with SigC++ 2.X, where the compiler
1726 might be able to figure out which overloaded member function to use in
1730 void (Editor::*type_A_pmf)(void (Region::*pmf)(bool), bool) = &Editor::region_selection_op;
1732 items.push_back (MenuElem (_("Lock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, true)));
1733 items.push_back (MenuElem (_("Unlock"), bind (mem_fun(*this, type_A_pmf), &Region::set_locked, false)));
1734 items.push_back (SeparatorElem());
1736 if (region->muted()) {
1737 items.push_back (MenuElem (_("Unmute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, false)));
1739 items.push_back (MenuElem (_("Mute"), bind (mem_fun(*this, type_A_pmf), &Region::set_muted, true)));
1741 items.push_back (SeparatorElem());
1743 items.push_back (MenuElem (_("Original position"), mem_fun(*this, &Editor::naturalize)));
1744 items.push_back (SeparatorElem());
1749 items.push_back (MenuElem (_("Toggle envelope visibility"), mem_fun(*this, &Editor::toggle_gain_envelope_visibility)));
1750 items.push_back (MenuElem (_("Toggle envelope active"), mem_fun(*this, &Editor::toggle_gain_envelope_active)));
1751 items.push_back (SeparatorElem());
1753 if (ar->scale_amplitude() != 1.0f) {
1754 items.push_back (MenuElem (_("DeNormalize"), mem_fun(*this, &Editor::denormalize_region)));
1756 items.push_back (MenuElem (_("Normalize"), mem_fun(*this, &Editor::normalize_region)));
1759 items.push_back (MenuElem (_("Reverse"), mem_fun(*this, &Editor::reverse_region)));
1760 items.push_back (SeparatorElem());
1764 Menu *nudge_menu = manage (new Menu());
1765 MenuList& nudge_items = nudge_menu->items();
1766 nudge_menu->set_name ("ArdourContextMenu");
1768 nudge_items.push_back (MenuElem (_("Nudge fwd"), (bind (mem_fun(*this, &Editor::nudge_forward), false))));
1769 nudge_items.push_back (MenuElem (_("Nudge bwd"), (bind (mem_fun(*this, &Editor::nudge_backward), false))));
1770 nudge_items.push_back (MenuElem (_("Nudge fwd by capture offset"), (mem_fun(*this, &Editor::nudge_forward_capture_offset))));
1771 nudge_items.push_back (MenuElem (_("Nudge bwd by capture offset"), (mem_fun(*this, &Editor::nudge_backward_capture_offset))));
1773 items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1774 items.push_back (SeparatorElem());
1776 Menu *trim_menu = manage (new Menu);
1777 MenuList& trim_items = trim_menu->items();
1778 trim_menu->set_name ("ArdourContextMenu");
1780 trim_items.push_back (MenuElem (_("Start to edit cursor"), mem_fun(*this, &Editor::trim_region_from_edit_cursor)));
1781 trim_items.push_back (MenuElem (_("Edit cursor to end"), mem_fun(*this, &Editor::trim_region_to_edit_cursor)));
1783 items.push_back (MenuElem (_("Trim"), *trim_menu));
1784 items.push_back (SeparatorElem());
1786 items.push_back (MenuElem (_("Split"), (mem_fun(*this, &Editor::split_region))));
1787 region_edit_menu_split_item = &items.back();
1789 items.push_back (MenuElem (_("Make mono regions"), (mem_fun(*this, &Editor::split_multichannel_region))));
1790 region_edit_menu_split_multichannel_item = &items.back();
1792 items.push_back (MenuElem (_("Duplicate"), (bind (mem_fun(*this, &Editor::duplicate_dialog), true))));
1793 items.push_back (MenuElem (_("Fill Track"), (mem_fun(*this, &Editor::region_fill_track))));
1794 items.push_back (SeparatorElem());
1795 items.push_back (MenuElem (_("Remove"), mem_fun(*this, &Editor::remove_clicked_region)));
1796 items.push_back (SeparatorElem());
1797 items.push_back (MenuElem (_("Destroy"), mem_fun(*this, &Editor::destroy_clicked_region)));
1799 /* OK, stick the region submenu at the top of the list, and then add
1803 /* we have to hack up the region name because "_" has a special
1804 meaning for menu titles.
1807 string::size_type pos = 0;
1808 string menu_item_name = region->name();
1810 while ((pos = menu_item_name.find ("_", pos)) != string::npos) {
1811 menu_item_name.replace (pos, 1, "__");
1815 edit_items.push_back (MenuElem (menu_item_name, *region_menu));
1816 edit_items.push_back (SeparatorElem());
1820 Editor::add_selection_context_items (Menu_Helpers::MenuList& edit_items)
1822 using namespace Menu_Helpers;
1823 Menu *selection_menu = manage (new Menu);
1824 MenuList& items = selection_menu->items();
1825 selection_menu->set_name ("ArdourContextMenu");
1827 items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
1828 items.push_back (MenuElem (_("Loop range"), mem_fun(*this, &Editor::set_route_loop_selection)));
1829 items.push_back (SeparatorElem());
1830 items.push_back (MenuElem (_("Create chunk from range"), mem_fun(*this, &Editor::name_selection)));
1831 items.push_back (SeparatorElem());
1832 items.push_back (MenuElem (_("Create Region"), mem_fun(*this, &Editor::new_region_from_selection)));
1833 items.push_back (MenuElem (_("Separate Region"), mem_fun(*this, &Editor::separate_region_from_selection)));
1834 items.push_back (MenuElem (_("Crop Region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
1835 items.push_back (MenuElem (_("Bounce range"), mem_fun(*this, &Editor::bounce_range_selection)));
1836 items.push_back (SeparatorElem());
1837 items.push_back (MenuElem (_("Duplicate"), bind (mem_fun(*this, &Editor::duplicate_dialog), false)));
1838 items.push_back (SeparatorElem());
1839 items.push_back (MenuElem (_("Export"), mem_fun(*this, &Editor::export_selection)));
1840 items.push_back (SeparatorElem());
1841 items.push_back (MenuElem (_("Fill range w/Region"), mem_fun(*this, &Editor::region_fill_selection)));
1843 edit_items.push_back (MenuElem (_("Range"), *selection_menu));
1844 edit_items.push_back (SeparatorElem());
1848 Editor::add_dstream_context_items (Menu_Helpers::MenuList& edit_items)
1850 using namespace Menu_Helpers;
1854 Menu *play_menu = manage (new Menu);
1855 MenuList& play_items = play_menu->items();
1856 play_menu->set_name ("ArdourContextMenu");
1858 play_items.push_back (MenuElem (_("Play from edit cursor")));
1859 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1860 play_items.push_back (MenuElem (_("Play region"), mem_fun(*this, &Editor::play_selected_region)));
1861 play_items.push_back (SeparatorElem());
1862 play_items.push_back (MenuElem (_("Loop Region"), mem_fun(*this, &Editor::loop_selected_region)));
1864 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1868 Menu *select_menu = manage (new Menu);
1869 MenuList& select_items = select_menu->items();
1870 select_menu->set_name ("ArdourContextMenu");
1872 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1873 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1874 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1875 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1876 select_items.push_back (SeparatorElem());
1877 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1878 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1879 select_items.push_back (SeparatorElem());
1881 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1885 Menu *cutnpaste_menu = manage (new Menu);
1886 MenuList& cutnpaste_items = cutnpaste_menu->items();
1887 cutnpaste_menu->set_name ("ArdourContextMenu");
1889 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1890 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1891 cutnpaste_items.push_back (MenuElem (_("Paste at edit cursor"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1892 cutnpaste_items.push_back (MenuElem (_("Paste at mouse"), mem_fun(*this, &Editor::mouse_paste)));
1894 cutnpaste_items.push_back (SeparatorElem());
1896 cutnpaste_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
1897 cutnpaste_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
1899 cutnpaste_items.push_back (SeparatorElem());
1901 cutnpaste_items.push_back (MenuElem (_("Insert chunk"), bind (mem_fun(*this, &Editor::paste_named_selection), 1.0f)));
1903 cutnpaste_items.push_back (SeparatorElem());
1905 cutnpaste_items.push_back (MenuElem (_("New Region from range"), mem_fun(*this, &Editor::new_region_from_selection)));
1906 cutnpaste_items.push_back (MenuElem (_("Separate Range"), mem_fun(*this, &Editor::separate_region_from_selection)));
1908 edit_items.push_back (MenuElem (_("Edit"), *cutnpaste_menu));
1910 /* Adding new material */
1912 Menu *import_menu = manage (new Menu());
1913 MenuList& import_items = import_menu->items();
1914 import_menu->set_name ("ArdourContextMenu");
1916 import_items.push_back (MenuElem (_("Insert Region"), bind (mem_fun(*this, &Editor::insert_region_list_selection), 1.0f)));
1917 import_items.push_back (MenuElem (_("Insert external sndfile"), bind (mem_fun(*this, &Editor::insert_sndfile), false)));
1919 edit_items.push_back (MenuElem (_("Import"), *import_menu));
1923 Menu *nudge_menu = manage (new Menu());
1924 MenuList& nudge_items = nudge_menu->items();
1925 nudge_menu->set_name ("ArdourContextMenu");
1927 edit_items.push_back (SeparatorElem());
1928 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1929 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1930 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1931 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1933 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1937 Editor::add_bus_context_items (Menu_Helpers::MenuList& edit_items)
1939 using namespace Menu_Helpers;
1943 Menu *play_menu = manage (new Menu);
1944 MenuList& play_items = play_menu->items();
1945 play_menu->set_name ("ArdourContextMenu");
1947 play_items.push_back (MenuElem (_("Play from edit cursor")));
1948 play_items.push_back (MenuElem (_("Play from start"), mem_fun(*this, &Editor::play_from_start)));
1949 edit_items.push_back (MenuElem (_("Play"), *play_menu));
1953 Menu *select_menu = manage (new Menu);
1954 MenuList& select_items = select_menu->items();
1955 select_menu->set_name ("ArdourContextMenu");
1957 select_items.push_back (MenuElem (_("Select All in track"), bind (mem_fun(*this, &Editor::select_all_in_track), false)));
1958 select_items.push_back (MenuElem (_("Select All"), bind (mem_fun(*this, &Editor::select_all), false)));
1959 select_items.push_back (MenuElem (_("Invert in track"), mem_fun(*this, &Editor::invert_selection_in_track)));
1960 select_items.push_back (MenuElem (_("Invert"), mem_fun(*this, &Editor::invert_selection)));
1961 select_items.push_back (SeparatorElem());
1962 select_items.push_back (MenuElem (_("Select loop range"), mem_fun(*this, &Editor::set_selection_from_loop)));
1963 select_items.push_back (MenuElem (_("Select punch range"), mem_fun(*this, &Editor::set_selection_from_punch)));
1964 select_items.push_back (SeparatorElem());
1966 edit_items.push_back (MenuElem (_("Select"), *select_menu));
1970 Menu *cutnpaste_menu = manage (new Menu);
1971 MenuList& cutnpaste_items = cutnpaste_menu->items();
1972 cutnpaste_menu->set_name ("ArdourContextMenu");
1974 cutnpaste_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
1975 cutnpaste_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
1976 cutnpaste_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
1978 Menu *nudge_menu = manage (new Menu());
1979 MenuList& nudge_items = nudge_menu->items();
1980 nudge_menu->set_name ("ArdourContextMenu");
1982 edit_items.push_back (SeparatorElem());
1983 nudge_items.push_back (MenuElem (_("Nudge entire track fwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, true))));
1984 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor fwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, true))));
1985 nudge_items.push_back (MenuElem (_("Nudge entire track bwd"), (bind (mem_fun(*this, &Editor::nudge_track), false, false))));
1986 nudge_items.push_back (MenuElem (_("Nudge track after edit cursor bwd"), (bind (mem_fun(*this, &Editor::nudge_track), true, false))));
1988 edit_items.push_back (MenuElem (_("Nudge"), *nudge_menu));
1991 /* CURSOR SETTING AND MARKS AND STUFF */
1994 Editor::set_snap_to (SnapType st)
1997 vector<string> txt = internationalize (snap_type_strings);
1998 snap_type_selector.set_active_text (txt[(int)st]);
2002 switch (snap_type) {
2003 case SnapToAThirtysecondBeat:
2004 case SnapToASixteenthBeat:
2005 case SnapToAEighthBeat:
2006 case SnapToAQuarterBeat:
2007 case SnapToAThirdBeat:
2008 update_tempo_based_rulers ();
2016 Editor::set_snap_mode (SnapMode mode)
2019 vector<string> txt = internationalize (snap_mode_strings);
2020 snap_mode_selector.set_active_text (txt[(int)mode]);
2026 Editor::add_location_from_selection ()
2028 if (selection->time.empty()) {
2032 if (session == 0 || clicked_trackview == 0) {
2036 jack_nframes_t start = selection->time[clicked_selection].start;
2037 jack_nframes_t end = selection->time[clicked_selection].end;
2039 Location *location = new Location (start, end, "selection");
2041 session->begin_reversible_command (_("add marker"));
2042 session->add_undo (session->locations()->get_memento());
2043 session->locations()->add (location, true);
2044 session->add_redo_no_execute (session->locations()->get_memento());
2045 session->commit_reversible_command ();
2049 Editor::add_location_from_playhead_cursor ()
2051 jack_nframes_t where = session->audible_frame();
2053 Location *location = new Location (where, where, "mark", Location::IsMark);
2054 session->begin_reversible_command (_("add marker"));
2055 session->add_undo (session->locations()->get_memento());
2056 session->locations()->add (location, true);
2057 session->add_redo_no_execute (session->locations()->get_memento());
2058 session->commit_reversible_command ();
2063 Editor::set_state (const XMLNode& node)
2065 const XMLProperty* prop;
2067 int x, y, width, height, xoff, yoff;
2069 if ((geometry = find_named_node (node, "geometry")) == 0) {
2071 width = default_width;
2072 height = default_height;
2080 width = atoi(geometry->property("x_size")->value());
2081 height = atoi(geometry->property("y_size")->value());
2082 x = atoi(geometry->property("x_pos")->value());
2083 y = atoi(geometry->property("y_pos")->value());
2084 xoff = atoi(geometry->property("x_off")->value());
2085 yoff = atoi(geometry->property("y_off")->value());
2088 set_default_size(width, height);
2091 if ((prop = node.property ("zoom-focus"))) {
2092 set_zoom_focus ((ZoomFocus) atoi (prop->value()));
2095 if ((prop = node.property ("zoom"))) {
2096 set_frames_per_unit (atof (prop->value()));
2099 if ((prop = node.property ("snap-to"))) {
2100 set_snap_to ((SnapType) atoi (prop->value()));
2103 if ((prop = node.property ("snap-mode"))) {
2104 set_snap_mode ((SnapMode) atoi (prop->value()));
2107 if ((prop = node.property ("show-waveforms"))) {
2108 bool yn = (prop->value() == "yes");
2109 _show_waveforms = !yn;
2110 set_show_waveforms (yn);
2113 if ((prop = node.property ("show-waveforms-recording"))) {
2114 bool yn = (prop->value() == "yes");
2115 _show_waveforms_recording = !yn;
2116 set_show_waveforms_recording (yn);
2119 if ((prop = node.property ("show-measures"))) {
2120 bool yn = (prop->value() == "yes");
2121 _show_measures = !yn;
2122 set_show_measures (yn);
2125 if ((prop = node.property ("follow-playhead"))) {
2126 bool yn = (prop->value() == "yes");
2127 _follow_playhead = !yn;
2128 set_follow_playhead (yn);
2131 if ((prop = node.property ("xfades-visible"))) {
2132 bool yn = (prop->value() == "yes");
2133 _xfade_visibility = !yn;
2134 set_xfade_visibility (yn);
2137 if ((prop = node.property ("region-list-sort-type"))) {
2138 region_list_sort_type = (Editing::RegionListSortType) -1; /* force change */
2139 reset_region_list_sort_type(str2regionlistsorttype(prop->value()));
2142 if ((prop = node.property ("mouse-mode"))) {
2143 MouseMode m = str2mousemode(prop->value());
2144 mouse_mode = MouseMode ((int) m + 1); /* lie, force mode switch */
2145 set_mouse_mode (m, true);
2147 mouse_mode = MouseGain; /* lie, to force the mode switch */
2148 set_mouse_mode (MouseObject, true);
2151 if ((prop = node.property ("editor-mixer-button"))) {
2152 editor_mixer_button.set_active(prop->value() == "yes");
2159 Editor::get_state ()
2161 XMLNode* node = new XMLNode ("Editor");
2164 if (is_realized()) {
2165 Glib::RefPtr<Gdk::Window> win = get_window();
2167 int x, y, xoff, yoff, width, height;
2168 win->get_root_origin(x, y);
2169 win->get_position(xoff, yoff);
2170 win->get_size(width, height);
2172 XMLNode* geometry = new XMLNode ("geometry");
2174 snprintf(buf, sizeof(buf), "%d", width);
2175 geometry->add_property("x_size", string(buf));
2176 snprintf(buf, sizeof(buf), "%d", height);
2177 geometry->add_property("y_size", string(buf));
2178 snprintf(buf, sizeof(buf), "%d", x);
2179 geometry->add_property("x_pos", string(buf));
2180 snprintf(buf, sizeof(buf), "%d", y);
2181 geometry->add_property("y_pos", string(buf));
2182 snprintf(buf, sizeof(buf), "%d", xoff);
2183 geometry->add_property("x_off", string(buf));
2184 snprintf(buf, sizeof(buf), "%d", yoff);
2185 geometry->add_property("y_off", string(buf));
2186 snprintf(buf,sizeof(buf), "%d",gtk_paned_get_position (static_cast<Paned*>(&edit_pane)->gobj()));
2187 geometry->add_property("edit_pane_pos", string(buf));
2189 node->add_child_nocopy (*geometry);
2192 snprintf (buf, sizeof(buf), "%d", (int) zoom_focus);
2193 node->add_property ("zoom-focus", buf);
2194 snprintf (buf, sizeof(buf), "%f", frames_per_unit);
2195 node->add_property ("zoom", buf);
2196 snprintf (buf, sizeof(buf), "%d", (int) snap_type);
2197 node->add_property ("snap-to", buf);
2198 snprintf (buf, sizeof(buf), "%d", (int) snap_mode);
2199 node->add_property ("snap-mode", buf);
2201 node->add_property ("show-waveforms", _show_waveforms ? "yes" : "no");
2202 node->add_property ("show-waveforms-recording", _show_waveforms_recording ? "yes" : "no");
2203 node->add_property ("show-measures", _show_measures ? "yes" : "no");
2204 node->add_property ("follow-playhead", _follow_playhead ? "yes" : "no");
2205 node->add_property ("xfades-visible", _xfade_visibility ? "yes" : "no");
2206 node->add_property ("region-list-sort-type", enum2str(region_list_sort_type));
2207 node->add_property ("mouse-mode", enum2str(mouse_mode));
2208 node->add_property ("editor-mixer-button", editor_mixer_button.get_active() ? "yes" : "no");
2216 Editor::trackview_by_y_position (double y)
2218 TrackViewList::iterator iter;
2221 for (iter = track_views.begin(); iter != track_views.end(); ++iter) {
2229 if (tv->y_position <= y && y < ((tv->y_position + tv->height + track_spacing))) {
2238 Editor::snap_to (jack_nframes_t& start, int32_t direction, bool for_mark)
2240 Location* before = 0;
2241 Location* after = 0;
2247 const jack_nframes_t one_second = session->frame_rate();
2248 const jack_nframes_t one_minute = session->frame_rate() * 60;
2250 jack_nframes_t presnap = start;
2252 switch (snap_type) {
2258 start = (jack_nframes_t) ceil ((double) start / (one_second / 75)) * (one_second / 75);
2260 start = (jack_nframes_t) floor ((double) start / (one_second / 75)) * (one_second / 75);
2263 case SnapToSMPTEFrame:
2265 start = (jack_nframes_t) (ceil ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2267 start = (jack_nframes_t) (floor ((double) start / session->frames_per_smpte_frame()) * session->frames_per_smpte_frame());
2271 case SnapToSMPTESeconds:
2272 if (session->smpte_offset_negative())
2274 start += session->smpte_offset ();
2276 start -= session->smpte_offset ();
2278 if (direction > 0) {
2279 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2281 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2284 if (session->smpte_offset_negative())
2286 start -= session->smpte_offset ();
2288 start += session->smpte_offset ();
2292 case SnapToSMPTEMinutes:
2293 if (session->smpte_offset_negative())
2295 start += session->smpte_offset ();
2297 start -= session->smpte_offset ();
2300 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2302 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2304 if (session->smpte_offset_negative())
2306 start -= session->smpte_offset ();
2308 start += session->smpte_offset ();
2314 start = (jack_nframes_t) ceil ((double) start / one_second) * one_second;
2316 start = (jack_nframes_t) floor ((double) start / one_second) * one_second;
2322 start = (jack_nframes_t) ceil ((double) start / one_minute) * one_minute;
2324 start = (jack_nframes_t) floor ((double) start / one_minute) * one_minute;
2329 start = session->tempo_map().round_to_bar (start, direction);
2333 start = session->tempo_map().round_to_beat (start, direction);
2336 case SnapToAThirtysecondBeat:
2337 start = session->tempo_map().round_to_beat_subdivision (start, 32);
2340 case SnapToASixteenthBeat:
2341 start = session->tempo_map().round_to_beat_subdivision (start, 16);
2344 case SnapToAEighthBeat:
2345 start = session->tempo_map().round_to_beat_subdivision (start, 8);
2348 case SnapToAQuarterBeat:
2349 start = session->tempo_map().round_to_beat_subdivision (start, 4);
2352 case SnapToAThirdBeat:
2353 start = session->tempo_map().round_to_beat_subdivision (start, 3);
2356 case SnapToEditCursor:
2357 start = edit_cursor->current_frame;
2365 before = session->locations()->first_location_before (start);
2366 after = session->locations()->first_location_after (start);
2368 if (direction < 0) {
2370 start = before->start();
2374 } else if (direction > 0) {
2376 start = after->start();
2378 start = session->current_end_frame();
2383 /* find nearest of the two */
2384 if ((start - before->start()) < (after->start() - start)) {
2385 start = before->start();
2387 start = after->start();
2390 start = before->start();
2393 start = after->start();
2400 case SnapToRegionStart:
2401 case SnapToRegionEnd:
2402 case SnapToRegionSync:
2403 case SnapToRegionBoundary:
2404 if (!region_boundary_cache.empty()) {
2405 vector<jack_nframes_t>::iterator i;
2407 if (direction > 0) {
2408 i = std::upper_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2410 i = std::lower_bound (region_boundary_cache.begin(), region_boundary_cache.end(), start);
2413 if (i != region_boundary_cache.end()) {
2416 start = region_boundary_cache.back();
2422 switch (snap_mode) {
2428 if (presnap > start) {
2429 if (presnap > (start + unit_to_frame(snap_threshold))) {
2433 } else if (presnap < start) {
2434 if (presnap < (start - unit_to_frame(snap_threshold))) {
2446 Editor::setup_toolbar ()
2449 vector<ToggleButton *> mouse_mode_buttons;
2451 mouse_mode_buttons.push_back (&mouse_move_button);
2452 mouse_mode_buttons.push_back (&mouse_select_button);
2453 mouse_mode_buttons.push_back (&mouse_gain_button);
2454 mouse_mode_buttons.push_back (&mouse_zoom_button);
2455 mouse_mode_buttons.push_back (&mouse_timefx_button);
2456 mouse_mode_buttons.push_back (&mouse_audition_button);
2457 mouse_mode_button_set = new GroupedButtons (mouse_mode_buttons);
2459 mouse_mode_button_table.set_homogeneous (true);
2460 mouse_mode_button_table.set_col_spacings (2);
2461 mouse_mode_button_table.set_row_spacings (2);
2462 mouse_mode_button_table.set_border_width (5);
2464 mouse_mode_button_table.attach (mouse_move_button, 0, 1, 0, 1);
2465 mouse_mode_button_table.attach (mouse_select_button, 1, 2, 0, 1);
2466 mouse_mode_button_table.attach (mouse_zoom_button, 2, 3, 0, 1);
2468 mouse_mode_button_table.attach (mouse_gain_button, 0, 1, 1, 2);
2469 mouse_mode_button_table.attach (mouse_timefx_button, 1, 2, 1, 2);
2470 mouse_mode_button_table.attach (mouse_audition_button, 2, 3, 1, 2);
2472 mouse_mode_tearoff = manage (new TearOff (mouse_mode_button_table));
2473 mouse_mode_tearoff->set_name ("MouseModeBase");
2475 mouse_mode_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2476 mouse_mode_tearoff->tearoff_window()));
2477 mouse_mode_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2478 mouse_mode_tearoff->tearoff_window(), 1));
2480 mouse_move_button.set_name ("MouseModeButton");
2481 mouse_select_button.set_name ("MouseModeButton");
2482 mouse_gain_button.set_name ("MouseModeButton");
2483 mouse_zoom_button.set_name ("MouseModeButton");
2484 mouse_timefx_button.set_name ("MouseModeButton");
2485 mouse_audition_button.set_name ("MouseModeButton");
2487 ARDOUR_UI::instance()->tooltips().set_tip (mouse_move_button, _("select/move objects"));
2488 ARDOUR_UI::instance()->tooltips().set_tip (mouse_select_button, _("select/move ranges"));
2489 ARDOUR_UI::instance()->tooltips().set_tip (mouse_gain_button, _("draw gain automation"));
2490 ARDOUR_UI::instance()->tooltips().set_tip (mouse_zoom_button, _("select zoom range"));
2491 ARDOUR_UI::instance()->tooltips().set_tip (mouse_timefx_button, _("stretch/shrink regions"));
2492 ARDOUR_UI::instance()->tooltips().set_tip (mouse_audition_button, _("listen to specific regions"));
2494 mouse_move_button.unset_flags (Gtk::CAN_FOCUS);
2495 mouse_select_button.unset_flags (Gtk::CAN_FOCUS);
2496 mouse_gain_button.unset_flags (Gtk::CAN_FOCUS);
2497 mouse_zoom_button.unset_flags (Gtk::CAN_FOCUS);
2498 mouse_timefx_button.unset_flags (Gtk::CAN_FOCUS);
2499 mouse_audition_button.unset_flags (Gtk::CAN_FOCUS);
2501 mouse_select_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseRange));
2502 mouse_select_button.signal_button_release_event().connect (mem_fun(*this, &Editor::mouse_select_button_release));
2504 mouse_move_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseObject));
2505 mouse_gain_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseGain));
2506 mouse_zoom_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseZoom));
2507 mouse_timefx_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseTimeFX));
2508 mouse_audition_button.signal_toggled().connect (bind (mem_fun(*this, &Editor::mouse_mode_toggled), Editing::MouseAudition));
2510 // mouse_move_button.set_active (true);
2512 /* automation control */
2514 global_automation_button.set_name ("MouseModeButton");
2515 automation_mode_button.set_name ("MouseModeButton");
2517 automation_box.set_spacing (2);
2518 automation_box.set_border_width (2);
2519 automation_box.pack_start (global_automation_button, false, false);
2520 automation_box.pack_start (automation_mode_button, false, false);
2524 edit_mode_label.set_name ("ToolBarLabel");
2526 edit_mode_selector.set_name ("EditModeSelector");
2528 edit_mode_box.set_spacing (3);
2529 edit_mode_box.set_border_width (3);
2531 /* XXX another disgusting hack because of the way combo boxes size themselves */
2533 const guint32 FUDGE = 20; // Combo's are stupid - they steal space from the entry for the button
2534 Gtkmm2ext::set_size_request_to_display_given_text (edit_mode_selector, "EdgtMode", 2+FUDGE, 10);
2535 set_popdown_strings (edit_mode_selector, internationalize (edit_mode_strings));
2536 edit_mode_box.pack_start (edit_mode_label, false, false);
2537 edit_mode_box.pack_start (edit_mode_selector, false, false);
2539 edit_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::edit_mode_selection_done));
2543 snap_type_label.set_name ("ToolBarLabel");
2545 snap_type_selector.set_name ("SnapTypeSelector");
2547 snap_type_box.set_spacing (3);
2548 snap_type_box.set_border_width (3);
2550 /* XXX another disgusting hack because of the way combo boxes size themselves */
2552 Gtkmm2ext::set_size_request_to_display_given_text (snap_type_selector, "SMPTE Seconds", 2+FUDGE, 10);
2553 set_popdown_strings (snap_type_selector, internationalize (snap_type_strings));
2555 snap_type_box.pack_start (snap_type_label, false, false);
2556 snap_type_box.pack_start (snap_type_selector, false, false);
2558 snap_type_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_type_selection_done));
2560 /* Snap mode, not snap type */
2562 snap_mode_label.set_name ("ToolBarLabel");
2564 snap_mode_selector.set_name ("SnapModeSelector");
2566 snap_mode_box.set_spacing (3);
2567 snap_mode_box.set_border_width (3);
2569 Gtkmm2ext::set_size_request_to_display_given_text (snap_mode_selector, "SngpMode", 2+FUDGE, 10);
2570 set_popdown_strings (snap_mode_selector, internationalize (snap_mode_strings));
2572 snap_mode_box.pack_start (snap_mode_label, false, false);
2573 snap_mode_box.pack_start (snap_mode_selector, false, false);
2575 snap_mode_selector.signal_changed().connect (mem_fun(*this, &Editor::snap_mode_selection_done));
2577 /* Zoom focus mode */
2579 zoom_focus_label.set_name ("ToolBarLabel");
2581 zoom_focus_selector.set_name ("ZoomFocusSelector");
2583 zoom_focus_box.set_spacing (3);
2584 zoom_focus_box.set_border_width (3);
2586 /* XXX another disgusting hack because of the way combo boxes size themselves */
2588 Gtkmm2ext::set_size_request_to_display_given_text (zoom_focus_selector, "Edgt Cursor", 2+FUDGE, 10);
2589 set_popdown_strings (zoom_focus_selector, internationalize (zoom_focus_strings));
2591 zoom_focus_box.pack_start (zoom_focus_label, false, false);
2592 zoom_focus_box.pack_start (zoom_focus_selector, false, false);
2594 zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
2596 /* selection/cursor clocks */
2598 toolbar_selection_cursor_label.set_name ("ToolBarLabel");
2599 selection_start_clock_label.set_name ("ToolBarLabel");
2600 selection_end_clock_label.set_name ("ToolBarLabel");
2601 edit_cursor_clock_label.set_name ("ToolBarLabel");
2603 selection_start_clock_label.set_text (_("Start:"));
2604 selection_end_clock_label.set_text (_("End:"));
2605 edit_cursor_clock_label.set_text (_("Edit:"));
2607 toolbar_selection_clock_table.set_border_width (5);
2608 toolbar_selection_clock_table.set_col_spacings (2);
2609 toolbar_selection_clock_table.set_homogeneous (false);
2611 // toolbar_selection_clock_table.attach (selection_start_clock_label, 0, 1, 0, 1, 0, 0, 0, 0);
2612 // toolbar_selection_clock_table.attach (selection_end_clock_label, 1, 2, 0, 1, 0, 0, 0, 0);
2613 toolbar_selection_clock_table.attach (edit_cursor_clock_label, 2, 3, 0, 1, FILL, FILL, 0, 0);
2615 // toolbar_selection_clock_table.attach (selection_start_clock, 0, 1, 1, 2, 0, 0);
2616 // toolbar_selection_clock_table.attach (selection_end_clock, 1, 2, 1, 2, 0, 0);
2617 toolbar_selection_clock_table.attach (edit_cursor_clock, 2, 3, 1, 2, FILL, FILL);
2620 // toolbar_clock_vbox.set_spacing (2);
2621 // toolbar_clock_vbox.set_border_width (10);
2622 /* the editor/mixer button will be enabled at session connect */
2624 editor_mixer_button.set_active(false);
2625 editor_mixer_button.set_sensitive(false);
2627 HBox* hbox = new HBox;
2629 hbox->pack_start (editor_mixer_button, false, false);
2630 hbox->pack_start (toolbar_selection_clock_table, false, false);
2631 hbox->pack_start (zoom_indicator_vbox, false, false);
2632 hbox->pack_start (zoom_focus_box, false, false);
2633 hbox->pack_start (snap_type_box, false, false);
2634 hbox->pack_start (snap_mode_box, false, false);
2635 hbox->pack_start (edit_mode_box, false, false);
2637 VBox *vbox = manage (new VBox);
2639 vbox->set_spacing (3);
2640 vbox->set_border_width (3);
2642 HBox *nbox = manage (new HBox);
2644 nudge_forward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_forward), false));
2645 nudge_backward_button.signal_clicked().connect (bind (mem_fun(*this, &Editor::nudge_backward), false));
2647 nbox->pack_start (nudge_backward_button, false, false);
2648 nbox->pack_start (nudge_forward_button, false, false);
2649 nbox->pack_start (nudge_clock, false, false, 5);
2651 nudge_label.set_name ("ToolBarLabel");
2653 vbox->pack_start (nudge_label, false, false);
2654 vbox->pack_start (*nbox, false, false);
2656 hbox->pack_start (*vbox, false, false);
2660 tools_tearoff = new TearOff (*hbox);
2661 tools_tearoff->set_name ("MouseModeBase");
2663 tools_tearoff->Detach.connect (bind (mem_fun(*this, &Editor::detach_tearoff), static_cast<Gtk::Box*>(&toolbar_hbox),
2664 tools_tearoff->tearoff_window()));
2665 tools_tearoff->Attach.connect (bind (mem_fun(*this, &Editor::reattach_tearoff), static_cast<Gtk::Box*> (&toolbar_hbox),
2666 tools_tearoff->tearoff_window(), 0));
2669 toolbar_hbox.set_spacing (8);
2670 toolbar_hbox.set_border_width (2);
2672 toolbar_hbox.pack_start (*tools_tearoff, false, false);
2673 toolbar_hbox.pack_start (*mouse_mode_tearoff, false, false);
2675 toolbar_base.set_name ("ToolBarBase");
2676 toolbar_base.add (toolbar_hbox);
2678 toolbar_frame.set_shadow_type (Gtk::SHADOW_OUT);
2679 toolbar_frame.set_name ("BaseFrame");
2680 toolbar_frame.add (toolbar_base);
2684 Editor::_autoscroll_canvas (void *arg)
2686 return ((Editor *) arg)->autoscroll_canvas ();
2690 Editor::autoscroll_canvas ()
2692 jack_nframes_t new_frame;
2693 bool keep_calling = true;
2695 if (autoscroll_direction < 0) {
2696 if (leftmost_frame < autoscroll_distance) {
2699 new_frame = leftmost_frame - autoscroll_distance;
2702 if (leftmost_frame > max_frames - autoscroll_distance) {
2703 new_frame = max_frames;
2705 new_frame = leftmost_frame + autoscroll_distance;
2709 if (new_frame != leftmost_frame) {
2710 reposition_x_origin (new_frame);
2713 if (new_frame == 0 || new_frame == max_frames) {
2720 if (autoscroll_cnt == 1) {
2722 /* connect the timeout so that we get called repeatedly */
2724 autoscroll_timeout_tag = gtk_timeout_add (100, _autoscroll_canvas, this);
2725 keep_calling = false;
2727 } else if (autoscroll_cnt > 10 && autoscroll_cnt < 20) {
2729 /* after about a while, speed up a bit by changing the timeout interval */
2731 autoscroll_timeout_tag = gtk_timeout_add (50, _autoscroll_canvas, this);
2732 keep_calling = false;
2734 } else if (autoscroll_cnt >= 20 && autoscroll_cnt < 30) {
2736 /* after about another while, speed up some more */
2738 autoscroll_timeout_tag = gtk_timeout_add (25, _autoscroll_canvas, this);
2739 keep_calling = false;
2741 } else if (autoscroll_cnt >= 30) {
2743 /* we've been scrolling for a while ... crank it up */
2745 autoscroll_distance = 10 * (jack_nframes_t) floor (canvas_width * frames_per_unit);
2748 return keep_calling;
2752 Editor::start_canvas_autoscroll (int dir)
2758 stop_canvas_autoscroll ();
2760 autoscroll_direction = dir;
2761 autoscroll_distance = (jack_nframes_t) floor ((canvas_width * frames_per_unit)/10.0);
2764 /* do it right now, which will start the repeated callbacks */
2766 autoscroll_canvas ();
2770 Editor::stop_canvas_autoscroll ()
2772 if (autoscroll_timeout_tag >= 0) {
2773 gtk_timeout_remove (autoscroll_timeout_tag);
2774 autoscroll_timeout_tag = -1;
2779 Editor::convert_drop_to_paths (vector<string>& paths,
2780 GdkDragContext *context,
2783 GtkSelectionData *data,
2791 gchar *tname = gdk_atom_name (data->type);
2793 if (session == 0 || strcmp (tname, "text/plain") != 0) {
2797 /* Parse the "uri-list" format that Nautilus provides,
2798 where each pathname is delimited by \r\n
2801 path = (char *) data->data;
2804 for (int n = 0; n < data->length; ++n) {
2808 if (path[n] == '\r') {
2815 if (path[n] == '\n') {
2816 paths.push_back (spath);
2820 warning << _("incorrectly formatted URI list, ignored")
2828 /* nautilus and presumably some other file managers prefix even text/plain with file:// */
2830 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2832 // cerr << "dropped text was " << *p << endl;
2836 // cerr << "decoded was " << *p << endl;
2838 if ((*p).substr (0,7) == "file://") {
2839 (*p) = (*p).substr (7);
2847 Editor::track_canvas_drag_data_received (GdkDragContext *context,
2850 GtkSelectionData *data,
2855 AudioTimeAxisView* tv;
2857 vector<string> paths;
2860 jack_nframes_t frame;
2862 if (convert_drop_to_paths (paths, context, x, y, data, info, time)) {
2866 /* D-n-D coordinates are window-relative, so convert to "world" coordinates
2872 track_canvas.c2w( x, y, wx, wy);
2874 ev.type = GDK_BUTTON_RELEASE;
2878 frame = event_frame (&ev, 0, &cy);
2882 if ((tvp = trackview_by_y_position (cy)) == 0) {
2884 /* drop onto canvas background: create a new track */
2886 insert_paths_as_new_tracks (paths, false);
2889 } else if ((tv = dynamic_cast<AudioTimeAxisView*>(tvp)) != 0) {
2891 /* check that its an audio track, not a bus */
2893 if (tv->get_diskstream()) {
2895 for (vector<string>::iterator p = paths.begin(); p != paths.end(); ++p) {
2896 insert_sndfile_into (*p, true, tv, frame);
2903 gtk_drag_finish (context, TRUE, FALSE, time);
2907 Editor::new_tempo_section ()
2913 Editor::map_transport_state ()
2915 ENSURE_GUI_THREAD (mem_fun(*this, &Editor::map_transport_state));
2917 if (session->transport_stopped()) {
2918 have_pending_keyboard_selection = false;
2924 Editor::State::State ()
2926 selection = new Selection;
2929 Editor::State::~State ()
2935 Editor::get_memento () const
2937 State *state = new State;
2939 store_state (*state);
2940 return bind (mem_fun (*(const_cast<Editor*>(this)), &Editor::restore_state), state);
2944 Editor::store_state (State& state) const
2946 *state.selection = *selection;
2950 Editor::restore_state (State *state)
2952 if (*selection == *state->selection) {
2956 *selection = *state->selection;
2957 time_selection_changed ();
2958 region_selection_changed ();
2960 /* XXX other selection change handlers? */
2964 Editor::begin_reversible_command (string name)
2967 UndoAction ua = get_memento();
2968 session->begin_reversible_command (name, &ua);
2973 Editor::commit_reversible_command ()
2976 UndoAction ua = get_memento();
2977 session->commit_reversible_command (&ua);
2982 Editor::flush_track_canvas ()
2984 /* I don't think this is necessary, and only causes more problems.
2985 I'm commenting it out
2986 and if the imageframe folks don't have any issues, we can take
2987 out this method entirely
2990 //gnome_canvas_update_now (GNOME_CANVAS(track_canvas));
2991 //gtk_main_iteration ();
2995 Editor::set_selected_track_from_click (bool add, bool with_undo, bool no_remove)
2997 if (!clicked_trackview) {
3002 begin_reversible_command (_("set selected trackview"));
3007 if (selection->selected (clicked_trackview)) {
3009 selection->remove (clicked_trackview);
3012 selection->add (clicked_trackview);
3017 if (selection->selected (clicked_trackview) && selection->tracks.size() == 1) {
3018 /* no commit necessary */
3022 selection->set (clicked_trackview);
3026 commit_reversible_command ();
3031 Editor::set_selected_control_point_from_click (bool add, bool with_undo, bool no_remove)
3033 if (!clicked_control_point) {
3038 begin_reversible_command (_("set selected control point"));
3048 commit_reversible_command ();
3053 Editor::set_selected_regionview_from_click (bool add, bool no_track_remove)
3055 if (!clicked_regionview) {
3059 AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*>(&clicked_regionview->get_time_axis_view());
3065 RouteGroup* group = atv->route().edit_group();
3066 vector<AudioRegionView*> all_equivalent_regions;
3068 if (group && group->is_active()) {
3070 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3072 AudioTimeAxisView* tatv;
3074 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3076 if (tatv->route().edit_group() != group) {
3081 vector<AudioRegion*> results;
3082 AudioRegionView* marv;
3085 if ((ds = tatv->get_diskstream()) == 0) {
3090 if ((pl = ds->playlist()) != 0) {
3091 pl->get_equivalent_regions (clicked_regionview->region,
3095 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3096 if ((marv = tatv->view->find_view (**ir)) != 0) {
3097 all_equivalent_regions.push_back (marv);
3106 all_equivalent_regions.push_back (clicked_regionview);
3110 begin_reversible_command (_("set selected regionview"));
3114 if (clicked_regionview->get_selected()) {
3115 if (group && group->is_active() && selection->audio_regions.size() > 1) {
3116 /* reduce selection down to just the one clicked */
3117 selection->set (clicked_regionview);
3119 selection->remove (clicked_regionview);
3122 selection->add (all_equivalent_regions);
3125 set_selected_track_from_click (add, false, no_track_remove);
3129 // karsten wiese suggested these two lines to make
3130 // a selected region rise to the top. but this
3131 // leads to a mismatch between actual layering
3132 // and visual layering. resolution required ....
3134 // gnome_canvas_item_raise_to_top (clicked_regionview->get_canvas_group());
3135 // gnome_canvas_item_raise_to_top (clicked_regionview->get_time_axis_view().canvas_display);
3137 if (clicked_regionview->get_selected()) {
3138 /* no commit necessary: we are the one selected. */
3143 selection->set (all_equivalent_regions);
3144 set_selected_track_from_click (add, false, false);
3148 commit_reversible_command () ;
3152 Editor::set_selected_regionview_from_region_list (Region& r, bool add)
3154 vector<AudioRegionView*> all_equivalent_regions;
3155 AudioRegion* region;
3157 if ((region = dynamic_cast<AudioRegion*>(&r)) == 0) {
3161 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3163 AudioTimeAxisView* tatv;
3165 if ((tatv = dynamic_cast<AudioTimeAxisView*> (*i)) != 0) {
3168 vector<AudioRegion*> results;
3169 AudioRegionView* marv;
3172 if ((ds = tatv->get_diskstream()) == 0) {
3177 if ((pl = ds->playlist()) != 0) {
3178 pl->get_region_list_equivalent_regions (*region, results);
3181 for (vector<AudioRegion*>::iterator ir = results.begin(); ir != results.end(); ++ir) {
3182 if ((marv = tatv->view->find_view (**ir)) != 0) {
3183 all_equivalent_regions.push_back (marv);
3190 begin_reversible_command (_("set selected regions"));
3194 selection->add (all_equivalent_regions);
3198 selection->set (all_equivalent_regions);
3201 commit_reversible_command () ;
3205 Editor::set_selected_regionview_from_map_event (GdkEventAny* ev, StreamView* sv, Region* r)
3207 AudioRegionView* rv;
3210 if ((ar = dynamic_cast<AudioRegion*> (r)) == 0) {
3214 if ((rv = sv->find_view (*ar)) == 0) {
3218 /* don't reset the selection if its something other than
3219 a single other region.
3222 if (selection->audio_regions.size() > 1) {
3226 begin_reversible_command (_("set selected regions"));
3228 selection->set (rv);
3230 commit_reversible_command () ;
3236 Editor::set_edit_group_solo (Route& route, bool yn)
3238 RouteGroup *edit_group;
3240 if ((edit_group = route.edit_group()) != 0) {
3241 edit_group->apply (&Route::set_solo, yn, this);
3243 route.set_solo (yn, this);
3248 Editor::set_edit_group_mute (Route& route, bool yn)
3250 RouteGroup *edit_group = 0;
3252 if ((edit_group == route.edit_group()) != 0) {
3253 edit_group->apply (&Route::set_mute, yn, this);
3255 route.set_mute (yn, this);
3260 Editor::set_edit_menu (Menu& menu)
3263 edit_menu->signal_map_event().connect (mem_fun(*this, &Editor::edit_menu_map_handler));
3267 Editor::edit_menu_map_handler (GdkEventAny* ev)
3269 using namespace Menu_Helpers;
3270 MenuList& edit_items = edit_menu->items();
3273 /* Nuke all the old items */
3275 edit_items.clear ();
3281 if (session->undo_depth() == 0) {
3284 label = string_compose(_("Undo (%1)"), session->next_undo());
3287 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::undo), 1U)));
3289 if (session->undo_depth() == 0) {
3290 edit_items.back().set_sensitive (false);
3293 if (session->redo_depth() == 0) {
3296 label = string_compose(_("Redo (%1)"), session->next_redo());
3299 edit_items.push_back (MenuElem (label, bind (mem_fun(*this, &Editor::redo), 1U)));
3300 if (session->redo_depth() == 0) {
3301 edit_items.back().set_sensitive (false);
3304 vector<MenuItem*> mitems;
3306 edit_items.push_back (SeparatorElem());
3307 edit_items.push_back (MenuElem (_("Cut"), mem_fun(*this, &Editor::cut)));
3308 mitems.push_back (&edit_items.back());
3309 edit_items.push_back (MenuElem (_("Copy"), mem_fun(*this, &Editor::copy)));
3310 mitems.push_back (&edit_items.back());
3311 edit_items.push_back (MenuElem (_("Paste"), bind (mem_fun(*this, &Editor::paste), 1.0f)));
3312 mitems.push_back (&edit_items.back());
3313 edit_items.push_back (SeparatorElem());
3314 edit_items.push_back (MenuElem (_("Align"), bind (mem_fun(*this, &Editor::align), ARDOUR::SyncPoint)));
3315 mitems.push_back (&edit_items.back());
3316 edit_items.push_back (MenuElem (_("Align Relative"), bind (mem_fun(*this, &Editor::align_relative), ARDOUR::SyncPoint)));
3317 mitems.push_back (&edit_items.back());
3318 edit_items.push_back (SeparatorElem());
3320 if (selection->empty()) {
3321 for (vector<MenuItem*>::iterator i = mitems.begin(); i != mitems.end(); ++i) {
3322 (*i)->set_sensitive (false);
3326 Menu* import_menu = manage (new Menu());
3327 import_menu->set_name ("ArdourContextMenu");
3328 MenuList& import_items = import_menu->items();
3330 import_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::import_audio), true)));
3331 import_items.push_back (MenuElem (_("... as new region"), bind (mem_fun(*this, &Editor::import_audio), false)));
3333 Menu* embed_menu = manage (new Menu());
3334 embed_menu->set_name ("ArdourContextMenu");
3335 MenuList& embed_items = embed_menu->items();
3337 embed_items.push_back (MenuElem (_("... as new track"), bind (mem_fun(*this, &Editor::insert_sndfile), true)));
3338 embed_items.push_back (MenuElem (_("... as new region"), mem_fun(*this, &Editor::embed_audio)));
3340 edit_items.push_back (MenuElem (_("Import audio (copy)"), *import_menu));
3341 edit_items.push_back (MenuElem (_("Embed audio (link)"), *embed_menu));
3342 edit_items.push_back (SeparatorElem());
3344 edit_items.push_back (MenuElem (_("Remove last capture"), mem_fun(*this, &Editor::remove_last_capture)));
3345 if (!session->have_captured()) {
3346 edit_items.back().set_sensitive (false);
3353 Editor::duplicate_dialog (bool dup_region)
3356 if (clicked_regionview == 0) {
3360 if (selection->time.length() == 0) {
3365 ArdourDialog win ("duplicate dialog");
3367 Label label (_("Duplicate how many times?"));
3369 win.get_vbox()->pack_start (label);
3370 win.add_action_widget (entry, RESPONSE_ACCEPT);
3371 win.add_button (Stock::OK, RESPONSE_ACCEPT);
3372 win.add_button (Stock::CANCEL, RESPONSE_CANCEL);
3374 win.set_position (Gtk::WIN_POS_MOUSE);
3376 entry.set_text ("1");
3377 set_size_request_to_display_given_text (entry, X_("12345678"), 20, 15);
3378 entry.select_region (0, entry.get_text_length());
3379 entry.grab_focus ();
3382 // win.get_window()->set_decorations (Gdk::WMDecoration (Gdk::DECOR_BORDER|Gdk::DECOR_RESIZEH));
3385 switch (win.run ()) {
3386 case RESPONSE_ACCEPT:
3392 string text = entry.get_text();
3395 if (sscanf (text.c_str(), "%f", ×) == 1) {
3397 AudioRegionSelection regions;
3398 regions.add (clicked_regionview);
3399 duplicate_some_regions (regions, times);
3401 duplicate_selection (times);
3407 Editor::show_verbose_canvas_cursor ()
3409 verbose_canvas_cursor->raise_to_top();
3410 verbose_canvas_cursor->show();
3411 verbose_cursor_visible = true;
3415 Editor::hide_verbose_canvas_cursor ()
3417 verbose_canvas_cursor->hide();
3418 verbose_cursor_visible = false;
3422 Editor::set_verbose_canvas_cursor (stringcr_t txt, double x, double y)
3424 /* XXX get origin of canvas relative to root window,
3425 add x and y and check compared to gdk_screen_{width,height}
3427 verbose_canvas_cursor->property_text() = txt.c_str();
3428 verbose_canvas_cursor->property_x() = x;
3429 verbose_canvas_cursor->property_y() = y;
3433 Editor::set_verbose_canvas_cursor_text (stringcr_t txt)
3435 verbose_canvas_cursor->property_text() = txt.c_str();
3439 Editor::edit_mode_selection_done ()
3445 string choice = edit_mode_selector.get_active_text();
3446 EditMode mode = Slide;
3448 if (choice == _("Splice")) {
3450 } else if (choice == _("Slide")) {
3454 session->set_edit_mode (mode);
3458 Editor::snap_type_selection_done ()
3464 string choice = snap_type_selector.get_active_text();
3465 SnapType snaptype = SnapToFrame;
3467 if (choice == _("Beats/3")) {
3468 snaptype = SnapToAThirdBeat;
3469 } else if (choice == _("Beats/4")) {
3470 snaptype = SnapToAQuarterBeat;
3471 } else if (choice == _("Beats/8")) {
3472 snaptype = SnapToAEighthBeat;
3473 } else if (choice == _("Beats/16")) {
3474 snaptype = SnapToASixteenthBeat;
3475 } else if (choice == _("Beats/32")) {
3476 snaptype = SnapToAThirtysecondBeat;
3477 } else if (choice == _("Beats")) {
3478 snaptype = SnapToBeat;
3479 } else if (choice == _("Bars")) {
3480 snaptype = SnapToBar;
3481 } else if (choice == _("Marks")) {
3482 snaptype = SnapToMark;
3483 } else if (choice == _("Edit Cursor")) {
3484 snaptype = SnapToEditCursor;
3485 } else if (choice == _("Region starts")) {
3486 snaptype = SnapToRegionStart;
3487 } else if (choice == _("Region ends")) {
3488 snaptype = SnapToRegionEnd;
3489 } else if (choice == _("Region bounds")) {
3490 snaptype = SnapToRegionBoundary;
3491 } else if (choice == _("Region syncs")) {
3492 snaptype = SnapToRegionSync;
3493 } else if (choice == _("CD Frames")) {
3494 snaptype = SnapToCDFrame;
3495 } else if (choice == _("SMPTE Frames")) {
3496 snaptype = SnapToSMPTEFrame;
3497 } else if (choice == _("SMPTE Seconds")) {
3498 snaptype = SnapToSMPTESeconds;
3499 } else if (choice == _("SMPTE Minutes")) {
3500 snaptype = SnapToSMPTEMinutes;
3501 } else if (choice == _("Seconds")) {
3502 snaptype = SnapToSeconds;
3503 } else if (choice == _("Minutes")) {
3504 snaptype = SnapToMinutes;
3505 } else if (choice == _("None")) {
3506 snaptype = SnapToFrame;
3509 set_snap_to (snaptype);
3513 Editor::snap_mode_selection_done ()
3519 string choice = snap_mode_selector.get_active_text();
3520 SnapMode mode = SnapNormal;
3522 if (choice == _("Normal")) {
3524 } else if (choice == _("Magnetic")) {
3525 mode = SnapMagnetic;
3528 set_snap_mode (mode);
3532 Editor::zoom_focus_selection_done ()
3538 string choice = zoom_focus_selector.get_active_text();
3539 ZoomFocus focus_type = ZoomFocusLeft;
3541 if (choice == _("Left")) {
3542 focus_type = ZoomFocusLeft;
3543 } else if (choice == _("Right")) {
3544 focus_type = ZoomFocusRight;
3545 } else if (choice == _("Center")) {
3546 focus_type = ZoomFocusCenter;
3547 } else if (choice == _("Playhead")) {
3548 focus_type = ZoomFocusPlayhead;
3549 } else if (choice == _("Edit Cursor")) {
3550 focus_type = ZoomFocusEdit;
3553 set_zoom_focus (focus_type);
3557 Editor::edit_controls_button_release (GdkEventButton* ev)
3559 if (Keyboard::is_context_menu_event (ev)) {
3560 ARDOUR_UI::instance()->add_route ();
3566 Editor::track_selection_changed ()
3568 switch (selection->tracks.size()){
3572 set_selected_mixer_strip (*(selection->tracks.front()));
3576 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3577 (*i)->set_selected (false);
3578 if (mouse_mode == MouseRange) {
3579 (*i)->hide_selection ();
3583 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3584 (*i)->set_selected (true);
3585 if (mouse_mode == MouseRange) {
3586 (*i)->show_selection (selection->time);
3592 Editor::time_selection_changed ()
3594 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3595 (*i)->hide_selection ();
3598 if (selection->tracks.empty()) {
3599 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3600 (*i)->show_selection (selection->time);
3603 for (TrackSelection::iterator i = selection->tracks.begin(); i != selection->tracks.end(); ++i) {
3604 (*i)->show_selection (selection->time);
3610 Editor::region_selection_changed ()
3612 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3613 (*i)->set_selected_regionviews (selection->audio_regions);
3618 Editor::point_selection_changed ()
3620 for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
3621 (*i)->set_selected_points (selection->points);
3626 Editor::mouse_select_button_release (GdkEventButton* ev)
3628 /* this handles just right-clicks */
3630 if (ev->button != 3) {
3637 Editor::TrackViewList *
3638 Editor::get_valid_views (TimeAxisView* track, RouteGroup* group)
3641 TrackViewList::iterator i;
3643 v = new TrackViewList;
3645 if (track == 0 && group == 0) {
3649 for (i = track_views.begin(); i != track_views.end (); ++i) {
3653 } else if (track != 0 && group == 0 || (track != 0 && group != 0 && !group->is_active())) {
3655 /* just the view for this track
3658 v->push_back (track);
3662 /* views for all tracks in the edit group */
3664 for (i = track_views.begin(); i != track_views.end (); ++i) {
3666 if (group == 0 || (*i)->edit_group() == group) {
3676 Editor::set_zoom_focus (ZoomFocus f)
3678 if (zoom_focus != f) {
3680 vector<string> txt = internationalize (zoom_focus_strings);
3681 zoom_focus_selector.set_active_text (txt[(int)f]);
3682 ZoomFocusChanged (); /* EMIT_SIGNAL */
3689 Editor::ensure_float (Window& win)
3691 win.set_transient_for (*this);
3695 Editor::pane_allocation_handler (Gtk::Allocation &alloc, Gtk::Paned* which)
3697 /* recover or initialize pane positions. do this here rather than earlier because
3698 we don't want the positions to change the child allocations, which they seem to do.
3704 XMLNode* node = ARDOUR_UI::instance()->editor_settings();
3706 static int32_t done[4] = { 0, 0, 0, 0 };
3709 if ((geometry = find_named_node (*node, "geometry")) == 0) {
3710 width = default_width;
3711 height = default_height;
3713 width = atoi(geometry->property("x_size")->value());
3714 height = atoi(geometry->property("y_size")->value());
3717 if (which == static_cast<Gtk::Paned*> (&edit_pane)) {
3723 if (!geometry || (prop = geometry->property ("edit_pane_pos")) == 0) {
3725 snprintf (buf, sizeof(buf), "%d", pos);
3727 pos = atoi (prop->value());
3730 if ((done[0] = GTK_WIDGET(edit_pane.gobj())->allocation.width > pos)) {
3731 edit_pane.set_position (pos);
3737 Editor::detach_tearoff (Gtk::Box* b, Gtk::Window* w)
3739 if (tools_tearoff->torn_off() &&
3740 mouse_mode_tearoff->torn_off()) {
3741 top_hbox.remove (toolbar_frame);
3748 Editor::reattach_tearoff (Gtk::Box* b, Gtk::Window* w, int32_t n)
3750 if (toolbar_frame.get_parent() == 0) {
3751 top_hbox.pack_end (toolbar_frame);
3756 Editor::set_show_measures (bool yn)
3758 if (_show_measures != yn) {
3761 if ((_show_measures = yn) == true) {
3764 DisplayControlChanged (ShowMeasures);
3770 Editor::set_follow_playhead (bool yn)
3772 if (_follow_playhead != yn) {
3773 if ((_follow_playhead = yn) == true) {
3775 update_current_screen ();
3777 DisplayControlChanged (FollowPlayhead);
3783 Editor::toggle_xfade_active (Crossfade* xfade)
3785 xfade->set_active (!xfade->active());
3789 Editor::toggle_xfade_length (Crossfade* xfade)
3791 xfade->set_follow_overlap (!xfade->following_overlap());
3795 Editor::edit_xfade (Crossfade* xfade)
3797 CrossfadeEditor cew (*session, *xfade, xfade->fade_in().get_min_y(), 1.0);
3802 // cew.signal_delete_event().connect (mem_fun (cew, &ArdourDialog::wm_doi_event_stop));
3804 switch (cew.run ()) {
3805 case RESPONSE_ACCEPT:
3812 xfade->StateChanged (Change (~0));
3816 Editor::playlist_selector () const
3818 return *_playlist_selector;
3822 Editor::get_nudge_distance (jack_nframes_t pos, jack_nframes_t& next)
3826 ret = nudge_clock.current_duration (pos);
3827 next = ret + 1; /* XXXX fix me */
3833 Editor::end_location_changed (Location* location)
3835 ENSURE_GUI_THREAD (bind (mem_fun(*this, &Editor::end_location_changed), location));
3836 horizontal_adjustment.set_upper (location->end() / frames_per_unit);
3840 Editor::playlist_deletion_dialog (Playlist* pl)
3842 ArdourDialog dialog ("playlist deletion dialog");
3843 Label label (string_compose (_("Playlist %1 is currently unused.\n"
3844 "If left alone, no audio files used by it will be cleaned.\n"
3845 "If deleted, audio files used by it alone by will cleaned."),
3848 dialog.set_position (Gtk::WIN_POS_CENTER);
3849 dialog.get_vbox()->pack_start (label);
3851 dialog.add_button (_("Delete playlist"), RESPONSE_ACCEPT);
3852 dialog.add_button (_("Keep playlist"), RESPONSE_CANCEL);
3853 dialog.add_button (_("Cancel"), RESPONSE_CANCEL);
3855 switch (dialog.run ()) {
3856 case RESPONSE_ACCEPT:
3857 /* delete the playlist */
3861 case RESPONSE_REJECT:
3862 /* keep the playlist */
3874 Editor::audio_region_selection_covers (jack_nframes_t where)
3876 for (AudioRegionSelection::iterator a = selection->audio_regions.begin(); a != selection->audio_regions.end(); ++a) {
3877 if ((*a)->region.covers (where)) {
3886 Editor::prepare_for_cleanup ()
3888 cut_buffer->clear_audio_regions ();
3889 cut_buffer->clear_playlists ();
3891 selection->clear_audio_regions ();
3892 selection->clear_playlists ();
3896 Editor::init_colormap ()
3898 for (size_t x = 0; x < sizeof (color_id_strs) / sizeof (color_id_strs[0]); ++x) {
3899 pair<ColorID,int> newpair;
3901 newpair.first = (ColorID) x;
3902 newpair.second = rgba_from_style (enum2str (newpair.first), 0, 0, 0, 255);
3903 color_map.insert (newpair);
3908 Editor::transport_loop_location()
3911 return session->locations()->auto_loop_location();
3918 Editor::transport_punch_location()
3921 return session->locations()->auto_punch_location();
3928 Editor::set_layout_width(Gtk::Requisition *r)
3930 edit_controls_vbox.check_resize();
3931 int w = edit_controls_vbox.get_width();
3932 cerr << "set_layout_width() called w = " << w << endl;
3934 controls_layout.set_size_request (w, -1);
3938 Editor::layout_expose (GdkEventExpose* ex)
3940 cerr << "layout_expose() called" << endl;